Objective C NSCalendar dateFromComponents 不处理第 53 周

发布于 2024-12-23 17:53:37 字数 960 浏览 2 评论 0原文

以下代码根据经过yearweek 计算给定周的前一周编号。

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];

令我惊讶的是,它处理了像 201101(给出 201052)这样的情况,但它不能正确处理有 53 周的年份。例如,对于 201601,它返回 201552 而不是 201153。(根据 http:// 至少应该返回 201153无论如何,en.wikipedia.org/wiki/ISO_week_date。)

我做错了什么吗?我已经进行了追踪以确保输入是正确的。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉城已无爱 2024-12-30 17:53:37

您已为日历选择了 NSGregorianCalendar。尝试使用 NSISO8601Calendar

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

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

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSISO8601Calendar];
站稳脚跟 2024-12-30 17:53:37

我们最终通过一些技巧解决了这个问题。从问题中的维基百科链接中,我们获得了接下来 400 年的所有年份的列表,其中包含 53 周,并将它们硬编码进去(包含明智的评论和“正确”的解决方案)。

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;
}

它并不理想,但在 Apple 实施 ISO 8601 或 2404 年之前它可以完成这项工作。

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.

凹づ凸ル 2024-12-30 17:53:37

对于 2016 年 1 月 1 日的情况,您应该得到:

  • 周 = 53
  • 年 = 2015

当您打印答案时,请使用“YYYY”而不是“yyyy”。

  • YYYY - 给出星期几
  • yyyy - 给出日期年份

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文