0

The results of destinationDate and components differ. how do i solve this problem?

NSTimeZone* sourceTimeZone      = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];

NSDate* sourceDate              = [NSDate date];
NSInteger sourceGMTOffset       = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger destinationGMTOffset  = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval         = destinationGMTOffset - sourceGMTOffset;

NSDate* destinationDate         = [[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate];

NSCalendar *calendar            = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components    = [calendar components:(NSYearCalendarUnit  |
                                                        NSMonthCalendarUnit |
                                                        NSDayCalendarUnit   |
                                                        NSHourCalendarUnit  |
                                                        NSMinuteCalendarUnit|
                                                        NSSecondCalendarUnit) fromDate:destinationDate];

NSLog(@"%@", destinationDate); 
NSLog(@"%@", components);

2013-04-24 19:27:09 +0000

Calendar Year: 2013 Month: 4 Leap month: no Day: 25 Hour: 4 Minute: 27 Second: 9

realmasse
  • 523
  • 1
  • 6
  • 18
  • What is your problem here, description of date will be always in GMT. Its seems like your localTimeZone is 5 hours behind GMT. First log can be interpreted as 4:27 PM, it is the same shown in components – Anupdas Apr 24 '13 at 10:38
  • have you got the answer. – Balu Apr 24 '13 at 11:19
  • I'm struggling with a close issue, but I can't understand from your code what were you trying to achieve on the first place - could you please state this with few preliminary words? – Motti Shneor Oct 10 '21 at 06:34

2 Answers2

5

The date (destinationDate) is printed in GMT. However, the date components are not because the calendar is created with the local time zone.

If you try it with calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0] you will get the same result from both. Otherwise you'll get the difference added twice (first time by your code, second time by the calendar)

Actually, your code doesn't make a lot of sense. NSDate should never be modified by time zone because it doesn't hold any time zone information. A NSDate always represents a specific moment in time, independent on time zones. Transform the date only if you want to convert it to a string - and when you do, use NSCalendar or NSDateFormatter with the correct time zone set.

The following code is enough to print out the date with the system (default) time zone,

NSDate* sourceDate              = [NSDate date];
NSCalendar *calendar            = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components = [calendar components:(NSYearCalendarUnit  |
                                                     NSMonthCalendarUnit |
                                                     NSDayCalendarUnit   |
                                                     NSHourCalendarUnit  |
                                                     NSMinuteCalendarUnit|
                                                     NSSecondCalendarUnit) fromDate:destinationDate];

NSLog(@"%@", sourceDate); 
NSLog(@"%@", components);
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • could you please add to your explanation where the system timezone is (implicitly) applied? is it in the calendar? in the transformation to components? you only state you want a Gregorian calendar, you say nothing about time-zone... – Motti Shneor Oct 10 '21 at 06:40
  • @MottiShneor This is a very old answer and improved the wording a bit. The system timezone is stored in the calendar. It is used when you want to convert `Date`(a moment in time) to specific time components (relative to given timezone). – Sulthan Oct 10 '21 at 08:35
1

NSDateComponents always gives the date in the form of GMT so simply place like below you'l get the current date.

NSDateComponents *components    = [calendar components:(NSYearCalendarUnit  |
                                                            NSMonthCalendarUnit |
                                                            NSDayCalendarUnit   |
                                                            NSHourCalendarUnit  |
                                                            NSMinuteCalendarUnit|
                                                            NSSecondCalendarUnit) fromDate:[NSDate date]];

replace destinationDate with [NSDate date] .

output:

 2013-04-24 16:05:08 +0000

<NSDateComponents: 0x7e3e5b0>
    Calendar Year: 2013
    Month: 4
    Day: 24
    Hour: 16
    Minute: 5
    Second: 8
Balu
  • 8,470
  • 2
  • 24
  • 41
  • How did you conclude what OP wants? – Anupdas Apr 24 '13 at 10:48
  • he mensioned that destinationDate and components differ that's why i find out the problem in his code . – Balu Apr 24 '13 at 10:49
  • In his code he is creating a sourceDate as currentDate and using the interval to create a destinationDate which depending on the timeZone will be advanced or delayed. The question itself is very vague and why did you say to replace destinationDate with currentDate. Very confusing. – Anupdas Apr 24 '13 at 10:53