时间格式化使用减少同一个format重复创建的开销
尽量不要使用YYYY大写的格式化年,否侧年末获取的时间可能不对
yyyy使用的是日历年,我们应该使用日历年这种方式
YYYY使用的是当前周所在的年份(Week of Year)
比如:2020年12月27日是周日,而周日是一周的开始。所以如果26日运行这个例子,年份上显示是没有问题的。而从2020年12月27日 00:00:00开始显示会有问题!
使用如下:
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
}