UILocalNotifications and time zones

By · Published · apple, cocoa, ios

Here's a tip when dealing with UILocalNotifications.

If you want to schedule a notification for a specific time using fireDate, you need to apply a timeZone to the UILocalNotification object. Otherwise, iOS will intepret this as an absolute, countdown-based date based on GMT.

To put it another way, suppose you have this code:

NSDate *date = [NSDate date];
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:date];
UILocalNotification *notification = [[UILocalNotification alloc] init];

// If hour has already passed, schedule for tomorrow.
if (components.hour >= 8) {
    components.day += 1;
}

// Schedule for 8
components.hour = 8;
components.minute = 0;

// Schedule it to repeat every day and give it a body.
notification.alertBody = @"Hello!";
NSDate *fireDate = [[NSCalendar currentCalendar] dateFromComponents:components];
notification.fireDate = fireDate;
notification.repeatInterval = NSDayCalendarUnit;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

You will get a local notification at 8am in your current timezone, just like you would expect. But say you're in Huntsville (in the Central timezone), and you fly to Utah (in the Mountain time zone). You now get a local notification at 7am. What?

In the AppleDoc for UILocalNotification, we find this:

The date specified in fireDate is interpreted according to the value of this property. If you specify nil (the default), the fire date is interpreted as an absolute GMT time, which is suitable for cases such as countdown timers. If you assign a valid NSTimeZone object to this property, the fire date is interpreted as a wall-clock time that is automatically adjusted when there are changes in time zones; an example suitable for this case is an an alarm clock.

So unless you specify a timezone on your UILocalNotification object, you will get a repeating countdown timer. Which is a little odd from a developer standpoint. This could be implemented a bit more clearly by Apple.

To fix this, you have to apply a timezone to the local notification itself.

// Have to set a timezone or this defaults to a coundown based timer. This
// should update based on the current user's timezone.
notification.timeZone = [NSTimeZone defaultTimeZone];

According to the docs, this should update automatically if the user's timezone changes.

( Comments )

Did something I wrote help you out?

That's great! I don't earn any money from this site - I run no ads, sell no products and participate in no affiliate programs. I do this solely because it's fun; I enjoy writing and sharing what I learn.

All the same, if you found this article helpful and want to show your appreciation, here's my Amazon.com wishlist.


Related Posts

NSHTMLTextDocumentType is Slow

Wallpaper Swapping with Hammerspoon


comments powered by Disqus