问题
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