Swift時間統一格式化

時間格式化使用減少同一個format重復創建的開銷
盡量不要使用YYYY大寫的格式化年,否側年末獲取的時間可能不對
yyyy使用的是日歷年,我們應該使用日歷年這種方式
YYYY使用的是當前周所在的年份(Week of Year)
比如:2020年12月27日是周日,而周日是一周的開始。所以如果26日運行這個例子,年份上顯示是沒有問題的。而從2020年12月27日 00:00:00開始顯示會有問題!


image.png

使用如下:

LDate.string(from: Date(), format: "yyyy-MM-dd")

時間類型枚舉

public enum LDateFormat: Int {
    // 始終顯示精確日期和時間
    case precise
    // specific 始終顯示具體分鐘
    case specific
    // short突出處理短時間
    case short
}

時間format緩存池

/// 根據外部傳入的format不同緩存不同的DateFormatter對象,傳入已存在的format格式對象直接返回不會再次創建

private extension DateFormatter {
    static func cached(withFormat format: String) -> DateFormatter {
        var cachedFormatters = LDate.shared.cachedFormatters
        if let cachedFormatter = cachedFormatters[format] {
            return cachedFormatter
        }
        let formatter = DateFormatter()
        formatter.locale = NSLocale.system // fix:iOS15.4~15.6 12小時制日期格式顯示問題
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.dateFormat = format
        cachedFormatters[format] = formatter
        return formatter
    }
}

LDate類

    /// 單例
    fileprivate static let shared = LDate.init()
    ///  緩存DateFormatter對象池
    fileprivate var cachedFormatters = [String: DateFormatter]()
    /// LDateFormat為specific生效
    fileprivate let defaultFormat = "yyyy-MM-dd HH:mm:ss"
    /// 內部處理時間格式
    fileprivate lazy var dateFormatter: DateFormatter = {
        let format = DateFormatter()
        format.dateFormat = LDate.shared.defaultFormat
        format.locale = NSLocale.system // fix:iOS15.4~15.6 12小時制日期格式顯示問題
        format.calendar = Calendar(identifier: .gregorian)
        return format
    }()

String轉Date

    /**
     String轉Date
     @param from String
     @param format 例如:yyyy-MM-dd
     */
    public class func date(from: String, format: String) -> Date? {
        let dateFormatter = DateFormatter.cached(withFormat: format)
        return dateFormatter.date(from: from)
    }

Date轉String

    /**
     Date轉String
     @param from Date
     @param format 例如:yyyy-MM-dd
     */
    public class func string(from: Date, format: String) -> String {
        let dateFormatter = DateFormatter.cached(withFormat: format)
        return dateFormatter.string(from: from)
    }

時間戳轉String

/**
     時間戳轉String
     @param timeStamp Int 時間戳
     @param format 例如:yyyy-MM-dd
     */
    public class func string(_ timeStamp: Int, format: String) -> String {
        let dateFormatter = DateFormatter.cached(withFormat: format)
        let date = NSDate(timeIntervalSince1970: TimeInterval(timeStamp)) as Date
        return dateFormatter.string(from: date)
    }

當前時間戳轉字符串 對應不同時間格式

/**
 時間轉換方法
 @param timeStamp 時間戳
 @param format 時間處理類型  precise // 始終顯示精確日期和時間 specific // 始終顯示具體分鐘 short // 突出處理短時間
 */
public class func timeToString(_ timeStamp: Int, _ format: LDateFormat) -> String {
    let timeStr = NSNumber(value: timeStamp).stringValue
    // 時間戳位數大于10視為毫秒級,轉秒級除以1000
    var timeInterval = timeStamp
    if timeStr.count > 10 {
        timeInterval /= 1000
    }
    switch format {
    case .precise:
        return preciseTimeStamp(timeInterval)
    case .specific:
        return specificTimeStamp(timeInterval)
    case .short:
        return shortTimeStamp(timeInterval)
    }
}

始終顯示精確日期和時間

private func preciseTimeStamp(_ timeStamp: Int) -> String {
    // 所有時間 默認 yyyy-MM-DD xx:xx:xx
    let date = NSDate(timeIntervalSince1970: TimeInterval(timeStamp)) as Date
    return LDate.shared.dateFormatter.string(from: date)
}

始終顯示具體分鐘

private func specificTimeStamp(_ timeStamp: Int) -> String {
    let timeInterval = TimeInterval(timeStamp)
    let date = NSDate(timeIntervalSince1970: timeInterval) as Date
    // 當天0:00-24:00 xx:xx
    if date.isToday() {
        return timeToString(timeInterval, "HH:mm")
    }
    // 昨天0:00-24:00 昨天xx:xx
    if date.isYesterday() {
        let timeStr = timeToString(timeInterval, "HH:mm")
        return String(format: "昨天 %@", timeStr)
    }
    // 超過昨天且當年 MM-DD xx:xx
    if date.isThisYear() {
        return timeToString(timeInterval, "MM-dd HH:mm")
    }
    // 超過昨天且跨年 yyyy-MM-DD xx:xx
    return timeToString(timeInterval, "yyyy-MM-dd HH:mm")
}

突出處理短時間

private func shortTimeStamp(_ timeStamp: Int) -> String {
    var timeInterval: Int = 0, temp: Int = 0
    // 從傳入時間到當前時間的差值 秒級
    timeInterval =  Int(Date().timeIntervalSince1970) - timeStamp
    // 獲取有多少分鐘
    temp = timeInterval / 60
    if temp < 1 { // 1分鐘內 剛剛
        return "剛剛"
    }
    if temp < 60 { // 1小時內 xx分鐘前
        return String(format: "%ld分鐘前", temp)
    }
    // 獲取有多少小時
    temp /= 60
    if temp < 24 { // 24小時內 xx小時前 (不考慮00:00前后,只要在24小時內)
        return String(format: "%ld小時前", temp)
    }
    let timeStampInterval = TimeInterval(timeStamp)
    let date = NSDate(timeIntervalSince1970: timeStampInterval) as Date
    if date.isYesterday() { // 超過24小時且在昨天 昨天
        return "昨天"
    }
    if date.isThisYear() { // 超過昨天且當年 MM-DD
        return timeToString(timeStampInterval, "MM-dd")
    }
    // 超過昨天且跨年 yyyy-MM-DD
    return timeToString(timeStampInterval, "yyyy-MM-dd")
}

時間戳 -> 日期

private func timeToString(_ timeStamp: TimeInterval, _ format: String?) -> String {
    let date = NSDate(timeIntervalSince1970: timeStamp) as Date
    let time = LDate.string(from: date, format: format ?? LDate.shared.defaultFormat)
    return time
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容