NSDate date method returns incorrect result

I know that there are many questions of this type, but I have not found a solution for my business; I need to get the current and correct NSDate object, not an NSString ! This code returns the wrong time (+3 hours), because I am from Ukraine.

 NSDate *currentDate = [NSDate date]; 

How to get current NSDate object from NSDateFormatter ? I only know how to get NSString , but I don't need it.

EDIT: I use this code to compare 2 NSDates using an NSCalendar object, here is the code:

 NSCalendar *calendar = [NSCalendar currentCalendar]; NSUInteger unitFlags = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; NSDateComponents *components = [calendar components:unitFlags fromDate:nowDate toDate:endDate options:0]; 

and components.hour shows me the difference of 3 hours

+4
source share
3 answers

NSDates are always stored in UTC, in fact the dates themselves do not know anything about time zones or weeks, month, years. This is just a point in time.

To see the correct time for your position on Earth, you need to take the NSCalendar, which represents your time model in your account. You can use it directly and mess with your dates, or create an NSDateFormatter that will leave the dates intact, but tailor their appearance to your needs.

 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterFullStyle]; [formatter setTimeStyle:NSDateFormatterFullStyle]; NSLog(@"%@", [formatter stringFromDate: date1]); 

leads to

 Thursday, July 12, 2012, 4:36:07 PM Central European Summer Time 

in response to the comment:

try this code as a test

 NSDate *now = [NSDate date]; NSDate *startOfToday = nil; NSDate *startOfThisWeek = nil; NSDate *startOfThisMonth = nil; NSDate *startOfThisYear = nil; [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startOfToday interval:NULL forDate:now]; [[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startOfThisWeek interval:NULL forDate:now]; [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startOfThisMonth interval:NULL forDate:now]; [[NSCalendar currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startOfThisYear interval:NULL forDate:now]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterFullStyle]; [formatter setTimeStyle:NSDateFormatterFullStyle]; NSLog(@"%@", now); NSLog(@"%@", [formatter stringFromDate:now]); NSLog(@"%@", startOfToday); NSLog(@"%@", [formatter stringFromDate:startOfToday]); NSLog(@"%@", startOfThisWeek); NSLog(@"%@", [formatter stringFromDate:startOfThisWeek]); NSLog(@"%@", startOfThisMonth); NSLog(@"%@", [formatter stringFromDate:startOfThisMonth]); NSLog(@"%@", startOfThisYear); NSLog(@"%@", [formatter stringFromDate:startOfThisYear]); 

You will understand that the beginning of the day, week, month and year will be adjusted to your local time, since the first of each pair of NSLog will give you a date in UTC, and the second in your local time zone.


you posted this code in the chat

 NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm"]; [dateFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; NSDate *date = [dateFormat dateFromString:dateString]; [dateFormat release]; 

so the problem is that the datestring is actually not from GMT, but EET (Eastern European Time)

try

 [dateFormat setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"EET"]]; 

but the most elegant solution would be to get a datestring with an offset to UTC, like 2012-07-12 12:23:00 +0300 , if possible, as much as possible.
In this case, you can parse it with [dateFormat setDateFormat:@"yyyy-mm-dd HH:mm:ss Z"]; and do not need further time zone processing, since the formatter knows the offset using the Z specifier.
Also note that if you do not set the time zone, you should use the device current. If the user is always in the same time zone as the time from the date string, this should work too. But if the user leaves this zone, or you want it to work around the world, you must use one of the solutions that I gave you. With the second (specifying the timezone c-in datestring) as preferred.

+9
source

The date probably has the correct meaning; maybe you think this is wrong because it looks wrong when you register it? This is because when you register it, it shows the date in UTC. You can get the string in your local time zone using NSDateFormatter .

+1
source

The answer is correct if the second date is specified in UTC. Currently, Ukraine is 3 hours ahead of UTC, and at 21:00 UTC - at 21:00. 21:00 - 18:00 - 3 hours. So check how you get the second date. Perhaps the wrong time zone is defined for it.

If the first date was really created at 18:00 in Ukraine through

 nowDate = [NSDate date]; 

then the second date is actually 21:00 in Ukraine, which corresponds to midnight UTC. Since you are claiming that it is midnight, you must use UTC to create it from a string - either implicitly or explicitly. Show us how you created it.

** EDIT **

The code you gave me in the chat is:

 NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm"]; [dateFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; NSDate *date = [dateFormat dateFromString:dateString]; [dateFormat release]; 

The third line sets the GMT time zone, which is identical to UTC for all purposes. Your date format is probably initialized with the correct locale for the device, and maybe you can just leave this line.

+1
source

All Articles