Objective C NSCalendar dateFromComponents not handling week 53

拥有回忆 提交于 2019-12-25 05:36:33

问题


The following code calculates the previous week number from a given week when passed year and week.

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:year];
[components setWeek:NSWeekCalendarUnit];
[components setWeekOfYear:(week-1)]; //Get the previous week
[components setWeekday:2]; //Monday
[components setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [calendar dateFromComponents:components];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyyww"];
NSString *newRevision = [formatter stringFromDate:date];

I was surprised that this handled cases like 201101 (which gives 201052), but it does not correctly handle years where there are 53 weeks. For example, for 201601 it returns 201552 instead of 201153. (At least it should return 201153 according to http://en.wikipedia.org/wiki/ISO_week_date anyway.)

Am I doing something wrong? I have traced through to make sure the inputs are correct.


回答1:


You have the NSGregorianCalendar selected for your calendar. Try using the NSISO8601Calendar

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSISO8601Calendar];



回答2:


We ended up working around the issue with a bit of hack. From the wikipedia link in the question, we got the list of all years with 53 weeks for the next 400 years and hard coded them in (with judicious comments and the 'correct' solution included).

if (week == 1)
{
    year = year - 1;
    week = 52;
    if (year == 2004 || year == 2009 || year == 2015 || year == 2020 || year == 2026 || year == 2032 || year == 2037 || year == 2043 || year == 2048 || year == 2054 || year == 2060 || year == 2065 || year == 2071 || year == 2076 || year == 2082 || year == 2088 || year == 2093 || year == 2099 || year == 2105 || year == 2111 || year == 2116 || year == 2122 || year == 2128 || year == 2133 || year == 2139 || year == 2144 || year == 2150 || year == 2156 || year == 2161 || year == 2167 || year == 2172 || year == 2178 || year == 2184 || year == 2189 || year == 2195 || year == 2201 || year == 2207 || year == 2212 || year == 2218 || year == 2224 || year == 2229 || year == 2235 || year == 2240 || year == 2246 || year == 2252 || year == 2257 || year == 2263 || year == 2268 || year == 2274 || year == 2280 || year == 2285 || year == 2291 || year == 2296 || year == 2303 || year == 2308 || year == 2314 || year == 2320 || year == 2325 || year == 2331 || year == 2336 || year == 2342 || year == 2348 || year == 2353 || year == 2359 || year == 2364 || year == 2370 || year == 2376 || year == 2381 || year == 2387 || year == 2392 || year == 2398)
    {
        week = 53;
    }
}
else
{
    week = week-1;
}

It's not ideal, but it will do the job until either Apple implements ISO 8601 or until the year 2404.




回答3:


For the case Jan 1st 2016 you should get:

  • week = 53
  • year = 2015

When you're printing your answer use "YYYY" instead of "yyyy".

  • YYYY - gives you year of the week
  • yyyy - gives you year of the date


来源:https://stackoverflow.com/questions/8716649/objective-c-nscalendar-datefromcomponents-not-handling-week-53

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!