如何在 Swift 中做一个正确的日期格式化程序

How to do a proper Date formatter in Swift

我不确定如何制作可重用的 dateFormatter,因为我读到 dateFormatter 多次执行非常昂贵,如果可能的话我应该重用它。目前我的函数如下所示:

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

如果我在一个屏幕上使用它,我不会感到困扰,但我在两个屏幕上使用,但也许它也不会太贵,但我想知道在未来的情况下如何正确地做到这一点。

这是我另一个屏幕上的功能,唯一不同的是 dateFormatterSet,我用它在我的屏幕上显示不同的格式。

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

提前致谢。

您不需要两个日期格式化程序即可将一个日期字符串转换为另一个日期字符串。

我的建议是创建一个具有固定语言环境的持久日期格式化程序

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

这也可以是一个扩展

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

其次是一个带有默认值和输出格式的输入格式参数的函数

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

您必须检查是否可以从字符串创建日期,因此 return 值是可选的。

旁注:

ISO8601 字符串中的 Z 是时区说明符。它不能用单引号引起来。年份说明符始终为小写 yyyy.

我正在阅读有关日期格式的昂贵费用的文章,并找到了一篇很好的文章来证明它们为何如此昂贵以及它们如何昂贵。根据我的理解,我通过使用单例 class 和 Dateformatter 的扩展创建了一个解决方案。您可以在下面找到它。

我阅读的文章: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")