27

I make an http get request to a server and get back a json object with a date string like this:

{
    name = "Place1";
    temperature = 79;
    humidity = 68;
    reported_at = "2013-07-21T19:32:00Z";
}

I want to format the reported_at key so I can display a readable date and time to the user.

This is the swift code I am trying which keeps returning nil, as it cannot format the date.

    var str = "2013-07-21T19:32:00Z"

    var dateFor: NSDateFormatter = NSDateFormatter()
    dateFor.dateFormat = "yyyy-MM-dd'T'HH:mm:ss:SSS"

    var yourDate: NSDate? = dateFor.dateFromString(str)

    println(yourDate)

How can I format this date and time with Swift correctly? I want to display the date and time to the user so they can know when the reading was taken.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nearpoint
  • 7,202
  • 13
  • 46
  • 74

6 Answers6

33

Nowadays (September 2017) in Swift 4 there are smarter ways to decode ISO8601:

  • ISO8601DateFormatter

    let str = "2013-07-21T19:32:00Z"
    let formatter = ISO8601DateFormatter()
    let yourDate = formatter.date(from: str)
    
  • JSONDecoder

    struct Place : Decodable {
    
        let name : String
        let temperature : Int
        let humidity : Int
        let reportedAt : Date
    
    }
    
    let json = """
    {"name" : "Place1", "temperature" : 79, "humidity" : 68, "reported_at" : "2013-07-21T19:32:00Z"}
    """
    let data = Data(json.utf8)
    
    let decoder =  JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let place = try! decoder.decode(Place.self, from: data)
    
vadian
  • 274,689
  • 30
  • 353
  • 361
28

Use the following string format to convert a server string into a Date

dateFor.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
Community
  • 1
  • 1
Zell B.
  • 10,266
  • 3
  • 40
  • 49
  • DO NOT quote the `Z`. That will give the wrong result. – rmaddy Feb 26 '15 at 19:17
  • @rmaddy just tried it and not quoting 'Z' is giving me a wrong – Zell B. Feb 27 '15 at 10:26
  • @zellb I can assure you that quoting the `Z` will give the wrong result. If you think you get the wrong result when you don't quote the `Z` then you are doing something else incorrectly or misunderstanding the result. – rmaddy Feb 27 '15 at 15:02
  • @rmaddy On my playground `var str = "2015-02-27T11:24:00Z" var dateFor: NSDateFormatter = NSDateFormatter() dateFor.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" var yourDate: NSDate? = dateFor.dateFromString(str)` is giving me {Some "Feb 27, 2015, 12:24 PM"} while with quote Z is giving {Some "Feb 27, 2015, 11:24 AM"} which is correct based on my string – Zell B. Feb 27 '15 at 15:41
  • 3
    The date `2015-02-27T11:24:00Z` is at 11:24am in GMT time (that's what the `Z` means in the date string). You must live in the GMT+1 timezone. Correct? If you don't quote the `Z`, the date string is properly interpreted in GMT time. If you do quote the `Z`, the date string is incorrectly interpreted in local time. – rmaddy Feb 27 '15 at 15:46
  • 4
    "yyyy-MM-dd'T'HH:mm:ssX" should be the correct date format – Leo Dabus Sep 27 '15 at 22:30
  • no matter what I do... always nil. what swift was working v1 or v2? – user1019042 Apr 26 '16 at 08:28
  • @user1019042 this answer was for swift 1.2 but still can you post your string date ? – Zell B. Apr 26 '16 at 09:00
4

If you are using SwiftDate (you probably should!) simply use:

Serialize:

let date:NSDate = ....
let dateInRegion = DateInRegion( absoluteTime: date )
let serializedString:String = dateInRegin.toString( .ISO8601Format( .Full ))!

Deserialize:

let serializedDate:String = "2016-03-01T22:10:55.200Z"
let date:NSDate? = serializedDate.toDateFromISO8601()
LightMan
  • 3,517
  • 31
  • 31
Marchy
  • 3,334
  • 5
  • 37
  • 27
1

Here is my answer using extension in Swift4.

extension String {
  func toDate(dateFormat: String) -> Date? {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = dateFormat

    let date: Date? = dateFormatter.date(from: self)
    return date
}

Simple Usage

let str = "2013-07-21T19:32:00Z";
let dateStr = str.toDate(dateFormat: "yyyy-MM-dd'T'HH:mm:ssZ")

Also, Check dateFormat that you want from here. ISO 8601

Changnam Hong
  • 1,669
  • 18
  • 29
  • In Swift 4 I'd prefer `ISO8601DateFormatter` or decode the JSON directly with `JSONDecoder` – vadian Sep 30 '17 at 06:55
  • @vad Yes, Using `JSONDecoder` will be better. But, `ISO8601DateFormatter`, it does not support milliseconds. https://stackoverflow.com/questions/41847672/iso8601dateformatter-doesnt-parse-iso-date-string – Changnam Hong Sep 30 '17 at 07:07
  • There are no milliseconds in the question and in macOS 10.13 / iOS 11 milliseconds are supported. – vadian Sep 30 '17 at 07:14
0

For Converting JSON String to Date & Time in Swift 3.0 Use Below Code:-

    let timeinterval : TimeInterval = (checkInTime as! NSString).doubleValue
    let dateFromServer = NSDate(timeIntervalSince1970:timeinterval)
    print(dateFromServer)
    let dateFormater : DateFormatter = DateFormatter()
    //dateFormater.dateFormat = "dd-MMM-yyyy HH:mm a"  // 22-Sep-2017 14:53 PM
    dateFormater.dateFormat = "dd-MMM-yyyy hh:mm a"   // 22-Sep-2017 02:53 PM
    print(dateFormater.string(from: dateFromServer as Date))

where checkInTimewill be your String.Hope it will help someone

Dilip Tiwari
  • 1,441
  • 18
  • 31
0

In Swift 5 you can do something like this (This is a variation of vadian's answer) in case you have a custom date string that is not in 'iso8601':

struct Place : Decodable {

    let name : String
    let temperature : Int
    let humidity : Int
    let reportedAt : Date

}

let json = """
{"name" : "Place1", "temperature" : 79, "humidity" : 68, "reported_at" : "2021-05-02 06:00"}
"""
let data = Data(json.utf8)

//FORMAT DATE
let dateFormatter = DateFormatter()
//Force dateFormatter to be always 24h
dateFormatter.setLocalizedDateFormatFromTemplate("HH:mm a")
dateFormatter.amSymbol = ""
dateFormatter.pmSymbol = ""
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"

let decoder =  JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
decoder.keyDecodingStrategy = .convertFromSnakeCase
let place = try! decoder.decode(Place.self, from: data)
Pietro Messineo
  • 777
  • 8
  • 28