時間格式化使用減少同一個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
}