dopcn
dopcn

Reputation: 4218

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

I know about NSDateComponents, but the thing is that some sort of week-based mechanism will mess up the result when the date is at the head or at the foot of a year.

For example:

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

Changing minimumDaysInFirstWeek doesn't make much difference either, and NSDateFormatter doesn't seem to be a better way.

Upvotes: 0

Views: 97

Answers (3)

gnasher729
gnasher729

Reputation: 52592

The "year" component will always return the correct year - based on the calendar that is being used! NSDate is logged in UTC, but the year is calculated using your local timezone. The date you gave was in 2015 in London where the use GMT (close to UTC), but in 2016 in other areas of the world. For example in Australia, where the New Year fireworks have long gone off at that time.

When you were looking at calendar weeks, that's a totally different and completely unrelated subject. 31st of December can be in the last week of one year, or the first week of the next week. But that's not returned by "year". It's returned by "yearForWeekOfYear".

Upvotes: 0

vadian
vadian

Reputation: 285140

Your code is perfectly fine. The po command displays the time description dependent on UTC while NSCalendar / NSDateComponents considers the current time zone.

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

and

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

are both the same moment in time.

If you have to deal always with UTC based dates set the time zone of the NSCalendar instance to UTC.

Upvotes: 0

Paulw11
Paulw11

Reputation: 114965

As @Larme indicated in his comment, your local timezone is affecting your result;

You have specified 4 pm on the 31 Dec 2015 at UTC. This is midnight on the 1st of January 2016 in your local timezone (UTC+8).

You can use the NSCalendar method componentsInTimeZone to get the year in a specific time zone:

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 

Upvotes: 3

Related Questions