The language in the docs is a bit on the dry side, to be sure, and the similarity of the names is potentially confusing. I'll quote the
NSTimeZone docs here and try to explain them:
The time zone currently used by the system. If the current time zone cannot be determined, returns the GMT time zone.
This is the time zone which the device believes it is in; it is often set automatically, and would then correspond to the device's physical location, but if the user has explicitly set a particular time zone in the Settings App, that's what you'll get.
The default time zone for the current application. If no default time zone has been set, this method invokes
systemTimeZone and returns the system time zone.
Your application is allowed to set its own time zone, so that you can perform actions as if the device were in another zone, but without affecting the system time zone (and thereby other apps). The setting is performed with a call to
setDefaultTimeZone:. If you haven't done that, this call is identical to calling
An object that forwards all messages to the default time zone for the current application. The local time zone represents the current state of the default time zone at all times.
This is where it gets a little bit tricky.
localTimeZone gives you nearly the same result as
defaultTimeZone. The difference is that the specific
NSTimeZone instance you get from
localTimeZone will always reflect the setting you've made to the time zone within your app. You can call it once, save the result, and always get the current simulated time zone through that object, no matter the changes made. It is as if, when you use this
NSTimeZone instance, the framework is calling
defaultTimeZone for you, to be sure that you always get the current value.
Here's a couple of brief illustrations of the above. The
NSTimeZone object that you get back from
systemTimeZone represents the system time zone at the time you make the call. If you call
systemTimeZone again, even if the user has since changed the time zone, you will get the same one. Your app caches that value, and you have to ask the system to clear it with
resetSystemTimeZone to get the update.
// Say that device is in GMT originally
NSLog(@"%@", [NSTimeZone systemTimeZone]); // GMT
// User flies into Rome and iPhone changes the zone automatically
NSLog(@"%@", [NSTimeZone systemTimeZone]); // Still GMT
[NSTimeZone resetSystemTimeZone]; // Clear app's cache
NSLog(@"%@", [NSTimeZone systemTimeZone]); // Now GMT+2
A similar thing happens with
defaultTimeZone. When you call that method, you get an object that will always represent the same time zone, even if you later call
setDefaultTimeZone:. However, if you use the object you get from
localTimeZone, it will follow the change you make to the default time zone*.
// Say that defaultTimeZone is originally GMT
NSTimeZone * myDefaultTZ = [NSTimeZone defaultTimeZone];
NSTimeZone * myLocalTZ = [NSTimeZone localTimeZone];
[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithName:@"Etc/GMT-4"]];
NSLog(@"%@", myDefaultTZ); // Still gives GMT
NSLog(@"%@", [NSTimeZone defaultTimeZone]); // GMT-4, the new value
NSLog(@"%@", myLocalTZ); // Also the new value!
Apple seems to recommend using
with the localTimeZone class method, you can get a relative time zone object that decodes itself to become the default time zone on any computer on which it finds itself.
localTimeZone is still subject to the app-level cache of the system time zone. It only changes to follow your setting of the default time zone.