日期组件似乎不尊重年份



我正试图将Date转换为DateComponents,更改一些属性,并获得新的Date。我写了下面的代码:

import Foundation
var components = Calendar.current.dateComponents(in: .current, from: Date())
components.day = 7
components.month = 3
components.year = 1900
DateFormatter.localizedString(from: components.date!, dateStyle: .long, timeStyle: .long)

我在iOS 15.0上的iOS模拟器上的America/Denver时区/区域以及运行最新macOS Big Sur和Xcode 13.0的Mac上的Swift REPL中测试了这一点,在这两个地方,我在撰写本文时得到了大约以下输出:

March 7, 2021 at 9:38:13 AM MST

除了年份之外,这一切都在预料之中。我已经明确地将年份设置为1900,但是输出中的年份是2021。我如何使DateComponents在生成日期时尊重年份,或者我如何手动做同样的事情,以便它实际工作?

如果你得到all组件从日期与dateComponents(in:from:),你必须也设置相应的yearForWeekOfYear

components.yearForWeekOfYear = 1900

或者只指定您真正需要的日期和时间组件,包括calendartimeZone,例如

var components = Calendar.current.dateComponents([.calendar, .timeZone, .year, .month, .day, .hour, .minute, .second], from: Date())
components.day = 7
components.month = 3
components.year = 1900
DateFormatter.localizedString(from: components.date!, dateStyle: .long, timeStyle: .long)

注意,您将获得所有日期组件,包括weekOfYearweekOfMonthdayOfWeek,以及最重要的yearForWeekOfYear。当您将日期组件设置为1900-03-07时,您也没有正确设置所有这些组件,并且当从具有此类冲突组件的DateComponents解析Date时,算法恰好更倾向于从yearForWeekOfYear获得的年份。

如果您将这些字段设置为nil,您将得到预期的结果:

var components = Calendar.current.dateComponents(in: .current, from: Date())
components.day = 7
components.month = 3
components.year = 1900
components.yearForWeekOfYear = nil

在日期组件中仍然会有冲突,虽然这不会导致崩溃,但我不确定这种行为将来是否会改变。我建议您只获取所需的组件。例如:

var components = Calendar.current.dateComponents([
.calendar, .timeZone, .era, .year, .month, .day, .hour, .minute, .second, .nanosecond
], from: Date())