ISO8601 UTC日期字符串转Swift Date的格式化困惑咨询
问题根源:误解了Swift
Date对象的本质 你犯的核心错误是对Swift的Date类型理解有误——Date本质是一个UTC时间戳,它不存储任何时区信息。它只代表「世界标准时间中的某一个绝对时刻」,时区的处理只发生在「把Date转成人类可读的字符串」(格式化)或者「把字符串转成Date」(解析)这两个环节。
你的错误操作拆解
你在dateFromUTCString里的逻辑完全是画蛇添足:
- 用
isoDateFormatter.date(from: dateString)解析UTC字符串,得到的Date已经是正确的——它对应UTC的2023-03-13T23:00:00Z,也就是AEDT时区的2023-03-14T10:00:00。 - 但你之后手动加上了本地时区的偏移量:
Date(timeInterval: localOffset, since: date),这相当于把这个绝对时刻往后推了11小时(AEDT比UTC快11小时),得到的新Date对应的UTC时刻变成了2023-03-14T10:00:00Z,对应本地时间就是2023-03-14T21:00:00(也就是9PM),这就是你格式化得到错误结果的原因。
修正后的代码
只需要删掉dateFromUTCString中手动调整时区偏移的逻辑,直接返回解析后的Date即可:
//发送到服务器的原日期为AEDT时区3月14日上午10:00 //通过以下代码转换为UTC /** let isoDateFormatter = ISO8601DateFormatter() isoDateFormatter.timeZone = TimeZone(abbreviation: "UTC") self.date = isoDateFormatter.string(from: data.date) */ //使用的格式化器 private let isoDateFormatter: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] formatter.timeZone = TimeZone(identifier: "UTC") return formatter }() //以下测试输入为UTC时区的ISO8601格式日期 //在Playground中运行 let dateString = "2023-03-13T23:00:00.000Z" let dateString2 = "2023-03-13T23:00:00.000+00:00" func dateFromUTCString(_ dateString: String) -> Date? { // 直接返回解析后的Date,不需要手动调整时区偏移 return isoDateFormatter.date(from: dateString) } func formattedDate(from date: Date?) -> String { guard let date = date else {return "no date"} let f = DateFormatter() // 不需要设置UTC时区,默认使用当前时区(AEDT) f.dateFormat = "dd MMM yyyy 'at' h:mm a" return f.string(from: date) // 现在会正确输出:14 Mar 2023 at 10:00 AM }
验证逻辑
- 解析
"2023-03-13T23:00:00.000Z"得到的Date,代表的是UTC时间2023-03-13 23:00:00。 DateFormatter默认使用当前时区(AEDT,比UTC快11小时),所以格式化时会自动计算出本地时间:2023-03-14 10:00:00,也就是你想要的正确结果。
内容的提问来源于stack exchange,提问作者Minon Weerasinghe
相关产品推荐
相关产品推荐

