如何在所有情况下从 NSDate 获取正确的年份?

How to get the correct year from NSDate in all circumstances?

我知道 NSDateComponents,但问题是当日期在年头或年尾时,某种基于周的机制会弄乱结果。

例如:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit calendarUnit = NSYearCalendarUnit;
NSDateComponents *dateComponents = [calendar components:calendarUnit fromDate:self.date];

(lldb) po self.date
2015-12-31 16:00:00 +0000

(lldb) po dateComponents
<NSDateComponents: 0x12f4c83f0>
    Calendar Year: 2016

改变minimumDaysInFirstWeek也没有太大区别,NSDateFormatter似乎也不是更好的方法。

正如@Larme 在他的评论中指出的那样,您当地的时区正在影响您的结果;

您已指定 UTC 时间 2015 年 12 月 31 日下午 4 点。现在是 2016 年 1 月 1 日你当地时区 (UTC+8) 的午夜。

您可以使用NSCalendar方法componentsInTimeZone获取特定时区的年份:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSTimeZone *tz=[NSTimeZone timeZoneForSecondsFromGMT:0];
NSDateComponents *dateComponents = [calendar componentsInTimeZone:tz fromDate:self.date];
int year=dateComponents.year;  // This will be 2015 

您的代码非常好。 po 命令根据 UTC 显示时间描述,而 NSCalendar / NSDateComponents 考虑当前时区。

2015-12-31 16:00:00 +0000

2016-01-01 00:00:00 +0800

都是同一时刻。

如果您必须始终处理基于 UTC 的日期,请将 NSCalendar 实例的时区设置为 UTC

"year" 组件将始终 return 正确的年份 - 基于所使用的日历! NSDate 以 UTC 记录,但年份是使用您当地的时区计算的。您提供的日期是 2015 年在伦敦使用 GMT(接近 UTC),但在世界其他地区是 2016 年。比如在澳大利亚,那里的新年烟花早就放过了。

当您查看日历周时,这是一个完全不同且完全不相关的主题。 12 月 31 日可以是一年的最后一周,也可以是下一周的第一周。但这不是 "year" 编辑的 return。它由 "yearForWeekOfYear" 编辑 return。