1

I am not quiet sure how to make dateFormatter that is reusable, since I read that dateFormatter is really expensive to do multiple times and that I should reuse it if its possible. Currently my function looks like this:

    func formatDate(date: String) -> String {
    let dateFormatterGet = DateFormatter()

    //this is format I get from my response
    dateFormatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    let dateFormatterSet = DateFormatter()

    //this is format I would like to show on my screen
    dateFormatterSet.dateFormat = "EEE, dd MMM YYYY, HH:mm a"
    let dateObj: Date? = dateFormatterGet.date(from: date)
    return dateFormatterSet.string(from: dateObj!)
}

I wouldn't be bothered if I would use it on one screen, but I am using on two, yet maybe its not to expensive either, but I want to know for future cases how to do it properly.

This is function from my other screen, only difference is dateFormatterSet, which I use for showing different format on my screen.

    func formatDate(date: String) -> String {
    let dateFormatterGet = DateFormatter()
    dateFormatterGet.dateFormat = "YYYY-MM-dd'T'HH:mm:ss.SSS'Z'"
    let dateFormatterSet = DateFormatter()
    dateFormatterSet.dateFormat = "EEE, dd MMM"
    guard let dateObj = dateFormatterGet.date(from: date) else { return "Start date 
    unknown"}
    return dateFormatterSet.string(from: dateObj)
}

Thanks in advance.

miki
  • 75
  • 9
  • That seems to be correct. The optimization is to reuse the same DateFormatter which have the same format. With a sharedInstance, an static var, etc. Currently, each timle you are calling your method, you are creating 2 formatters where they could be created beforehand and reused. Also, is your 3rd formatter correct, with the `YYYY`? Else, it would be the same as the first one (and could be "shared"). – Larme Mar 02 '21 at 08:46
  • Not related to your question but If you are using it to show the date to the user you should never display it using a fixed date format. You should respect the user device locale and setting while doing it. You should only chose how long is the date format using date and time style. https://stackoverflow.com/a/28347285/2303865 – Leo Dabus Mar 02 '21 at 15:40

2 Answers2

3

You don't need two date formatters to convert one date string to another.

My suggestion is to create one persistent date formatter with a fixed locale

let dateFormatter : DateFormatter = {
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    return formatter
}()

This could be also an extension

extension DateFormatter {
    static let posixFormatter : DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        return formatter
    }()
}

And secondly a function with parameters for input format with a default value and output format

func formatDate(dateString: String, inFormat: String = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", outFormat: String) -> String? {

    // let dateFormatter = DateFormatter.posixFormatter
   
    //this is format I get from my response
    dateFormatter.dateFormat = inFormat
    guard let date = dateFormatter.date(from: dateString) else { return nil }

    dateFormatter.dateFormat = outFormat
    return dateFormatter.string(from: date)
}

You have to check if a date could be created from the string so the return value is an optional.

Side note:

The Z in an ISO8601 string is the time zone specifier. It must not be wrapped in single quotes. And the year specifier is always lowercase yyyy.

vadian
  • 274,689
  • 30
  • 353
  • 361
0

I was reading about how expensive date formatting is and found a good article that proves why they are expensive and how they are expensive. Based on my understanding I created a solution by using a singleton class and an extension of Dateformatter. You can find it below.

Article I read: https://sarunw.com/posts/how-expensive-is-dateformatter/

class MyDateFormatter {
    static let sharedInstance = DateFormatter()
    private init() {
    }
}

extension DateFormatter{
    func getDateFrom(stringDate:String,format dateFormat:String)->Date?{
        let dateFormatter = MyDateFormatter.sharedInstance
        dateFormatter.dateFormat = dateFormat
        let dateObj: Date? = dateFormatter.date(from: stringDate)
        return dateObj
    }
    
    func getStringFrom(date:Date,format dateFormat:String)->String?{
        let dateFormatter = MyDateFormatter.sharedInstance
        dateFormatter.dateFormat = dateFormat
        let dateString: String? = dateFormatter.string(from: date)
        return dateString
    }
}

func formatDate(date: String) -> String {
    let dateObj:Date? = MyDateFormatter.sharedInstance.getDateFrom(stringDate: date, format: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
    let formattedDate:String? = MyDateFormatter.sharedInstance.getStringFrom(date: dateObj!, format: "EEE, dd MMM YYYY, HH:mm a")
    return formattedDate ?? ""
}

formatDate(date: "2011-11-02T02:50:12.208Z")