Date.distantPast #
在 iOS/macOS 的开发中,如果需要一个表示遥远过去的日期值(distant past),可以使用 Foundation
框架中提供的 Date
类型的 静态属性 Date.distantPast
。
Date.distantPast #
Date.distantPast
是Date
的一个静态属性,用于表示一个特别遥远过去的时间点。- 它通常用于那些需要一个方法返回一个非常早的日期(例如,起始时间)但又不需要指定具体的日期值的场景。
语法: #
let pastDate = Date.distantPast
值: #
Date.distantPast
的内部表示非常小的时间值,它是早于已知有意义的时间范围的一个时间点。通常在调试或者比较某些时间值时被用作“初始值”。
使用场景 #
Date.distantPast
常用于以下场景:
1. 时间比较中的初始值 #
- 如果您正在实现一种系统,需要找到一个最早的日期,您可以将
Date.distantPast
作为比较的初始值。 - 示例:循环一组日期,找出最早的日期。
let dates: [Date] = [
Date(), // 当前日期
Date.distantPast, // 远古日期
Date.distantFuture // 遥远的未来
]
var earliestDate: Date = Date.distantFuture
for date in dates {
if date < earliestDate {
earliestDate = date
}
}
print("Earliest date: \(earliestDate)")
2. 默认时间的占位值 #
- 用于初始化某些时间值,使其代表“无限早”的起始时间。例如,用在通过算法动态计算日期时,为变量赋一个默认的早时间值。
var startDate = Date.distantPast
print("Initial startDate: \(startDate)") // 默认值是历史起点
3. 时间范围的边界 #
- 它可以用作时间范围的下边界,用于在逻辑代码中表示 “任何早于这个时间的内容都算早于范围”。
let earliestAllowedDate = Date.distantPast
let currentDate = Date()
if currentDate >= earliestAllowedDate {
print("Current date is valid.")
}
4. 表示历史查询 #
- 在某些需要查询历史数据的情况下,可以使用
Date.distantPast
表示“从有历史记录的最早时间开始查询”。
Date.distantPast
的表示
#
输出值:
如果您打印Date.distantPast
,它通常会输出 ISO8601 或yyyy-MM-dd HH:mm:ss
格式的日期时间,这代表一个非常远的历史时间。示例:
let distantPastDate = Date.distantPast
print(distantPastDate) // 输出类似于 "0001-01-01 00:00:00 +0000"
- 底层存储值: Apple 使用时间戳(秒数)来存储日期,
Date.distantPast
值可能接近负的浮点数范围限制(非常低的时间戳)。
与 Date.distantFuture
的对比
#
- 与
Date.distantPast
相对,Date.distantFuture
表示一个非常遥远未来的日期值。它通常用作时间比较的上界或默认结束时间。
Date.distantFuture
示例:
#
let futureDate = Date.distantFuture
print(futureDate) // 输出类似于 "4001-01-01 00:00:00 +0000"
- 使用场景:当需要设置一个遥远的上界时间时,例如,定义一个默认的事件结束时间或逻辑边界。
总结 #
Date.distantPast
描述:
它表示一个距离现在非常遥远的过去时间,常用作日期比较的初值、时间范围的下界或占位时间。常见使用逻辑:
占位值:初始化某些需要代表“非常早”日期的变量。
时间比较:用于与其他日期一起计算最早时间。
时间范围:作为查询或判断范围的极端边界。
与
Date.distantFuture
搭配:Date.distantPast
和Date.distantFuture
一起,用于表示时间范围极端的上下界。
通过使用 Date.distantPast
,您可以简化一些需要处理时间逻辑的场景并提高代码的可读性。
API #
以下是 Foundation 框架中 Date
类型的核心 API 分类整理,涵盖初始化方法、计算属性、常用操作及扩展功能。结合 Calendar
和其他工具的使用场景,以下是完整的分类表格:
Foundation Date
API 分类整理
#
分类 | API / 方法 | 说明 | 示例 |
---|---|---|---|
初始化方法 | init() | 创建当前时间的 Date 对象 | let now = Date() |
init(timeIntervalSinceNow:) | 基于当前时间的偏移量创建日期 | let futureDate = Date(timeIntervalSinceNow: 3600) // 1小时后 | |
init(timeIntervalSince1970:) | 基于 1970-01-01 00:00:00 UTC 的秒数创建日期 | let date = Date(timeIntervalSince1970: 1_000_000) | |
init(timeIntervalSinceReferenceDate:) | 基于 2001-01-01 00:00:00 UTC 的秒数创建日期 | let date = Date(timeIntervalSinceReferenceDate: 3600) | |
计算属性 | timeIntervalSince1970 (属性) | 返回日期距离 1970-01-01 00:00:00 UTC 的秒数 | let timestamp = date.timeIntervalSince1970 |
timeIntervalSinceReferenceDate (属性) | 返回日期距离 2001-01-01 00:00:00 UTC 的秒数 | let refTime = date.timeIntervalSinceReferenceDate | |
比较与计算 | timeIntervalSince(_:) | 计算两个日期之间的时间间隔(秒) | let interval = date1.timeIntervalSince(date2) |
distance(to:) | 与 timeIntervalSince 等价,返回日期差值(兼容 Comparable 协议) | let diff = date1.distance(to: date2) | |
数学运算 | addingTimeInterval(_:) | 返回当前日期加上指定秒数的新日期 | let newDate = date.addingTimeInterval(3600) // 加1小时 |
advanced(by:) | 与 addingTimeInterval 等价(支持 Strideable 协议) | let newDate = date.advanced(by: 3600) | |
比较操作符 | == , > , < , >= , <= | 直接比较两个日期的先后顺序 | if date1 > date2 { ... } |
描述与转换 | description (属性) | 返回日期字符串(UTC 格式) | print(date.description) // “2023-09-15 07:30:45 +0000” |
description(with:) | 返回指定时区的本地化日期字符串 | date.description(with: TimeZone(identifier: "Asia/Tokyo")) | |
扩展功能 | ISO8601Format() | 返回 ISO 8601 格式的字符串(Swift 5.7+) | let isoString = date.ISO8601Format() // “2023-09-15T07:30:45Z” |
formatted() | 返回本地化的简洁日期字符串(依赖 FormatStyle ,Swift 5.5+) | date.formatted() // “9/15/23, 3:30 PM” | |
formatted(_:) | 自定义格式化(需结合 Date.FormatStyle ) | date.formatted(.dateTime.year().month().day()) // “Sep 15, 2023” |
结合 Calendar
的常用操作
#
Date
本身不直接处理日历逻辑,需通过 Calendar
实现更复杂的操作:
分类 | API / 方法 | 示例 |
---|---|---|
获取日期组件 | Calendar.component(_:from:) | let year = Calendar.current.component(.year, from: date) |
日期计算 | Calendar.date(byAdding:value:to:) | let nextMonth = Calendar.current.date(byAdding: .month, value: 1, to: date) |
日期范围 | Calendar.startOfDay(for:) | let start = Calendar.current.startOfDay(for: date) |
日期比较 | Calendar.isDate(_:inSameDayAs:) | Calendar.current.isDate(date1, inSameDayAs: date2) |
关键说明 #
Date
的局限性:Date
仅表示时间点,不包含日历、时区信息。具体年/月/日等需通过Calendar
和DateComponents
解析。时区处理:
Date
存储的时间是 UTC 时间,转换为本地时间需结合TimeZone
和Calendar
:let formatter = DateFormatter() formatter.timeZone = TimeZone(identifier: "Asia/Shanghai") formatter.dateFormat = "yyyy-MM-dd HH:mm" let localTime = formatter.string(from: date)
SwiftUI 扩展:
SwiftUI 提供Text(date, style: .time)
等便捷方式显示日期,底层仍依赖DateFormatter
。
完整示例 #
// 初始化与计算
let now = Date()
let tomorrow = now.addingTimeInterval(86400)
let interval = tomorrow.timeIntervalSince(now) // 86400 秒
// 使用 Calendar 处理
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: now)
let startOfDay = calendar.startOfDay(for: now)
// 格式化输出
let isoString = now.ISO8601Format() // Swift 5.7+
let customFormat = now.formatted(.dateTime.day().month(.wide).year()) // "September 15, 2023"
总结 #
- 核心功能:
Date
负责时间点的存储和基本运算,复杂日历逻辑需依赖Calendar
。 - 现代化扩展:Swift 5.5+ 的
formatted(_:)
和FormatStyle
提供了更简洁的本地化格式控制。
Formatter #
以下是 Foundation 框架中 Date Formatter 的详细说明,涵盖内置格式化工具、自定义方法及代码示例:
一、内置日期格式化工具 #
1. DateFormatter
#
用于将 Date
对象格式化为本地化的字符串,或解析字符串为 Date
对象。
预设样式 (通过 .dateStyle
和 .timeStyle
)
#
样式类型 | 示例(en_US) | 说明 |
---|---|---|
.none | — | 不显示日期/时间 |
.short | “6/15/23” / “3:30 PM” | 最短格式(数字为主) |
.medium | “Jun 15, 2023” / “3:30:45 PM” | 中等详细度 |
.long | “June 15, 2023” / “3:30:45 PM PDT” | 包含更多文本信息 |
.full | “Thursday, June 15, 2023” / “3:30:45 PM Pacific Daylight Time” | 完整格式(含时区) |
代码示例:
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let dateString = formatter.string(from: Date()) // "Jun 15, 2023 at 3:30 PM"
自定义格式符号 #
使用 dateFormat
属性定义完全自定义的格式:
符号 | 含义 | 示例 |
---|---|---|
yyyy | 四位数年份 | 2023 |
MM | 两位数月份 | 06 |
dd | 两位数日期 | 15 |
HH | 24小时制小时 | 15 |
hh | 12小时制小时 | 03 |
mm | 分钟 | 30 |
ss | 秒 | 45 |
a | AM/PM | AM 或 PM |
EEEE | 完整星期名称 | Thursday |
MMMM | 完整月份名称 | June |
代码示例:
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateString = formatter.string(from: Date()) // "2023-06-15 15:30:45"
2. ISO8601DateFormatter
#
专用于处理 ISO 8601 标准日期格式(如 2023-06-15T15:30:45Z
)。
常用选项: #
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let dateString = isoFormatter.string(from: Date()) // "2023-06-15T15:30:45.123Z"
选项 | 说明 |
---|---|
.withInternetDateTime | 标准格式(不含毫秒) |
.withFractionalSeconds | 包含毫秒(需与其他选项组合) |
.withTimeZone | 包含时区偏移(如 +08:00) |
3. RelativeDateTimeFormatter
(iOS 13+)
#
生成相对时间描述(如 “2 hours ago”, “tomorrow”)。
代码示例:
let relativeFormatter = RelativeDateTimeFormatter()
relativeFormatter.unitsStyle = .full
let relativeString = relativeFormatter.localizedString(for: Date(), relativeTo: Date().addingTimeInterval(-3600)) // "1 hour ago"
4. DateComponentsFormatter
#
将时间间隔(TimeInterval
)格式化为易读字符串(如 “2h 30m”)。
代码示例:
let componentsFormatter = DateComponentsFormatter()
componentsFormatter.unitsStyle = .abbreviated
componentsFormatter.allowedUnits = [.hour, .minute]
let intervalString = componentsFormatter.string(from: 9000) // "2h 30m"
二、自定义 Formatter 的完整方法 #
1. 固定格式(忽略用户区域设置) #
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX") // 强制使用固定区域
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
2. 动态本地化格式 #
formatter.locale = Locale.current // 跟随用户设置
formatter.setLocalizedDateFormatFromTemplate("ddMMyyyy") // 自动适配区域格式
// 在 en_US 显示 "MM/dd/yyyy",在 de_DE 显示 "dd.MM.yyyy"
3. 高级自定义 #
// 组合符号和文本
formatter.dateFormat = "'Created on' EEEE, MMMM d 'at' h:mm a"
// 输出:"Created on Thursday, June 15 at 3:30 PM"
// 处理时区
formatter.timeZone = TimeZone(identifier: "Asia/Tokyo")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
// 输出:"2023-06-16 07:30:45 +0900"
三、关键注意事项 #
性能优化
DateFormatter
的创建成本较高,建议缓存实例(尤其是频繁使用时)。- 避免在列表单元格中重复创建 Formatter。
线程安全
DateFormatter
不是线程安全的,需确保在同一线程使用。
错误处理
- 解析字符串时使用
date(from:)
可能返回nil
,需做空值检查:if let date = formatter.date(from: "2023-06-15") { // 解析成功 }
- 解析字符串时使用
四、不同 Formatter 的适用场景 #
场景 | 推荐工具 |
---|---|
显示用户本地化日期 | DateFormatter + 预设样式 |
处理 API 的 ISO 日期 | ISO8601DateFormatter |
显示“XX 分钟前” | RelativeDateTimeFormatter |
格式化时间间隔 | DateComponentsFormatter |
完全自定义格式 | DateFormatter.dateFormat |
五、完整自定义示例 #
// 自定义带时区的格式化
let customFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ja_JP")
formatter.timeZone = TimeZone(identifier: "Asia/Tokyo")
formatter.dateFormat = "yyyy年M月d日 (EEE) HH時mm分"
return formatter
}()
let dateString = customFormatter.string(from: Date())
// 输出:"2023年6月15日 (木) 23時30分"
通过灵活组合这些工具,可以满足从简单日期显示到复杂国际化的所有需求。
Style #
以下是 Foundation 框架中 DateFormatter
的 dateStyle
、timeStyle
和 behavior
属性的详细说明,包括它们的可选类型、作用区别及代码示例:
一、dateStyle
和 timeStyle
属性
#
这两个属性控制日期和时间的预设格式化样式,属于 DateFormatter.Style
枚举类型。它们会根据用户设备的区域设置自动适配本地化格式。
1. 可选值及效果 #
枚举值 | 日期示例 (en_US) | 时间示例 (en_US) | 说明 |
---|---|---|---|
.none | — | — | 不显示日期/时间部分 |
.short | 6/15/23 | 3:30 PM | 最简格式(数字为主) |
.medium | Jun 15, 2023 | 3:30:45 PM | 中等详细度 |
.long | June 15, 2023 | 3:30:45 PM PDT | 包含更多文本信息(如时区缩写) |
.full | Thursday, June 15, 2023 | 3:30:45 PM Pacific Daylight Time | 完整格式(含完整时区名称) |
2. 代码示例 #
let formatter = DateFormatter()
// 设置日期样式
formatter.dateStyle = .medium // 输出日期如 "Jun 15, 2023"
formatter.timeStyle = .short // 输出时间如 "3:30 PM"
let dateString = formatter.string(from: Date()) // "Jun 15, 2023 at 3:30 PM"
3. 关键规则 #
- 若同时设置
dateStyle
和timeStyle
,输出会合并日期和时间(如"Jun 15, 2023 at 3:30 PM"
)。 - 若只设置其中一个,另一个默认为
.none
。 - 优先级:如果同时设置了
dateFormat
和dateStyle
/timeStyle
,dateFormat
会覆盖样式设置。
二、behavior
属性(已废弃)
#
behavior
属性原本属于 NSDateFormatter
的 Behavior
枚举类型,用于控制解析和格式化的严格性,但在 Swift 的现代版本中已标记为废弃。其原始可选值为:
枚举值 | 说明 |
---|---|
.default | 默认行为(宽松解析,允许不完整日期) |
.behavior10_0 | 兼容 macOS 10.0 的旧解析逻辑 |
.behavior10_4 | 兼容 macOS 10.4 的行为(更严格的解析) |
⚠️ 注意 #
- Swift 中不再推荐使用:Apple 官方建议直接使用
DateFormatter
的默认行为,不再需要手动设置behavior
。 - 替代方案:若需控制解析严格性,可使用
dateFormat
或isLenient
属性。
三、替代 behavior
的现代属性
#
1. isLenient
#
控制解析时是否允许宽松处理(如将 “2023-13-01” 解析为 2024-01-01)。
formatter.isLenient = true // 默认值为 true(允许宽松解析)
2. dateFormat
#
直接定义严格的格式模板,替代旧的 behavior
控制方式。
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.isLenient = false // 严格模式(格式不匹配则返回 nil)
四、不同属性的优先级与冲突 #
属性组合 | 结果 |
---|---|
同时设置 dateStyle 和 dateFormat | dateFormat 覆盖 dateStyle 和 timeStyle |
设置 isLenient = false | 解析时严格匹配 dateFormat ,否则返回 nil |
设置 locale | 覆盖本地化规则(影响星期/月份名称和顺序) |
五、完整示例 #
// 创建 Formatter
let formatter = DateFormatter()
// 设置样式(优先于 dateFormat)
formatter.dateStyle = .long
formatter.timeStyle = .short
// 设置区域和严格性
formatter.locale = Locale(identifier: "fr_FR") // 法文格式
formatter.isLenient = false
// 输出结果
let date = Date()
print(formatter.string(from: date)) // "15 juin 2023 à 15:30"
六、总结 #
dateStyle
和timeStyle
:快速生成本地化友好的日期时间格式。behavior
:已废弃,不再建议使用。- 替代方案:用
isLenient
控制解析宽松性,用dateFormat
精确控制格式。
Date Style #
在 Swift 中,Date
类型的格式化功能非常强大,主要通过 FormatStyle
及其子类型实现。除了 RelativeFormatStyle
,还有多种 FormatStyle
可用于不同场景。以下是完整的分类介绍和代码示例:
1. 标准日期时间格式(Date.FormatStyle
)
#
最常用的格式化方式,支持高度自定义日期和时间的各个组成部分。
核心方法 #
dateTime
:组合日期和时间date
:仅日期time
:仅时间- 可配置年、月、日、时区等细节
代码示例 #
import Foundation
let date = Date() // 当前时间
// 基础格式化
let formatted1 = date.formatted() // 默认格式,如 "2024年3月18日 下午3:45"
// 自定义日期和时间组件
let formatted2 = date.formatted(
.dateTime
.year(.defaultDigits) // 年(如 "2024")
.month(.abbreviated) // 缩写月份(如 "Mar")
.day(.twoDigits) // 两位日期(如 "18")
.hour(.conversationalDefaultDigits(amPM: .abbreviated)) // 12小时制带AM/PM
.minute(.twoDigits) // 两位分钟
)
// 输出结果示例:"Mar 18, 2024 at 3:45 PM"
配置选项 #
组件 | 配置方法示例 | 效果示例 |
---|---|---|
年份 | .year(.twoDigits) | “24”(两位年份) |
月份 | .month(.wide) | “March”(完整月份名) |
星期 | .weekday(.short) | “Mon”(缩写星期) |
日 | .day(.ordinalOfDayInMonth) | “18th”(序数后缀) |
小时 | .hour(.conversationalDefaultDigits(amPM: .omitted)) | “15”(24小时制) |
时区 | .timeZone(.identifier(.short)) | “CST”(时区缩写) |
2. 纯字符串自定义格式(VerbatimFormatStyle
)
#
完全自定义格式字符串,类似传统 DateFormatter
的样式。
代码示例 #
let verbatimStyle = Date.VerbatimFormatStyle(
format: "yyyy-MM-dd HH:mm:ss",
locale: Locale(identifier: "en_US"),
timeZone: TimeZone.current,
calendar: Calendar.current
)
let formatted = date.formatted(verbatimStyle) // "2024-03-18 15:45:00"
常用格式符号 #
符号 | 含义 | 示例 |
---|---|---|
y | 年份 | “2024” |
M | 月份 | “03” 或 “3” |
d | 日期 | “18” |
H | 小时(24小时制) | “15” |
h | 小时(12小时制) | “3” |
m | 分钟 | “45” |
s | 秒 | “00” |
E | 星期缩写 | “Mon” |
3. 日期区间格式(Date.IntervalFormatStyle
)
#
用于格式化两个日期之间的间隔(如事件时间段)。
代码示例 #
let startDate = Calendar.current.date(from: DateComponents(year: 2024, month: 3, day: 18))!
let endDate = Calendar.current.date(from: DateComponents(year: 2024, month: 3, day: 20))!
let intervalStyle = Date.IntervalFormatStyle(
date: .numeric, // 日期格式
time: .shortened // 时间格式
)
let formatted = intervalStyle.format(startDate...endDate)
// 输出:"3/18/2024 – 3/20/2024"
配置选项 #
// 更详细的配置
let customIntervalStyle = Date.IntervalFormatStyle(
date: .abbreviated, // 如 "Mar 18"
time: .omitted, // 不显示时间
locale: Locale(identifier: "zh_CN")
)
let formattedCN = customIntervalStyle.format(startDate...endDate)
// 输出:"3月18日 – 3月20日"
4. ISO 8601 格式(ISO8601FormatStyle
)
#
生成符合 ISO 8601 标准的字符串,适合网络传输或日志记录。
代码示例 #
let isoStyle = Date.ISO8601FormatStyle(
timeZone: TimeZone(identifier: "Asia/Shanghai")!,
includingFractionalSeconds: true, // 包含毫秒
dateSeparator: .dash // 日期分隔符
).year().month().day().dateTimeSeparator(.space).time()
let formatted = date.formatted(isoStyle)
// 输出示例:"2024-03-18 07:45:00.000+08:00"
配置选项 #
// 精简配置(仅日期)
let dateOnly = Date.ISO8601FormatStyle(dateSeparator: .dash).year().month().day()
let formattedDate = date.formatted(dateOnly) // "2024-03-18"
5. 本地化格式(Locale
适配)
#
通过 locale
自动适配不同地区的日期格式。
代码示例 #
let date = Date()
// 美式格式
let usStyle = date.formatted(.dateTime.locale(Locale(identifier: "en_US")))
// "Mar 18, 2024 at 3:45 PM"
// 中文格式
let cnStyle = date.formatted(.dateTime.locale(Locale(identifier: "zh_CN")))
// "2024年3月18日 下午3:45"
// 日式格式
let jpStyle = date.formatted(.dateTime.locale(Locale(identifier: "ja_JP")))
// "2024/03/18 15:45"
6. 快捷样式(预定义样式) #
Swift 提供了一些预定义的快捷样式,适用于常见场景。
代码示例 #
let date = Date()
// 仅日期(完整格式)
let dateFull = date.formatted(date: .complete, time: .omitted)
// "Monday, March 18, 2024"
// 仅时间(短格式)
let timeShort = date.formatted(date: .omitted, time: .shortened)
// "3:45 PM"
// 组合样式
let combined = date.formatted(date: .abbreviated, time: .standard)
// "Mar 18, 2024, 3:45:00 PM"
总结:不同场景的推荐选择 #
场景 | 推荐样式 | 示例 API |
---|---|---|
标准日期时间显示 | Date.FormatStyle | .dateTime.year().month() |
完全自定义格式 | VerbatimFormatStyle | "yyyy-MM-dd HH:mm:ss" |
日期区间 | IntervalFormatStyle | .format(startDate...endDate) |
网络传输/日志记录 | ISO8601FormatStyle | .iso8601 |
国际化适配 | 结合 Locale 的格式化 | .locale(Locale(identifier:)) |
通过灵活组合这些 FormatStyle
,你可以轻松实现从简单到复杂的日期时间格式化需求!