63

I am getting from my server a string date in UTC time zone and I need to convert it to the local time zone.

MY CODE:

let utcTime = "2015-04-01T11:42:00.269Z"    
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(name: "UTC")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let date = dateFormatter.dateFromString(utcTime)
println("utc: \(utcTime), date: \(date)")

this prints -

utc: 2015-04-01T11:42:00.269Z, date: Optional(2015-04-01 11:42:00 +0000)

if I remove

dateFormatter.timeZone = NSTimeZone(name: "UTC") 

it prints

utc: 2015-04-01T11:42:00.269Z, date: Optional(2015-04-01 08:42:00 +0000)

my local time zone is UTC +3 and in the first option I get UTC in the second option I get UTC -3

I should get

utc: 2015-04-01T11:42:00.269Z, date: Optional(2015-04-01 14:42:00 +0000)

So how do I convert the UTC date format to local time?

Krunal
  • 77,632
  • 48
  • 245
  • 261
ilan
  • 4,402
  • 6
  • 40
  • 76

7 Answers7

78

Something along the following worked for me in Objective-C :

// create dateFormatter with UTC time format
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"]; 
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
NSDate *date = [dateFormatter dateFromString:@"2015-04-01T11:42:00"]; // create date from string

// change to a readable time format and change to local time zone
[dateFormatter setDateFormat:@"EEE, MMM d, yyyy - h:mm a"];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *timestamp = [dateFormatter stringFromDate:date];

I keep these two websites handy for converting different time formats: http://www.w3.org/TR/NOTE-datetime

http://benscheirman.com/2010/06/dealing-with-dates-time-zones-in-objective-c/

In Swift it will be:

// create dateFormatter with UTC time format
  let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
        dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?
        let date = dateFormatter.date(from: "2015-04-01T11:42:00")// create   date from string

        // change to a readable time format and change to local time zone
        dateFormatter.dateFormat = "EEE, MMM d, yyyy - h:mm a"
        dateFormatter.timeZone = NSTimeZone.local
        let timeStamp = dateFormatter.string(from: date!)
Krunal Nagvadia
  • 1,083
  • 2
  • 12
  • 33
c_rath
  • 3,618
  • 2
  • 22
  • 14
70

Try this Swift extension

Swift 4: UTC/GMT ⟺ Local (Current/System)

extension Date {

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

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

}


// Try it
let utcDate = Date().toGlobalTime()
let localDate = utcDate.toLocalTime()

print("utcDate - \(utcDate)")        //Print UTC Date
print("localDate - \(localDate)")     //Print Local Date
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • @Krunal, I like the simplicity of this, but when I run this: `public func runDatesExample() { let now = Date() let utcDate = now.toGlobalTime() let localDate = now.toLocalTime() print(now) //prints: 2020-04-08 00:31:17 +0000. //actual GMT/UTC right now print("utcDate - \(utcDate)") //prints: utcDate - 2020-04-08 06:31:17 +0000 print("localDate - \(localDate)") //prints: localDate - 2020-04-07 18:31:17 +0000 } ` I would have expected `utcDate` to be the same output as `now`. Am I missing something? – Herbal7ea Apr 08 '20 at 00:39
  • This does **NOT** return the time in the local timezone. It returns a Date object that represents a point in time with a certain offset from the current time. Then it prints that as a UTC time. To get a string representing the time in the local time zone, use DateFormatter. – fishinear Jul 04 '22 at 15:16
  • @fishinear - You are welcomed to edit and improve quality of this answer. – Krunal Jul 10 '22 at 04:24
  • @Krunal There is no need to do that, there are already multiple correct answers to the question. You are welcomed to remove the answer. – fishinear Jul 11 '22 at 11:49
27

Swift version of c_rath answer:

// create dateFormatter with UTC time format
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let date = dateFormatter.dateFromString("2015-04-01T11:42:00")

// change to a readable time format and change to local time zone
dateFormatter.dateFormat = "EEE, MMM d, yyyy - h:mm a"
dateFormatter.timeZone = NSTimeZone.localTimeZone() 
let timeStamp = dateFormatter.stringFromDate(date!)
TomazStoiljkovic
  • 808
  • 8
  • 21
  • 1
    Line 5 should read: dateFormatter.dateFormat = "EEE, MMM d, yyyy - h:mm a" and Line 6 should read: dateFormatter.timeZone = NSTimeZone.localTimeZone() – dotToString Dec 01 '15 at 01:07
9

I had to remove both z and milli seconds from c_rath solution. Works in swift 4.

extension String {
    func fromUTCToLocalDateTime() -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
        var formattedString = self.replacingOccurrences(of: "Z", with: "")
        if let lowerBound = formattedString.range(of: ".")?.lowerBound {
            formattedString = "\(formattedString[..<lowerBound])"
        }

        guard let date = dateFormatter.date(from: formattedString) else {
            return self
        }

        dateFormatter.dateFormat = "EEE, MMM d, yyyy - h:mm a"
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: date)
    }
}
Nidhin
  • 628
  • 7
  • 16
6

In Swift 3 this works well:

// create dateFormatter with UTC time format
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let date = dateFormatter.date(from: "2015-04-01T11:42:00")// create date from string

// change to a readable time format and change to local time zone
dateFormatter.dateFormat = "EEE, MMM d, yyyy - h:mm a"
dateFormatter.timeZone = TimeZone.current
let timeStamp = dateFormatter.string(from: date!)
FredFlinstone
  • 896
  • 11
  • 16
5

Expanding on what others have mentioned, here is a handy NSDate extension in Swift

import Foundation

extension NSDate {
    func ToLocalStringWithFormat(dateFormat: String) -> String {
        // change to a readable time format and change to local time zone
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = dateFormat
        dateFormatter.timeZone = NSTimeZone.localTimeZone()
        let timeStamp = dateFormatter.stringFromDate(self)

        return timeStamp
    }
}
Derek Hewitt
  • 775
  • 8
  • 16
3

Maybe you can try something like:

extension NSDate {
    convenience init(utcDate:String, dateFormat:String="yyyy-MM-dd HH:mm:ss.SSS+00:00") {
        // 2016-06-06 00:24:21.164493+00:00
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = dateFormat
        dateFormatter.timeZone = NSTimeZone(name: "UTC")

        let date = dateFormatter.dateFromString(utcDate)!
        let s = NSTimeZone.localTimeZone().secondsFromGMTForDate(date)
        let timeInterval = NSTimeInterval(s)

        self.init(timeInterval: timeInterval, sinceDate:date)
    }
}
Juan José Brown
  • 1,196
  • 1
  • 10
  • 7