我有一段代码在过去确实有效(至少我认为这样做是因为否则问题会在之前得到认可)。从几周开始,可能是自DST以来,它开始产生不正确的结果。
此代码段应生成一个NSDate对象,引用给定日期周的第一天00:00h。
NSCalendar *gregorianCalender = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *firstDayDate;
unsigned yearAndWeek = NSTimeZoneCalendarUnit | NSYearCalendarUnit | NSWeekCalendarUnit;
// retrieve the components from the current date
NSDateComponents *compsCurrentDate = [gregorianCalender components:yearAndWeek fromDate:date];
[compsCurrentDate setWeekday:2]; // Monday
[compsCurrentDate setHour:0];
[compsCurrentDate setMinute:0];
[compsCurrentDate setSecond:0];
// make a date from the modfied components
firstDayDate = [gregorianCalender dateFromComponents:compsCurrentDate];
NSLog(@"MONDAY: %@", firstDayDate);
今天是5月24日,所以最后一行应该打印类似
MONDAY: 2011-05-23 00:00:00 +0000
但它确实打印了以下内容
MONDAY: 2011-05-22 22:00:00 +0000
这显然是错误的。 5月22日是最后一个星期天。现在为了让事情变得奇怪,当我将setHour:0
更改为
[compsCurrentDate setHour:2];
我的猜测是,时区出了点问题。但是在苹果文档,谷歌和stackoverflow上花了半天后,我无法弄清楚问题是什么。也许我使用了错误的关键字,或者我是唯一一个遇到这个问题的人。
我们非常感谢每一条信息!请让我知道你在想什么!谢谢!
答案 0 :(得分:3)
由于没有人能够回答我继续我的研究并在NSData
的文档中发现了一个简单但致命的细节:description
方法在尝试打印NSDate
时调用默认情况下,NSString
使用“默认”NSLocale
来确定格式和时区。所以关于我的代码的一切都是正确的,我试图修复的真正问题是在其他地方,我已经在星期一做了这个...我应该RTFM更强烈;)
以下代码行打印时区的正确时间:
NSLog(@"MONDAY: %@", [firstDayDate descriptionWithLocale:[NSLocale systemLocale]]);
然而,在我的研究中,我发现一些有趣的片段基本上做同样的事情(虽然输出也是“错误的”,这就是为什么我不简单地取代我的)。考虑到所有这些因素,我的尝试工作有点崎岖不平。我找到的最简单和最强大的内容来自Apple文档本身,也可以在各种网站上找到:
/* VERSION FROM APPLE DOKU */
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Get the weekday component of the current date
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:date];
/*
Create a date components to represent the number of days to subtract from the current date.
The weekday value for Monday in the Gregorian calendar is 2, so subtract 2 from the number of days to subtract from the date in question. (If today's Sunday, subtract 0 days.)
*/
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
[componentsToSubtract setDay: 0 - ([weekdayComponents weekday] - 2)];
NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:date options:0];
/*
Optional step:
beginningOfWeek now has the same hour, minute, and second as the original date (today).
To normalize to midnight, extract the year, month, and day components and create a new date from those components.
*/
NSDateComponents *components =
[gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate: beginningOfWeek];
beginningOfWeek = [gregorian dateFromComponents:components];
NSLog(@"MONDAY: %@", [beginningOfWeek descriptionWithLocale:[NSLocale systemLocale]]);
最后,要完成此操作:如何计算当前周的最后日的代码段。
// reuse the "first day" to calculate the last day
NSDate *endOfLastWeek = [whateveryourobject andmethodiscalled];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
/*
endOfLastWeek now is monday in the current week so create date components to add one week to the current date
*/
NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init];
[componentsToAdd setWeek:1];
NSDate *endOfWeek = [gregorian dateByAddingComponents:componentsToAdd toDate:endOfLastWeek options:0];
NSLog(@"SUNDAY: %@", [endOfWeek descriptionWithLocale:[NSLocale systemLocale]]);