NSDateComponents 返回意外结果

Posted

技术标签:

【中文标题】NSDateComponents 返回意外结果【英文标题】:NSDateComponents returning unexpected result 【发布时间】:2017-03-03 16:13:01 【问题描述】:

我有这段代码

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。我预计会是 23,因为 UTC 中的发件人值显然包含等于 23 的天分量。

这和上午 12 点有什么关系吗?我在这里想念什么?

谢谢!

【问题讨论】:

它是 22,因为它以您自己的时区显示给您,而字符串显示的是 GMT/UTC/Zulu 中的日期。 考虑使用简单的NSDate *converted = [[NSCalendar currentCalendar] startOfDayForDate:sender.date]; @Rob 但我已经为 DateComponents 对象设置了 UTC。所以我希望它输出到日志的 UTC 值。 @vadian - 不,会有同样的问题。他需要设置他用于dateFromComponentsNSCalendartimeZone @ViktorKucera - 这不是组件的时区。这是您在提取重要组件时使用的日历的时区。 【参考方案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);

这将报告:

历年: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

显然,如果您不想显示时间,请使用 timeStyleNSDateFormatterNoStyle,但我包含它只是为了向您展示真正发生的事情。

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

我可能会建议澄清您的实际意图,为什么要这样做,我们也许可以提供更好的建议。

【讨论】:

你是英雄。非常感谢。

以上是关于NSDateComponents 返回意外结果的主要内容,如果未能解决你的问题,请参考以下文章

从 String 创建 DateComponents / NSDateComponents,反之亦然

NSDateComponents 不返回日期

NSDateComponents 给出奇怪的结果

使用 NSDateComponents 时无法返回目标日期

NSDateComponents weekOfYear 返回错误的日期

NSDateFormatter 和 NSDateComponents 为周数返回不同的值