2012-12-03 103 views
1

編輯07/08/13:Apple擁有一套出色的WWDC視頻,這些視頻確實幫助我瞭解Objective-C中的各種日期和時間類,以及如何正確執行時間計算/操作。(iOS,Objective-C)在計算日期/時間時處理不同的時區

「解決共同日期和時間挑戰」(HD videoSD videoslides (PDF))(WWDC 2013)
「執行日曆計算」(SD videoslides (PDF))(WWDC 2011)

注意:鏈接需要免費的Apple Developer會員資格。

this SO question,我問我如何去計算某個日期和時間(「下週五下午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]; 
    } 
} 

的問題在於,雖然這個代碼工作對我來說,它不工作的人誰在PST時區不是,可以看出通過我在EST收到的一個用戶的調試輸出:

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)} 

我在做什麼錯在這裏?

+0

嘿,你有能力找出解決方案嗎? – gdubs

回答

0

而NSDate是相對於UTC/GMT。如果在太平洋時間進行「調整」,則會造成完全混淆。

2

您的邏輯有一個問題,只是在您的時間間隔中添加86,400可能不是您想要的。例如,如果用戶體驗日光節約,那麼如果發生在午夜附近,您將會關閉一小時,甚至一天。更好的方法是向NSCalendar詢問結果,該結果考慮了用戶本地時區。

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

NSCalendar *cal = [NSCalendar currentCalendar]; 
NSDate *end = [cal dateByAddingComponents:oneDay toDate:start options:0];