我很難理解dateByAddingComponents如何處理夏令時的例外情況。我已閱讀了Apple日期和時間編程指南,並預計dateByAddingComponents將DST更改考慮在內。但是,在DST更改日期,它不適合我。NSCalendar dateByAddingComponents如何處理夏時制錯誤
下面的代碼:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *midnight = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:self.currentDate];
midnight.hour = 0;
midnight.minute = 0;
midnight.second = 0;
NSDate *startDate = [gregorian dateFromComponents:midnight];
NSDateComponents *offSetComponents = [[NSDateComponents alloc] init];
[offSetComponents setDay:1];
NSDate *endDate = [gregorian dateByAddingComponents:offSetComponents toDate:startDate options:0];
//Calculate start time from config (hours/min from seconds)
int startTimeInMinutes = self.club.clubConfiguration.startTime.integerValue;
int startTimeHours = startTimeInMinutes/60;
int startTimeMins = startTimeInMinutes % 60;
NSLog(@"---- startTimeHours %i", startTimeHours);
NSLog(@"---- startTImeMins %i", startTimeMins);
NSDateComponents *offSetComponents2 = [[NSDateComponents alloc] init];
[offSetComponents2 setHour:startTimeHours];
[offSetComponents2 setMinute:startTimeMins];
NSDate *firstTeeTime = [gregorian dateByAddingComponents:offSetComponents2 toDate:startDate options:0];
說明: 我從我用它來計算firstTeeTime服務器獲取一個startTimeInMinutes。例如,我希望將startDate(12am在我的用例中)添加6小時,並獲得6am(localTimeZone)。
使用dateByAddingComponents可以在DST更改之前和之後使用,但是在DST更改日的11月3日星期日,我得到了5am。
理論:由於11月3日星期日實際上有2個2點,我可能要解釋這個問題嗎?如果是這種情況,我不得不編寫一些邏輯來說明DST更改的實際日期,並在適當的情況下使用daylightSavingTimeOffsetForDate添加偏移量。
我失蹤了什麼?
編輯:好吧,我決定通過確定今天是否是DST更改並添加/刪除小時偏移量來解決問題。感覺有點像我在這裏錯過關於NSDate的東西,但是,它的工作原理。希望這可以幫助別人整天早上撓頭。
解決代碼:
////// Work around for DST
NSTimeZone *currentZone = [gregorian timeZone];
NSDate *dstTransitionDate = [currentZone nextDaylightSavingTimeTransitionAfterDate:startDate];
NSTimeInterval dstOffset = [currentZone daylightSavingTimeOffsetForDate:endDate];
NSDateComponents *startDateComponents = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:startDate];
NSDateComponents *dstTransitionDateComponents = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:dstTransitionDate];
int offset = 0;
if ([startDateComponents year] == [dstTransitionDateComponents year] &&
[startDateComponents month] == [dstTransitionDateComponents month] &&
[startDateComponents day] == [dstTransitionDateComponents day])
{
if (dstOffset > 0){
offset = -1;
} else {
offset = 1;
}
}
//////