2012-07-10 78 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