swift 日期与时间的三个结构体

193 阅读5分钟

DateComponents

在 swift 中,DateComponents 结构体表示的是日期时间的组成部分,比如年、月、日、小时、分钟等。你可以根据需要选择性的设置字段(例如,只设置年月日、忽略时间等)。

它符合以下协议:

  • Hashable:支持哈希操作,用于存储在 Set 或作为字典的键。
  • Equatable:支持比较两个 DateComponents 是否相等。
  • Sendable:支持多线程安全传递(在并发编程中很有用

这是它的初始化方法:

public init(calendar: Calendar? = nil, timeZone: TimeZone? = nil, era: Int? = nil, year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil, second: Int? = nil, nanosecond: Int? = nil, weekday: Int? = nil, weekdayOrdinal: Int? = nil, quarter: Int? = nil, weekOfMonth: Int? = nil, weekOfYear: Int? = nil, yearForWeekOfYear: Int? = nil)

各个字段说明如下:

字段描述
calendar使用的日历(如公历、农历等)
timeZone时区
era纪元(如公历纪元、佛历纪元等)
year年份
month月份
day天数
hour小时
minute分钟
second
nanosecond纳秒
weekday星期几(1=周日,2=周一等)
weekdayOrdinal周几的顺序(如第二个周五)
quarter季度(1、2、3、4)
weekOfMonth月中的第几周
weekOfYear年中的第几周
dayOfYear一年中的第几天(如 1 到 365 或 366)
yearForWeekOfYearISO 8601 周编号年份
isLeapMonth是否为闰月

你可以传入一些参数来构建时间,如果不传入就是nil,默认使用系统的时间参数,下面是示例:

let components = DateComponents(year: 2025, month: 7, day: 28, hour: 15)
let calendar = Calendar.current
let date = calendar.date(from: components)

calendar 参数是一个 Calendar 类型,表示使用哪种日历系统。 使用方法如下:

let calendar = Calendar(identifier: .republicOfChina)  // 创建 Republic of China 日历
let currentDate = DateComponents(calendar: calendar)

它还包括验证某个日期组成是不是有效的方法:

let components = DateComponents(year: 2025, month: 2, day: 30)
let isValid = components.isValidDate(in: Calendar.current)

一个验证两个日期组成是不是相等的方法,

import Foundation

var a = DateComponents()
a.year = 2025
a.month = 7
a.day = 28

var b = DateComponents()
b.year = 2025
b.month = 7
b.day = 28

print(a == b) // 输出 true

一个往DateComponents中加入日期组成和一个提取出日期组成的方法 示例如下:

var components = DateComponents()
components.setValue(2025, for: .year)
components.setValue(7, for: .month)
components.setValue(28, for: .day)
let year = components.value(for: .year)  // 返回 Optional(2025)

Calendar 结构体

这个结构体是swift处理时间和日期的核心工具,基于底层的 NSCalendar,支持多种历法(如公历、佛历、伊斯兰历等)。

下面是它的初始化函数,,需要传入一个历法参数。

/// Returns a new Calendar.
    ///
    /// - parameter identifier: The kind of calendar to use.
    public init(identifier: Calendar.Identifier)

示例:

let gregorian = Calendar(identifier: .gregorian)
let chinese = Calendar(identifier: .chinese)

它有提取日期时间组成的方法:

例如:

func dateComponents(_:from:) -> DateComponents
func component(_:from:) -> Int

示例:

let now = Date()
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.year, .month, .day], from: now)
// 或
let year = calendar.component(.year, from: now)

下面是它所有的方法汇总:

方法签名作用返回类型是否支持自定义 TimeZone
func date(from: DateComponents) -> Date?用日期组件构建 DateDate?✅(通过 DateComponents.timeZone
func dateComponents(_ comps: Set<Calendar.Component>, from: Date) -> DateComponents提取单个日期的组成部分DateComponents✅(使用 Calendar.timeZone
func dateComponents(_ comps: Set<Calendar.Component>, from: Date, to: Date) -> DateComponents计算两个日期之间的差值DateComponents✅(使用 Calendar.timeZone
func dateComponents(in: TimeZone, from: Date) -> DateComponents用指定时区提取日期组件DateComponents✅(显式参数)
func component(_ component: Calendar.Component, from: Date) -> Int提取单个时间单位Int
func isDate(_ date1: Date, equalTo: Date, toGranularity: Calendar.Component) -> Bool判断两个日期在某个单位是否相等Bool
func isDateInToday(_ date: Date) -> Bool是否是今天Bool
func isDateInTomorrow(_ date: Date) -> Bool是否是明天Bool
func isDateInYesterday(_ date: Date) -> Bool是否是昨天Bool
func isDateInWeekend(_ date: Date) -> Bool是否在周末Bool
func nextDate(after: Date, matching: DateComponents, matchingPolicy: MatchingPolicy) -> Date?查找下一个匹配的日期(如下一个 10 点)Date?
func date(byAdding component: Calendar.Component, value: Int, to: Date) -> Date?增加时间(如 +3 天)Date?
func date(byAdding: DateComponents, to: Date) -> Date?增加多个组件(如 +3天 +2小时)Date?
func startOfDay(for: Date) -> Date获取一天的开始Date
func range(of: Calendar.Component, in: Calendar.Component, for: Date) -> Range<Int>?某单位在上一级单位中的范围(如某月有几天)Range<Int>?
func ordinality(of: Calendar.Component, in: Calendar.Component, for: Date) -> Int?获取某单位在上一级单位中的序号(如今天是本月第几天)Int?
func compare(_ date1: Date, to date2: Date, toGranularity: Calendar.Component) -> ComparisonResult比较两个日期在某单位的大小关系ComparisonResult

方法类型分类

类别方法举例
创建/生成date(from:), date(byAdding:), nextDate(after:)
提取组件dateComponents(...), component(...)
判断属性isDateInToday(...), isDateInWeekend(...)
比较关系isDate(_:equalTo:toGranularity:), compare(...)
范围信息range(of:in:for:), ordinality(of:in:for:)

日期转字符串

如果您有一个 Date 对象,您可能需要以一种用户友好的格式显示它。值得庆幸的是,Swift 提供了多种将日期格式化为字符串的方法,允许您根据特定需求定制输出,例如 2023 年 11 月 1 日或 2023 年 11 月 1 日。

您可以使用 DateFormatter 类将日期转换为字符串表示形式:

// Change the date format
let currentDate = Date()

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let formattedDate = dateFormatter.string(from: currentDate)
print(formattedDate)

Date 结构体

Date 表示从参考点(2001-01-01 00:00:00 UTC)起经过的秒数

它与calendar的区别是:

它表示一个精确的时间点(绝对时间),而 Calendar 是用来解释和操作这个时间点的工具,它将 Date 映射为“人类可读”的时间单位(年、月、日、时、分等),考虑时区和历法差异。

本文使用 「Markdown 在线编辑器 | 公众号内容排版工具」 排版