Swift 微信时间格式的String扩展

2020-10-10  本文已影响0人  喵喵粉

代码链接 http://www.52im.net/thread-2371-1-1.html

StringDateextension

extension String {
    
    func extGetWxTimeString() -> String {
        let fmt = DateFormatter()
        fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
        
        guard let cDate = fmt.date(from: self) else {
            return ""
        }
        
        let rst = cDate.extGetWxTimeString()
        return rst
    }
}

extension Date {
    /**
     * 仿照微信中的消息时间显示逻辑,将时间戳(单位:毫秒)转换为友好的显示格式.
     *
     * 1)7天之内的日期显示逻辑是:今天、昨天(-1d)、前天(-2d)、星期?(只显示总计7天之内的星期数,即<=-4d);
     * 2)7天之外(即>7天)的逻辑:直接显示完整日期时间。
     *
     * @param dt 日期时间对象(本次被判断对象)
     * @param includeTime YES表示输出的格式里一定会包含“时间:分钟”,否则不包含(参考微信,不包含时分的情况,用于首页“消息”中显示时)
     *
     * @return 输出格式形如:“刚刚”、“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式
     * @since 1.3
     */
    func extGetWxTimeString(_ includeTime: Bool = true) -> String {
        
        let kCalendar = Calendar.current
        
        // 当前时间 比我们实际时间慢了8个小时
        let currentDate = Date()
        
        let curComponents = kCalendar.dateComponents([.year, .month, .day, .weekday], from: currentDate)
        let currentYear = curComponents.year
        let currentMonth = curComponents.month
        let currentDay = curComponents.day
        
        // 目标判断时间
        let srcComponents = kCalendar.dateComponents([.year, .month, .day, .weekday], from: self)
        let srcYear = srcComponents.year
        let srcMonth = srcComponents.month
        let srcDay = srcComponents.day
        
        // 要额外显示的时间分钟
        let timeExtraStr = (includeTime ? getTimeString(date: self, format: " HH:mm") : "")
        
        // 当年
        if (currentYear == srcYear) {
            let currentTimestamp = currentDate.extTimeStamp
            let srcTimestamp = self.extTimeStamp
            
            // 相差时间(单位:秒)
            let delta = currentTimestamp - srcTimestamp
            
            // 当天(月份和日期一致才是)
            if(currentMonth == srcMonth && currentDay == srcDay) {
                // 时间相差60秒以内
                if (delta < 60) {
                    return "刚刚"
                }
                
                // 否则当天其它时间段的,直接显示“时:分”的形式
                return getTimeString(date: self, format: "HH:mm")
            }
            // 当年 && 当天之外的时间(即昨天及以前的时间)
            else {
                // 昨天(以“现在”的时候为基准-1天)
                let nowDate = Date()
                let yesterdayDate = Date(timeInterval: -24*60*60, since: nowDate)
                let yesterdayComponents = kCalendar.dateComponents([.year, .month, .day, .weekday], from: yesterdayDate)
                let yesterdayMonth = yesterdayComponents.month
                let yesterdayDay = yesterdayComponents.day
                
                // 前天(以“现在”的时候为基准-2天)
                let beforeYesterdayDate = Date(timeInterval: -48*60*60, since: nowDate)
                let beforeYesterdayComponents = kCalendar.dateComponents([.year, .month, .day, .weekday], from: beforeYesterdayDate)
                let beforeYesterdayMonth = beforeYesterdayComponents.month
                let beforeYesterdayDay = beforeYesterdayComponents.day
                
                // 用目标日期的“月”和“天”跟上方计算出来的“昨天”进行比较,是最为准确的(如果用时间戳差值
                // 的形式,是不准确的,比如:现在时刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00,
                // 这两者间只相差2小时,直接用“delta/3600” > 24小时来判断是否昨天,就完全是扯蛋的逻辑了)
                if (srcMonth == yesterdayMonth && srcDay == yesterdayDay) {
                    return "昨天\(timeExtraStr)"// -1d
                }
                // “前天”判断逻辑同上
                else if (srcMonth == beforeYesterdayMonth && srcDay == beforeYesterdayDay) {
                    return "前天\(timeExtraStr)"// -2d
                }
                else {
                    // 跟当前时间相差的小时数
                    let deltaHour = (delta/3600)
                    
                    // 如果小于或等 7*24小时就显示星期几
                    if (deltaHour <= 7*24) {
                        let weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
                        // 取出的星期数:1表示星期天,2表示星期一,3表示星期二。。。。 6表示星期五,7表示星期六
                        guard let srcWeekday = srcComponents.weekday else {
                            return ""
                        }
                        
                        // 取出当前是星期几
                        let weedayDesc = weekdays[srcWeekday-1]
                        return "\(weedayDesc)\(timeExtraStr)"
                    }
                    // 否则直接显示完整日期时间
                    else {
                        return "\(getTimeString(date: self, format: "yyyy/M/d"))\(timeExtraStr)"
                    }
                }
            }
        }
        
        // 往年
        return "\(getTimeString(date: self, format: "yyyy/M/d"))\(timeExtraStr)"
    }
    
    fileprivate func getTimeString(date: Date, format: String) -> String {
        let fmt = DateFormatter()
        fmt.dateFormat = format
        let rst = fmt.string(from: date)
        return rst
    }
}

/**
 let millisecond = Date().milliStamp
 print("当前毫秒级时间戳是 millisecond == ",millisecond)
 let timeStamp = Date().timeStamp
 print("当前秒级时间戳是 timeStamp == ",timeStamp)
 
 输出结果
 当前毫秒级时间戳是 millisecond ==  1524801851988
 当前秒级时间戳是 timeStamp ==  1524801851
 */
extension Date {

    /// 获取当前 秒级 时间戳 - 10位
    var extTimeStamp : CLongLong {
        let timeInterval: TimeInterval = timeIntervalSince1970
        let timeStamp = CLongLong(timeInterval)
        return timeStamp
    }

    /// 获取当前 毫秒级 时间戳 - 13位
    var extMilliStamp : CLongLong {
        let timeInterval: TimeInterval = timeIntervalSince1970
        let millisecond = CLongLong(round(timeInterval*1000))
        return millisecond
    }

    /// 获取当前 秒级 时间戳 - 10位
    var extTimeStampStr : String {
        let timeInterval: TimeInterval = timeIntervalSince1970
        let timeStamp = Int(timeInterval)
        return "\(timeStamp)"
    }

    /// 获取当前 毫秒级 时间戳 - 13位
    var extMilliStampStr : String {
        let timeInterval: TimeInterval = timeIntervalSince1970
        let millisecond = CLongLong(round(timeInterval*1000))
        return "\(millisecond)"
    }

    /// 获取当前date字符串
    var extNowDateString: String {
        let fmt = DateFormatter()
        fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"

        return fmt.string(from: Date())
    }
}

调用

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
     
     let fmt = DateFormatter()
     fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
     
     var nowDate = Date()
     print("当前date:", nowDate)
     let nowDateStr = fmt.string(from: nowDate)
     print("当前date str:", nowDateStr)
     nowDate = fmt.date(from: nowDateStr)!
     print("当前date:", nowDate)

     let times = ["2020-10-09 22:06:43",
                  "2020-10-08 08:23:44",
                  "2020-10-07 01:23:45",
                  "2030-10-01 01:23:45",
                  "2011-12-02 13:23:46"]
     for time in times {
         guard let cDate = fmt.date(from: time) else { return }
         
         var rst = cDate.extGetWxTimeString()
         print("\n1 字串:", time, "转成date:", cDate, "  --->", rst)
         
         rst = time.extGetWxTimeString()
         print("2 字串:", time, "转成date:", cDate, "  --->", rst)
     }
 }

打印

当前date: 2020-10-10 01:15:35 +0000
当前date str: 2020-10-10 09:15:35
当前date: 2020-10-10 01:15:35 +0000

1 字串: 2020-10-09 22:06:43 转成date: 2020-10-09 14:06:43 +0000   ---> 昨天 22:06
2 字串: 2020-10-09 22:06:43 转成date: 2020-10-09 14:06:43 +0000   ---> 昨天 22:06

1 字串: 2020-10-08 08:23:44 转成date: 2020-10-08 00:23:44 +0000   ---> 前天 08:23
2 字串: 2020-10-08 08:23:44 转成date: 2020-10-08 00:23:44 +0000   ---> 前天 08:23

1 字串: 2020-10-07 01:23:45 转成date: 2020-10-06 17:23:45 +0000   ---> 星期三 01:23
2 字串: 2020-10-07 01:23:45 转成date: 2020-10-06 17:23:45 +0000   ---> 星期三 01:23

1 字串: 2030-10-01 01:23:45 转成date: 2030-09-30 17:23:45 +0000   ---> 2030/10/1 01:23
2 字串: 2030-10-01 01:23:45 转成date: 2030-09-30 17:23:45 +0000   ---> 2030/10/1 01:23

1 字串: 2011-12-02 13:23:46 转成date: 2011-12-02 05:23:46 +0000   ---> 2011/12/2 13:23
2 字串: 2011-12-02 13:23:46 转成date: 2011-12-02 05:23:46 +0000   ---> 2011/12/2 13:23
上一篇下一篇

猜你喜欢

热点阅读