dateByAddingComponents が夏時間を処理する方法の例外を理解するのに苦労しています。私は Apple Date and Time Programming Guide を読み、期待される dateByAddingComponents が DST の変更を考慮に入れていることを確認しました。ただし、DST の変更日には、うまくいきません。
コードは次のとおりです。
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 に 6 時間を追加して (私のユース ケースでは午前 12 時)、午前 6 時 (localTimeZone) になることを期待しています。
dateByAddingComponents の使用は DST 変更の前後の両方で機能しますが、11 月 3 日日曜日の DST 変更の日に、午前 5 時になります。
理論: 実際には 11 月 3 日の日曜日に午前 2 時が 2 回あるので、それを考慮する必要があるのでしょうか? その場合、DST の変更の実際の日を説明するロジックを記述し、必要に応じて daylightSavingTimeOffsetForDate を使用してオフセットを追加する必要があります。
私は何が欠けていますか???
編集: わかりました、今日が DST の変更であるかどうかを判断し、1 時間のオフセットを追加/削除することで問題を回避することにしました。ここで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;
}
}
//////