2012-07-10 50 views
0

我正在使用此方法将月份和年份转换为等于给定年份中最后一天的日期。从核心数据检索NSDate时发生的时区问题

+ (NSDate*)endOfMonthDateForMonth:(int)month year:(int)year 
{ 
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSDateComponents *comps = [[NSDateComponents alloc] init]; 
    comps.year = year; 
    comps.month = month; 

    NSDate *monthYearDate = [calendar dateFromComponents:comps]; 

    // daysRange.length will contain the number of the last day of the endMonth: 
    NSRange daysRange = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:monthYearDate]; 
    comps.day = daysRange.length; 
    comps.hour = 0; 
    comps.minute = 0; 
    comps.second = 0; 
    [comps setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; 
    [calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; 
    [calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; 
    NSDate *endDate = [calendar dateFromComponents:comps]; 
    return endDate; 
} 

我想要的日期有时间是00:00:00成分,这就是为什么我已经设置了时区GMT 0和几分钟,几小时日期组件和秒0的返回日期从该方法是正确的,并具有从00:00:00的时间组件。

这是我如何保存日期到核心数据:

NSDate *endDate = [IBEstPeriod endOfMonthDateForMonth:endMonth year:endCalYear]; 
[annualPeriod setEndDate:endDate]; 

检索数据,并将其NSLogging调试器控制台后,我得到的日期一样2008-12-30 23:00:00 +0000与时间分量= 0

为什么组件现在改变了? 不应该停留在00:00:00吗?

这里我错了什么?

谢谢!

回答

3

您只需在创建日历后设置日历时区。

添加为你的函数的第二行:

calendar.timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; 

然而,一个更简单的方式做到这一点会是这样:

- (NSDate*)endOfMonthDateForMonth:(int)month year:(int)year 
{ 
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    calendar.timeZone  = [NSTimeZone timeZoneWithName:@"UTC"]; 

    NSDateComponents *comps = [[NSDateComponents alloc] init]; 
    comps.year    = year; 
    comps.month    = month+1; 
    comps.day    = 0; 

    NSDate *monthYearDate = [calendar dateFromComponents:comps]; 
    return monthYearDate; 
} 

结果:

NSLog(@"%@",[self endOfMonthDateForMonth:12 year:2010]); 
// Output: 2012-07-10 12:30:05.999 Testing App[16310:fb03] 2010-12-31 00:00:00 +0000 

这通过将日期设置为下个月的“第0天”来工作,这与本月的最后一天相同。 (这与从下个月的第一天开始减去相同的事情)注意,这是可行的,因为comps被允许“溢出”(或者在这种情况下是“下溢”)并且dateFromComponents:自动进行数学运算。

+0

我试过你的代码,但我仍然有同样的问题:我得到'2010-12-30 23:00:00 +0000 '而不是'2010-12-31'。 – AlexR 2012-07-10 16:20:22

+0

你确定你没有在其他地方更改日期吗?我只是更新了我的答案,以显示我在运行时收到的实际结果。 – lnafziger 2012-07-10 16:31:56

+0

有没有可能我需要设置不同的本地时区(我在本地时区(GMT +2 =德国),但在创建日期时使用了GMT + 0。 – AlexR 2012-07-10 16:37:13

1

两件事情来看待:

  1. 试试您设定的时间组件之前设置的时区comps。我没有测试过,但可能是NSDateComponents调整小时,以便在设置时区时保持与GMT相对的相同时间。

  2. 看看当你从核心数据存储中读回日期时你是如何解释日期的。

+0

谢谢你的帮助,迦勒!我尝试了你的建议1.不幸的是没有成功。关于2:我只是记录日期而没有任何转换。看来,存储在核心数据中的日期正在被读取时(我在格林威治标准时间+2:00)在我当前的时区转换。我怎样才能避免这种转换,这实际上改变了一天?我不在乎时间部分,我只需要日期,在所有时区中必须保持不变。 – AlexR 2012-07-10 15:48:51

+0

NSDate存储独立于时区的日期信息。为了理解NSDate,您应该使用日期格式化程序来显示日期,以便您可以自己指定时区。我怀疑当你记录一个日期时,NSDate的'-description'方法可能使用当前时区,但日期本身不会改变(日期是不可变的)。因此,如果您想在GMT中显示日期,请再次使用日期格式化程序。 – Caleb 2012-07-10 16:22:37

+0

我不确定NSDate的-description方法是否真的使用当前时区,因为我使用类似的代码来生成一个NSDate:'NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@“en_US_POSIX”]]; [dateFormatter setDateFormat:@“yyy-MM-dd”]; [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; NSDate * date = [dateFormatter dateFromString:[csvLineItems objectAtIndex:0]];'从字符串解析。 – AlexR 2012-07-10 16:28:40