6

我知道有很多此类问题,但我没有找到适合我的案例的解决方案;我需要获取当前和正确的NSDate对象,而不是NSString!此代码返回错误的时间(+3 小时),因为我来自乌克兰。

NSDate *currentDate = [NSDate date];

如何从中获取当前NSDate对象NSDateFormatter?我只知道如何获取NSString,但我不需要它。

编辑:我正在使用此代码来比较 2NSDates使用NSCalendar对象,这里是代码:

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

并向components.hour我展示+3小时的差异

4

3 回答 3

9

NSDates 始终以 UTC 格式存储,实际上日期本身并不了解时区或周、月、年。它们只是一个时间点。

要查看您在地球表面上的位置的正确时间,您需要使用代表您的时间模型的 NSCalendar。您可以直接使用它并弄乱您的日期,或者创建一个 NSDateFormatter 保持日期不变,但根据您的需要调整它们的外观。

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];

NSLog(@"%@", [formatter stringFromDate: date1]);

结果是

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

回应评论:

试试这个代码作为测试

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]);

您会意识到,日、周、月和年的开始将根据您的本地时间进行调整,因为每个 NSLog 对中的第一个将为您提供 UTC 日期和您当地时区的第二个日期。


在您发布此代码的聊天中

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

所以问题是,日期字符串实际上不是来自 GMT,而是 EET(东欧时间)

尝试

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

但到目前为止,最优雅的解决方案是获取带有 UTC 偏移量的日期字符串,类似于2012-07-12 12:23:00 +0300如果有可能的话。
在这种情况下,您可以使用它来解析它
[dateFormat setDateFormat:@"yyyy-mm-dd HH:mm:ss Z"]; 并且不需要进一步的时区处理,因为格式化程序通过Z-specifier 知道偏移量。
另请注意,如果您未设置任何时区,则应使用设备的当前时区。如果用户始终与日期字符串中的时间处于同一时区,这也应该有效。但是如果用户离开了那个区域,或者你想让它在世界范围内工作,你应该使用我给你的解决方案之一。使用第二个(在日期字符串中指定时区)作为首选。

于 2012-07-12T15:03:35.390 回答
2

日期可能具有正确的值;也许您认为它不正确,因为当您记录它时它看起来是错误的?这是因为当您记录它时,它会以 UTC 显示日期。您可以使用 NSDateFormatter获取本地时区中的字符串。

于 2012-07-12T14:48:30.180 回答
2

如果第二个日期是 UTC,则答案是正确的。乌克兰目前比 UTC 时间早 3 小时,因此乌克兰的午夜 UTC 时间为 21:00。21:00 - 18:00 为 3 小时。因此,请检查您如何获得第二个日期。可能为它指定了错误的时区。

如果第一个日期真的是在乌克兰时间 18:00 通过

nowDate = [NSDate date];

那么第二个日期实际上是乌克兰时间 21:00,对应于 UTC 午夜。由于您声称现在是午夜,因此您必须使用 UTC 从字符串创建它 - 隐式或显式。向我们展示您是如何创建它的。

** 编辑 **

你在聊天时给我的代码是这样的:

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

第三行将时区设置为 GMT,这在所有意图和目的上都与 UTC 相同。您的日期格式化程序可能已初始化为设备的正确区域设置,因此您可能只需忽略该行。

于 2012-07-12T15:14:09.953 回答