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
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容