AM/PM
是否显示 AM PM 根据系统时间设置 24 还是 12 小时制进行区分
let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)
let containsA = dateFormat?.range(of: "a")
return containsA == nil ? .twentyFourHour : .twelveHour
时区常见缩写
- UTC: Coordinated Universal Time,世界标准时间;时区偏移通过添加或减去小时数来表示。例如,UTC+2 表示比协调世界时晚2个小时,而UTC-5表示比协调世界时早5个小时。
- EEST: 欧洲东部夏令时间(Eastern European Summer Time)
- *ST: 夏令时 ( * Summer Time)
- *WT: 东令时 ( * Winter Time)
- GMT: Greenwich Mean Time
时区分类
- 用户时区
- 本地时区
DateFormatter
- H: 小时,hh 代表 12 小时制,HH 代表 24 小时制,如果 dataFormat = "HH:mm a",则显示 "15:45 PM"
- m: 分钟
- s: 秒
- Y/y: 年
- M: 月
- d: 日
- a: AM/PM
- Z: 时区偏移, "HH:mm Z" 格式显示为 "15:45 -08:00"
日历
默认公历,其他日历暂不处理
Locale
举例 identify 为 "es-US",包括语言和国家,假定不做对国家的相关业务处理,只在不同的语言下,进行时间
格式转换
不同语言下的时间格式会有所差别,例如同样是年月日的展示 "yyyy MMM dd"
- 法语 fr: dd MMM yyyy
- 德语 de: dd. MMM yyyy
- 日语 jp: yyyy年M月dd日
- 英语 us: MMM dd, yyyy
let formatStr = DateFormatter.dateFormat(fromTemplate: "yyyy MMM dd", options: 0, locale: Locale(identifier: "es-US"))
东夏令时
拿英国举例,英国的冬令时和夏令时具有很强的规律性,并且调整时间的日期也相对固定。
英国冬令时 BWT,在每年 10 月的最后一个周日的凌晨 2 点实行,时钟将会向后调 1 个小时,今年就是在 10 月 29 日,直至次年 3 月的最后一个周末为止。
而英国夏令时 BST,在每年 3 月的最后一个周日的凌晨 1 点实行,时钟将会向前调 1 个小时
代码实现,系统 api 会根据系统时区进行东夏令时偏移,和设备
TimeZone.current.daylightSavingTimeOffset(for: <#T##Date#>)
常见时间格式字符串
- 简写月数组: short month symbols
- 单字符月数组: very short month symbols
- 全称月数组: standalone month symbols
- 简写周数组: short weekday symbols
- 单字符周数组: very short weekday symbols
- 全称周数组: standalone weekday symbols
var calendar = Calendar.user
calendar.timeZone = timeZone
calendar.locale = locale
return calendar.shortWeekdaySymbols
常见日期需求
日期 date 对象获取
- start of year: 一年中第一天的零点时间
- end of year: 一年中最后一天的零点时间
- start of day: 一天的零点时间
- end of day: 一天的 23:59:59
- start of month: 月第一天的零点时间
- end of month: 月最后一天的零点时间
- start of week: 周第一天的零点时间
- end of week: 周最后一天的零点时间
- offset day(offset): 距今往后 offset 天的零点时间
- offset month(offset): 距今往后 offset 月的零点时间,例如 2023.12.1 天 一个月后是 2024.1.1
- offset year(offset): 距今往后 offset 年的零点时间,例如 2023.12.1 天 一年后是 2024.12.1
- previousDay: 前一天的零点时间
var calendar = Calendar.user
calendar.timeZone = timeZone
calendar.date(from: calendar.dateComponents([.year, .month], from: calendar.startOfDay(for: base)))
calendar.date(byAdding: .day, value: offset, to: base)
判断是否符合条件
- is today: 是否是今天
- is tomorrow: 是否是明天
- is yesterday: 是否是昨天
- is weekend: 是否是周末
- is workday: 是否是工作日
- is this week: 是否在这周
- is this month: 是否是这个月
- is this year: 是否是今年
var calendar = Calendar.user
calendar.timeZone = timeZone
calendar.isDateInToday(base)
calendar.isDate(base, equalTo: Date(), toGranularity: .weekOfYear)
日期 date 对象比较
- is same year: 是否是同一年
- is same month: 是否是同一月
- is same day: 是否是同一天
int 获取
- weekday: 周的第几天,以 iOS 为例,默认在 es 英语中,1 为星期日,2 为星期一,依次类推
- month: 年的第几月,从 1 开始以此类推
- year: 哪一年,例如 2023
- day in month: 这个月有多少天
- day: 是这个月的第几天
- hour: 时钟数
- minute: 分钟数
- second: 秒钟数
- day second: 今天零点开始的秒数累计值 = 时钟数 * 60 * 60 + 分钟数 * 60 + 秒钟数
var calendar = Calendar.user
calendar.timeZone = timeZone
calendar.component(.weekday, from: base)
calendar.range(of: .day, in: .month, for: base)?.count
日期 date 对象相距数量比较
- year: 相距多少年,2023.1.20 和 2024.1.23 相距 1 年
- month: 相距多少个月,2023.12.29 和 2024.1.2 相距 0 个月
- day: 相距多少天
字符串获取
let dateFormat = DateFormatter()
dateFormat.timeZone = timeZone
dateFormat.formattingContext = .standalone
dateFormat.locale = locale
if var formatStr = DateFormatter.dateFormat(fromTemplate: property.rawValue, options: 0, locale: dateFormat.locale) {
if let regex = try? NSRegularExpression(pattern: "(?<!h)h(?!h)") {
formatStr = regex.stringByReplacingMatches(in: formatStr, options: [], range: NSRange(location: 0, length: formatStr.utf16.count), withTemplate: "hh")
}
if let index = formatStr.firstIndex(of: "a") {
formatStr.remove(at: index)
dateFormat.dateFormat = formatStr + (Date.vst.hourFormat == .twelveHour ? " a" : "")
} else {
dateFormat.dateFormat = formatStr
}
}
return dateFormat.string(from: base)
String 转 Date
获取 DateA 偏移后的 DateB
常见时间格式转换
- EEEE
- EEE
- MMM
- MM dd
- MMM dd
- MM/dd
- MMM/dd
- yyyy
- yyyy MM dd
- yyyy MMM dd
- yyyy/MM/dd
- yyyy/MMM/dd
- yyyy MM
- yyyy MMM
- yyyy/MM
- yyyy/MMM
- yyyy MM dd hh:mm:ss
- yyyy MMM dd hh:mm:ss
- yyyy/MM/dd hh:mm:ss
- yyyy/MMM/dd hh:mm:ss
- yyyy MM dd hh:m
- yyyy MMM dd hh:mm
- yyyy/MM/dd hh:mm
- yyyy/MMM/dd hh:mm
- hh:mm:ss
- hh:mm