1

2013年7月8日編集:Appleには、Objective-Cのさまざまな日付と時刻のクラス、およびそれらを使用して時間の計算/操作を正しく実行する方法を理解するのに本当に役立つWWDCビデオの優れたセットがあります。

「一般的な日付と時刻の課題の解決策」(HDビデオSDビデオスライド(PDF))(WWDC 2013)
「カレンダー計算の実行」(SDビデオスライド(PDF))(WWDC 2011)

注:リンクには、無料のAppleDeveloperメンバーシップが必要です。

このSOの質問では、特定の日時(「次の日曜日の午後5時」)を計算する方法を尋ねました。私が得た答えのおかげで、私は次のコードを思いついた:

 - (NSDate *) toPacificTime
 {
     NSTimeZone *tz = [NSTimeZone timeZoneWithName:@"America/Los_Angeles"];
     NSInteger seconds = [tz secondsFromGMTForDate: self];
     return [NSDate dateWithTimeInterval: seconds sinceDate: self];
 }

 - (void)handleLiveShowReminders
 {
    NSDate *gmtNow = [NSDate date];
    NSDate *now = [gmtNow toPacificTime];

    NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"America/Los_Angeles"]];
    NSDateComponents *dateComponents = [calendar components:NSWeekdayCalendarUnit fromDate:now];
    NSInteger weekday = [dateComponents weekday];

    NSInteger daysTillNextSunday = 8 - weekday;

    int secondsInDay = 86400; // 24 * 60 * 60
    NSDate *nextSunday = [now dateByAddingTimeInterval:secondsInDay * daysTillNextSunday];

    NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:nextSunday];
    [components setHour:17];
    [components setMinute:00];
    [components setTimeZone:[NSTimeZone timeZoneWithName:@"America/Los_Angeles"]];
    NSDate *nextSunday5PM = [calendar dateFromComponents:components];

    warningInterval = -300;    // we want the notification to fire 5 minutes beforehand

    NSDate *alertDate = [nextSunday5PM dateByAddingTimeInterval:(NSTimeInterval)warningInterval];

    UILocalNotification* notifyAlarm = [[[UILocalNotification alloc] init] autorelease];
    if (notifyAlarm)
    {
        notifyAlarm.fireDate = alertDate;
        notifyAlarm.timeZone = [NSTimeZone timeZoneWithName:@"America/Los_Angeles"];    
        notifyAlarm.repeatInterval = NSWeekCalendarUnit;
        notifyAlarm.soundName = @"alert.aif";
        notifyAlarm.alertBody = @"LIVE SHOW REMINDER: The live show is about to start!";

        [[UIApplication sharedApplication] scheduleLocalNotification:notifyAlarm];
    }
 }

問題は、このコードは私には機能しますが、ESTのユーザーから受け取ったこのデバッグ出力からわかるように、PSTタイムゾーンにいない人には機能しないことです。

number of notifications = 1

Notification #1
===================
Body: LIVE SHOW REMINDER: The live show is about to start!
Details: <UIConcreteLocalNotification: 0x1d5f2200>
{fire date = Sunday, December 9, 2012, 4:30:00 PM Pacific Standard Time,
time zone = America/Los_Angeles (PST) offset -28800,
repeat interval = NSWeekCalendarUnit
repeat count = UILocalNotificationInfiniteRepeatCount,
next fire date = Sunday, December 9, 2012, 4:30:00 PM Eastern Standard Time,
user info = (null)}

私はここで何が間違っているのですか?

4

2 に答える 2

2

ロジックの問題が 1 つあります。時間間隔に 86,400 を追加するだけでは、希望どおりにならない可能性があります。たとえば、ユーザーがサマータイムを経験した場合、1 時間、または真夜中近くに発生した場合は 1 日ずれることになります。より良い方法は、NSCalendar に結果を求めることです。これには、ユーザーのローカル タイム ゾーンが考慮されます。

NSDate *start = yourDate;
NSDateComponents *oneDay = [NSDateComponents new];
[oneDay setDay:1];

NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *end = [cal dateByAddingComponents:oneDay toDate:start options:0];
于 2013-01-16T20:51:05.520 に答える
0

また、NSDate は UTC/GMT を基準としています。太平洋時間の場合に「調整」すると、完全な混乱が生じます。

于 2012-12-03T22:49:18.170 に答える