22

Here is the code excerpt:

func mapping(map: Map) {
    time      <- (map["time"], TransformOf<Date, String>(fromJSON: {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "HH:mm:ss"
        //dateFormatter.timeZone = TimeZone(abbreviation: "EEST")
        if let argument = $0 {
            let date = dateFormatter.date(from: argument)
            return dateFormatter.date(from: argument)
        }
        return nil
        }}

$0 is string with "22:12:00". I put "let date" to see what it returns and it's nil. I've looked up for format codes here: http://waracle.net/iphone-nsdateformatter-date-formatting-table/

Code should work actually. What am I doing wrong?

EDIT: Added the whole function

EDIT2: I just noticed it's working properly on iPhone 7 iOS 10.1 simulator but returns nil on my iPod 10.1.1 (2016). This is so weird.

shallowThought
  • 19,212
  • 9
  • 65
  • 112
muvaf
  • 323
  • 4
  • 9
  • 2
    You probably have to set the formatters locale to "en_US_POSIX", see for example http://stackoverflow.com/a/16706425/1187415 or http://stackoverflow.com/a/25671175/1187415 . – Martin R Nov 19 '16 at 12:00
  • The app will not be used in US and even if that's the case I don't want it to be localized for en_US. Also I checked settings of simulator and ipod, both are the same. – muvaf Nov 19 '16 at 12:04
  • @bymafmaf: Did you at least *try* if it makes a difference? – Martin R Nov 19 '16 at 12:05
  • Off topic: what will I google for if I do not understand this syntax: ` time <- ( ...` – shallowThought Nov 19 '16 at 12:05
  • @MartinR i tried it worked but returned different value than what simulator normally returns. both UTC, 1 hour forward in device with en_US_POSIX – muvaf Nov 19 '16 at 12:14
  • @bymafmaf: That is a different issue, printing a `Date` *always* uses UTC. – Martin R Nov 19 '16 at 12:56
  • @shallowThought it must be user-defined operator – ramacode Nov 19 '16 at 13:43
  • @ramacode: ahh, that makes sense. Thx! (suspicious to be the root of the issue also) – shallowThought Nov 19 '16 at 14:59
  • @MartinR I added "en_US_POSIX" to everywhere I do formatting. Now it seems to work fine. Please write it as answer so that I can mark it. Thank you! – muvaf Nov 19 '16 at 20:39
  • @bymafmaf i'm facing same issue of getting nil date for string HH:mm:ss? Can you suggest any solution for it. – Kalyani Apr 27 '17 at 06:30

2 Answers2

39

From Technical Q&A QA1480 – NSDateFormatter and Internet Dates (emphasis added):

On the other hand, if you're working with fixed-format dates, you should first set the locale of the date formatter to something appropriate for your fixed format. In most cases the best locale to choose is "en_US_POSIX", a locale that's specifically designed to yield US English results regardless of both user and system preferences.

This will prevent the date from being interpreted according to the user's regional settings:

let dateFormatter = DateFormatter()
// Set the locale first ...
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
// ... and then the date format:
dateFormatter.dateFormat = "HH:mm:ss"

// ...

See also What is the best way to deal with the NSDateFormatter locale "feechur"?.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
-1

sample of usage:

let a = Date.now

let b = a.asString("yyyy-MM-dd")
let c = Date.fromString(strDate: "2023-05-30", "yyyy-MM-dd")

back code:

extension DateFormatter {
    static var shared = getSharedDateFormatter()
    
    fileprivate static func getSharedDateFormatter(template: String? = nil) -> DateFormatter {
        let df = DateFormatter()
        df.timeZone = .current
        df.dateFormat = template ?? "HH:mm:ss"
        
        df.amSymbol = "AM"
        df.pmSymbol = "PM"
        
        return df
    }
}

public extension Date {
    func asString(_ template: String?) -> String {
        DateFormatter.shared.dateFormat = template
        return DateFormatter.shared.string(from: self)
    }
    
    static func fromString(strDate: String, _ template: String) -> Date? {
        DateFormatter.shared.dateFormat = template
        
        return DateFormatter.shared.date(from: strDate)
    }
}

important thing: this code does not create lot of instances of DateFormatter so it's works really fast.

Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101