NSDateComponents返回意外结果

时间:2017-03-03 16:13:02

标签: ios nsdatecomponents

我有这段代码

NSDateComponents *comps = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:sender.date];
[comps setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
NSDate *converted = [[NSCalendar currentCalendar] dateFromComponents:comps];

Sender.date 可以输出到控制台,如

  

1963-02-23 12:00:00 am +0000

但是UTC的 comps.day 给了我22.由于UTC中的发送者值明显包含等于23的日期成分,因此我预期为23。

这与上午12点有什么关系吗?我在这里错过了什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

这取决于你的意图。考虑:

NSString *string = @"1963-02-23 12:00:00 am +0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd hh:mm:ss a X";
NSDate *date = [formatter dateFromString:string];
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
NSDateComponents *comps = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
NSLog(@"%@", comps);

这将报告:

  

< NSDateComponents:0x610000140420>
      历年:1963年       月份:2       闰月:没有       日:23日

然后我可以将其转换为我们当地时区的日期:

NSDate *converted = [[NSCalendar currentCalendar] dateFromComponents:comps];
NSLog(@"%@", converted);

这将显示我当地时区的午夜(GMT-8),格林尼治标准时间早上8点:

  

1963-02-23 08:00:00 +0000

但是当我使用格式化程序向用户显示时,它会在我当地的时区向我显示:

NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
outputFormatter.dateStyle = NSDateFormatterMediumStyle;
outputFormatter.timeStyle = NSDateFormatterMediumStyle;
NSLog(@"%@", [outputFormatter stringFromDate:converted]);

这将显示:

  

1963年2月23日,上午12:00:00

显然,如果您不想显示时间,请使用timeStyle NSDateFormatterNoStyle,但我只是为了向您展示实际情况。

就个人而言,我发现以上所有内容都很复杂。我猜测原始字符串试图反映独立于任何特定时间和/或时区的日期(例如生日,周年纪念等),然后我认为如果省略时间,一切都会更容易来自原始字符串的时区信息,只需以yyyy-MM-dd格式捕获日期,然后将其保留。然后,这简化了上述代码中的大部分内容。

我可能会建议澄清您的实际意图,为什么您正在做您正在做的事情,我们可能会提供更好的建议。