Swift日期和时间(一)

2,364 阅读6分钟

参考 introduction date time programming swift

image.png

Date

Swift 使用Date来表示日期和时间。

Date对象存储一个 Double 值,表示相对 2001-1-1 00:00:00 UTC 的秒数

正值表示参考点之后的日期和时间,而负值表示参考点之前的日期和时间。

import UIKit

let momentInTime = Date() // 当前日期和时间
print(momentInTime.description)

输出结果

2023-06-26 13:00:14 +0000 // 默认UTC时间格式

以字符串形式返回日期和时间,格式为日期-时间-时区

Date 属性

  • timeIntervalSinceNow 返回date对象与当前时间间隔的秒数。如果date是过去的,则为负数。
  • timeIntervalSinceReferenceDate 返回date与2001-1-1 00:00:00 UTC间隔的秒数。如果date是过去的,则为负数。
  • timeIntervalSince1970 返回date与1970-1-1 00:00:00 UTC间隔的秒数。
let momentInTime = Date().addingTimeInterval(1000)

let secondsAgo = momentInTime.timeIntervalSinceNow
print("距离现在  \(secondsAgo)秒")
let secondsSinceReferenceDate = momentInTime.timeIntervalSinceReferenceDate
print("距离2001-01-01  \(secondsSinceReferenceDate)秒")
let secondsSinceUnixEpochDate = momentInTime.timeIntervalSince1970
print("距离1970-01-01  \(secondsSinceUnixEpochDate)秒")
距离现在  999.9940940141678秒
距离2001-01-01  709482189.537294秒
距离1970-01-01  1687789389.537294秒

Locale

Date有个方法,根据Locale以字符串形式返回日期和时间值。

print(momentInTime.description(with: Locale(identifier: "zh-Hans")))  // 中国
print(momentInTime.description(with: Locale(identifier: "en-US")))    // 美国
print(momentInTime.description(with: Locale(identifier: "en-GB")))    // 英国
print(momentInTime.description(with: Locale(identifier: "es")))       // 西班牙
2023年6月26日 星期一 中国标准时间 下午10:23:09
Monday, June 26, 2023 at 10:23:09 PM China Standard Time
Monday, 26 June 2023 at 22:23:09 China Standard Time
lunes, 26 de junio de 2023, 22:23:09 (hora estándar de China)

以四种区域的语言打印出来。

Date初始化

下面是四种初始化方式, 当前时间, 2001-01-01, 1970-01-01, 指定日期 + 指定秒数

var userLocale = Locale.autoupdatingCurrent

// 当前时间向前或向后指定的秒数
let fiveSecondsAgo = Date(timeIntervalSinceNow: -5)
let eightMinutesFromNow = Date(timeIntervalSinceNow: 8 * 60)

print("5秒前: \(fiveSecondsAgo.description(with: userLocale)).")
print("8分钟后: \(eightMinutesFromNow.description(with: userLocale)).")

// 2001-01-01 后指定秒数
let iPhoneStevenoteSwiftInterval = 190_058_400.0
var iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: iPhoneStevenoteSwiftInterval)
print("iPhone 发布的时间: \(iPhoneStevenoteDate.description(with: userLocale)).")

// 1970-01-01 后指定秒数
let iPadStevenoteUnixInterval = 1_264_615_200.0
var iPadStevenoteDate = Date(timeIntervalSince1970: iPadStevenoteUnixInterval)
print("iPad发布时间: \(iPadStevenoteDate.description(with: userLocale)).")

// 相对指定的日期
let appleSiliconTimnoteIPadStevenoteInterval = 328_230_000.0
var appleSiliconTimnoteDate = Date(
    timeInterval: appleSiliconTimnoteIPadStevenoteInterval,
    since: iPadStevenoteDate
)
print("Apple Silicon发布时间: \(appleSiliconTimnoteDate.description(with: userLocale)).")
5秒前: 2023年6月26日 星期一 中国标准时间 下午10:50:06.
8分钟后: 2023年6月26日 星期一 中国标准时间 下午10:58:11.
iPhone 发布的时间: 2007年1月10日 星期三 中国标准时间 上午2:00:00.
iPad发布时间: 2010年1月28日 星期四 中国标准时间 上午2:00:00.
Apple Silicon发布时间: 2020年6月23日 星期二 中国标准时间 上午1:00:00.

DateFormatter初始化Date

我们以北京奥运会开幕式开始的时间: 2008年8月8日下午8时为例子

var userLocale = Locale.autoupdatingCurrent

let myDateFormatter = DateFormatter()

// http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns 查看更多格式
myDateFormatter.dateFormat = "y年M月d日aah时"
var beijinggDate = myDateFormatter.date(from: "2008年8月8日下午8时")!

print("北京奥运会开幕时间: \(beijinggDate.description(with: userLocale)).")
北京奥运会开幕时间: 2008年8月8日 星期五 中国标准时间 下午8:00:00.

DateFormatter日期格式

  • y: 年(1-4位数字)
  • yy: 年的后2位
  • yyyy: 完整年(4位数字: 0001)
  • M: 月(显示1-12)
  • MM: 月(显示01-12)
  • MMM: 月,英文月份简写,如 Jan
  • MMMM: 月,显示为英文月份全称,如 January
  • d: 日,1-2位显示,如 2
  • dd: 日,2位数表示,如02
  • D/DD/DDD: 表示一年中的第几天
  • h/hh: 12小时制
  • H/HH: 时,24小时制,0-23
  • m/mm: 分数
  • s/ss: 秒
  • S:毫秒
  • aa: 上/下午,AM/PM
  • EEE: 简写星期几,如Sun
  • EEEE: 全写星期几,如Sunday
  • W: 表示一个月中的第几周
  • w/ww 表示一年中的第几周

常用日期结构:

yyyy-MM-dd HH:mm:ss.SSS

yyyy-MM-dd HH:mm:ss

yyyy-MM-dd

MM dd yyyy

更多格式可以参考 Date_Format_Patterns

Calendar

日历可以想象成一把尺子,放在时间系统旁边,提供日期计算的上下文。大多数情况下,使用公历; 除公历外,还支持其他 15 种历法系统,包括佛教历和希伯来历

print("当前日历: \(Calendar.current).")
print("当前日历的时区是: \(Calendar.current.timeZone) ")
当前日历: gregorian (current)
当前日历的时区是: Asia/Shanghai (current)

DateComponents

DateComponents 让我们组装和分解Date, 有如下组成单位

  • day: 日期的天
  • hour: 小时数
  • minute 分钟数
  • month 月份编号
  • quarter 季度编号
  • second
  • timeZone 时区, 这将取决于所用日历的时区。
  • weekday 星期几
  • weekOfMonth 月份中的第几周
  • weekOfYear 年份中的第几周
  • year

下面是组装Date的例子

let userLocale = Locale.autoupdatingCurrent
var gregorianCalendar = Calendar(identifier: .gregorian) // 公历
gregorianCalendar.locale = userLocale

let beijingComponents = DateComponents(
  calendar: gregorianCalendar,
  timeZone: TimeZone.current, // 指定时区
  year: 2008,
  month: 8,
  day: 8,
  hour: 20,
  minute: 00
)
let beijingDate = gregorianCalendar.date(from: beijingComponents)!
print("北京奥运会开幕时间: \(beijingDate.description(with: userLocale)).")

组装2023年第10000小时

let tenThousandHoursComponents = DateComponents(
    year: 2023,
    hour: 10000
)
let tenThousandHoursInto2023Date = Calendar.current.date(from: tenThousandHoursComponents)!
print("2023年的第10000小时 \(tenThousandHoursInto2023Date.description(with: Locale.current)).")
print("UTC时间: \(tenThousandHoursInto2023Date.description).")
2023年的第10000小时 2024年2月21日 星期三 中国标准时间 下午4:00:00.
UTC时间: 2024-02-21 08:00:00 +0000.

2023年第 33 周的星期四是哪一天?

let thursday33rdWeek2023Components = DateComponents(
    year: 2023,     // 2023年
    weekOfYear: 33, // 一年的第33个星期
    weekday: 5      // 星期四
)
let thursday33rdWeek2023Date = gregorianCalendar.date(from: thursday33rdWeek2023Components)!
print("2023年第33周的星期四: \(thursday33rdWeek2023Date.description(with: userLocale)).")

分解Date

从Date中分解出年月日时分秒这些小的单位

let nowDate = Date()

var nowDateComponents = Calendar.current.dateComponents(
    [
        .calendar,
        .day,
        .era,
        .hour,
        .minute,
        .month,
        .nanosecond,
        .quarter,
        .second,
        .timeZone,
        .weekday,
        .weekdayOrdinal,
        .weekOfMonth,
        .weekOfYear,
        .year,
        .yearForWeekOfYear
    ],
    from: nowDate
)
print("Calendar: \(nowDateComponents.calendar!.identifier)")
print("Day: \(nowDateComponents.day!)")
print("Era: \(nowDateComponents.era!)")
print("Hour: \(nowDateComponents.hour!)")
print("Minute: \(nowDateComponents.minute!)")
print("Month: \(nowDateComponents.month!)")
print("Nanosecond: \(nowDateComponents.nanosecond!)")
print("季度: \(nowDateComponents.quarter!)")
print("Second: \(nowDateComponents.second!)")
print("时区: \(nowDateComponents.timeZone!)")
print("Weekday: \(nowDateComponents.weekday!)")
print("Weekday ordinal: \(nowDateComponents.weekdayOrdinal!)")
print("Week of month: \(nowDateComponents.weekOfMonth!)")
print("Week of year: \(nowDateComponents.weekOfYear!)")
print("Year: \(nowDateComponents.year!)")
print("Year for week of year: \(nowDateComponents.yearForWeekOfYear!)")
Calendar: gregorian
Day: 27
Era: 1
Hour: 22
Minute: 37
Month: 6
Nanosecond: 125563979
季度: 0
Second: 14
时区: Asia/Shanghai (current)
Weekday: 3
Weekday ordinal: 4
Week of month: 5
Week of year: 26
Year: 2023
Year for week of year: 2023