Swift 中的日期和时间处理:高级技巧

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 中日期和时间的高级处理



日期和时间处理是 iOS/macOS 开发中的关键任务之一。在基础层面上,大多数开发者都熟悉 Date、DateFormatter 和 Calendar。然而,在高级层面上会出现复杂的场景:时区处理、解析数百个日期时的高性能要求、相对时间的正确显示以及自定义格式的处理。在本文中,我们将深入探讨 Swift 中日期处理的高级技巧,帮助您编写更可靠、更高效的代码。



1. 日期解析优化:DateFormatter vs ISO8601DateFormatter



最常见的操作之一是将字符串转换为日期。标准的 DateFormatter 使用方便,但创建它的成本很高。如果您在循环中解析数百个日期,每次调用 DateFormatter() 都会创建一个新对象,从而导致性能下降。



问题:在循环中创建 DateFormatter

// ❌ 不好:在循环中创建格式化器for dateString in dateStrings {    let formatter = DateFormatter()    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"    if let date = formatter.date(from: dateString) {        // 处理    }}


解决方案:缓存和 ISO8601DateFormatter

对于 ISO 8601 格式,请使用 ISO8601DateFormatter——它更快且线程安全。对于自定义格式,请创建一次格式化器并重复使用。



// ✅ 好:缓存格式化器private let isoFormatter: ISO8601DateFormatter = {    let formatter = ISO8601DateFormatter()    formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]    return formatter}()

// 对于自定义格式private let customFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "dd.MM.yyyy HH:mm" formatter.locale = Locale(identifier: "ru_RU") formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter}()

func parseDates(_ strings: [String]) -> [Date] { return strings.compactMap { isoFormatter.date(from: $0) }}


重要提示: DateFormatter 不是线程安全的。如果您处理多线程,请使用 Thread.current 或为每个线程创建单独的格式化器。



2. 时区和 DateComponents 的处理



高级日期处理需要考虑时区。Swift 中的 Date 是一个绝对时间点(自 2001 年 1 月 1 日以来的秒数)。所有时区信息都存在于 Calendar 和 DateFormatter 中。



在特定时区中提取日期组件

let date = Date()let calendar = Calendar.currentlet timeZone = TimeZone(identifier: "America/New_York")!

// 获取指定时区的组件var components = calendar.dateComponents(in: timeZone, from: date)components.hour // 纽约的小时components.day // 纽约的日期

// 从组件创建日期并显式指定时区var newComponents = DateComponents()newComponents.year = 2024newComponents.month = 12newComponents.day = 25newComponents.hour = 10newComponents.minute = 30newComponents.timeZone = TimeZone(identifier: "Europe/Moscow")

let christmasDate = calendar.date(from: newComponents)print(christmasDate!) // 2024-12-25 07:30:00 +0000 (UTC)


考虑日历的日期比较

使用 compare(_:to:toGranularity:) 进行精确到天、小时或分钟的比较:



let date1 = Date()let date2 = Date().addingTimeInterval(3600) // +1 小时

let result = calendar.compare(date1, to: date2, toGranularity: .hour)// .orderedSame,如果在同一小时内// .orderedAscending,如果 date1 更早

博客

书籍推荐