iOS: Convert UTC NSDate to local Timezone

153,792

Solution 1

NSTimeInterval seconds; // assume this exists
NSDate* ts_utc = [NSDate dateWithTimeIntervalSince1970:seconds];

NSDateFormatter* df_utc = [[[NSDateFormatter alloc] init] autorelease];
[df_utc setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[df_utc setDateFormat:@"yyyy.MM.dd G 'at' HH:mm:ss zzz"];

NSDateFormatter* df_local = [[[NSDateFormatter alloc] init] autorelease];
[df_local setTimeZone:[NSTimeZone timeZoneWithName:@"EST"]];
[df_local setDateFormat:@"yyyy.MM.dd G 'at' HH:mm:ss zzz"];

NSString* ts_utc_string = [df_utc stringFromDate:ts_utc];
NSString* ts_local_string = [df_local stringFromDate:ts_utc];

// you can also use NSDateFormatter dateFromString to go the opposite way

Table of formatting string parameters:

https://waracle.com/iphone-nsdateformatter-date-formatting-table/

If performance is a priority, you may want to consider using strftime

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/strftime.3.html

Solution 2

EDIT When i wrote this I didn't know I should use a dateformatter which is probably a better approach, so check out slf's answer too.

I have a webservice that returns dates in UTC. I use toLocalTime to convert it to local time and toGlobalTime to convert back if needed.

This is where I got my answer from:

https://agilewarrior.wordpress.com/2012/06/27/how-to-convert-nsdate-to-different-time-zones/

@implementation NSDate(Utils)

-(NSDate *) toLocalTime
{
  NSTimeZone *tz = [NSTimeZone defaultTimeZone];
  NSInteger seconds = [tz secondsFromGMTForDate: self];
  return [NSDate dateWithTimeInterval: seconds sinceDate: self];
}

-(NSDate *) toGlobalTime
{
  NSTimeZone *tz = [NSTimeZone defaultTimeZone];
  NSInteger seconds = -[tz secondsFromGMTForDate: self];
  return [NSDate dateWithTimeInterval: seconds sinceDate: self];
}

@end

Solution 3

The easiest method I've found is this:

NSDate *someDateInUTC = …;
NSTimeInterval timeZoneSeconds = [[NSTimeZone localTimeZone] secondsFromGMT];
NSDate *dateInLocalTimezone = [someDateInUTC dateByAddingTimeInterval:timeZoneSeconds];

Solution 4

Swift 3+: UTC to Local and Local to UTC

extension Date {

    // Convert UTC (or GMT) to local time
    func toLocalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }

    // Convert local time to UTC (or GMT)
    func toGlobalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }
}

Solution 5

If you want local Date and time. Try this code:-

NSString *localDate = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];
Share:
153,792
Admin
Author by

Admin

Updated on July 08, 2022

Comments

  • Admin
    Admin almost 2 years

    How do I convert a UTC NSDate to local timezone NSDate in Objective C or/and Swift?

  • slf
    slf over 12 years
    probably worth mentioning you can use formatter to read dates back in from strings as well
  • Christopher Pickslay
    Christopher Pickslay over 12 years
    @DaveDeLong that's all well and good if you're just displaying the date as a string. But there are perfectly valid reasons for doing time zone conversions on a date. For example, if you want to default the date on a UIDatePicker using setDate:. Dates returned by web services often are UTC, but represent an event in the user's local time zone, like a TV listing. Passing in an unconverted date will display the incorrect time in the picker.
  • slf
    slf over 12 years
    You use this same method to read dates in from strings. Formatter does the conversion to and from UTC for you.
  • Diziet
    Diziet about 12 years
    Dates don't just matter for 'human consumption' they also matter for web services that might expect the date in the local format (summertime here in blighty).
  • Satyam
    Satyam almost 12 years
    Above code works perfectly for creating and handling NSStrings. But if want to create event in calendar using event kit so that event will be created as per local time zone, this code won't work. what changes do i've to make such that it works.....?
  • slf
    slf almost 12 years
    @Satyamsvv EKEvent has a startDate property, just set that
  • Glenn Maynard
    Glenn Maynard almost 12 years
    +22 for a wrong answer? @Dave: Nope. For example, aggregating events day by day in the user's local time.
  • Dave DeLong
    Dave DeLong almost 12 years
    @GlennMaynard it's not wrong; this is how you format a date for displaying it according to a different timezone. If you need to group dates by their local day, then you can get an NSCalendar, set its timezone to the one you care about, and start converting dates to NSDateComponents and comparing their day.
  • Glenn Maynard
    Glenn Maynard almost 12 years
    @Dave: It's plainly a wrong answer. The question asked how to get an NSDate; he didn't ask anything about formatting it. This answer is irrelevant to the question.
  • Dave DeLong
    Dave DeLong almost 12 years
    @GlennMaynard I disagree. The essence of this answer is that no conversion to the NSDate object is necessary, which is correct. Conversion to a timezone happens when the date is formatted, not when it is created, because dates don't have timezones.
  • Glenn Maynard
    Glenn Maynard almost 12 years
    @DaveDeLong: No, it only says how to convert a date to a string. Suggesting that the OP might want to make an NSCalendarDate instead would have been fine, but this answer didn't even hint at that.
  • Dave DeLong
    Dave DeLong almost 12 years
    @GlennMaynard ... except that NSCalendarDate is deprecated.
  • huggie
    huggie almost 12 years
    Also note this: oleb.net/blog/2011/11/… where it says "GMT != UTC"
  • JeremyP
    JeremyP over 11 years
    Don't do this. NSDates are always in UTC. This just confuses the issue.
  • Taylor Lafrinere
    Taylor Lafrinere over 11 years
    This can be very useful for the "webservice" case noted above. Let's say you have a server that stores events in UTC and the client wants to ask for all events that happened today. To do this, the client needs to get the current date (UTC/GMT) and then shift it by its timezone offset before sending it to the server.
  • Murray Sagal
    Murray Sagal about 11 years
    @JeremyP It would be more accurate to say that NSDates are always in GMT. From the NSDate class reference: "This method returns a time value relative to an absolute reference date—the first instant of 1 January 2001, GMT." Note the clear and specific reference to GMT. There is a technical difference between GMT and UTC but that is mostly irrelevant to the solutions most people are looking for.
  • Pawan Sharma
    Pawan Sharma over 10 years
    The best and most reusable solution for my problem :). Thanks a lot :)
  • bleeckerj
    bleeckerj almost 10 years
    This answer feels more portable. The answer below assumes the timezone is fixed at runtime whereas the answer above derives the timezone from the platform.
  • Sergey M
    Sergey M over 9 years
    Very helpful. One addition, secondsFromGMTForDate should be used if you want to account for daylight saving. See Apple Docs
  • aryaxt
    aryaxt about 9 years
    Would be nice to note where you copied the code from: agilewarrior.wordpress.com/2012/06/27/…
  • gyozo kudor
    gyozo kudor about 9 years
    @aryaxt you are right, i'm sorry. I honestly didn't remember where I copied from when I posted the answer.
  • Daniel Ran Lehmann
    Daniel Ran Lehmann almost 9 years
    I was looking for an answer like this that didn't require you to set an nsdateformatter! thanks @gyozokudor
  • alex-i
    alex-i over 8 years
    This will probably cause some issues around daylight savings - the offset used in transforming to local may be different than the one used in transforming back into global.
  • Volomike
    Volomike over 8 years
    Great answer! This will grab the current date. An adaptation of this which uses a date string would be to replace [NSDate date] with [NSDate dateWithNaturalLanguageString:sMyDateString].
  • NiKKi
    NiKKi about 8 years
    @slf How can the string date for EST be made to NSDate for EST?
  • slf
    slf about 8 years
    @NiKKi I think you are looking for the lowercase z refer to the links I added to the post
  • lkraider
    lkraider over 7 years
    This fails to take into account DST changes.
  • Fadi Abuzant
    Fadi Abuzant over 6 years
    Not work for me, my local time is +3 and this code return +2
  • Mitesh
    Mitesh almost 4 years
    It will convert any time zone to UTC or vice versa?