简体   繁体   English

Swift:设置DateComponents年时的意外行为

[英]Swift: unexpected behavior when setting DateComponents year

The example code below gets DateComponents from the current Date, modifies the components, and creates a new Date from the modified components. 下面的示例代码从当前Date获取DateComponents,修改组件,并从修改的组件创建新Date。 It also shows creating a new DateComponents object, filling it out, and then creating a new Date from that. 它还显示了创建一个新的DateComponents对象,填充它,然后从中创建一个新的Date。

import Foundation

let utcHourOffset = -7.0
let tz = TimeZone(secondsFromGMT: Int(utcHourOffset*60.0*60.0))!
let calendar = Calendar(identifier: .gregorian)
var now = calendar.dateComponents(in: tz, from: Date())

// Get and display current date
print("\nCurrent Date:")
print("\(now.month!)/\(now.day!)/\(now.year!) \(now.hour!):\(now.minute!):\(now.second!)   \(now.timeZone!)")
let curDate = calendar.date(from: now)
print("\(curDate!)")

// Modify and display current date
now.year = 2010
now.month = 2
now.day = 24
now.minute = 0
print("\nModified Date:")
print("\(now.month!)/\(now.day!)/\(now.year!) \(now.hour!):\(now.minute!):\(now.second!)   \(now.timeZone!)")
let modDate = calendar.date(from: now)
print("\(modDate!)")

// Create completely new date
var dc = DateComponents()
dc.year = 2014
dc.month = 12
dc.day = 25
dc.hour = 10
dc.minute = 12
dc.second = 34
print("\nNew Date:")
print("\(dc.month!)/\(dc.day!)/\(dc.year!) \(dc.hour!):\(dc.minute!):\(dc.second!)   \(now.timeZone!)")
let newDate = calendar.date(from: dc)
print("\(newDate!)")

In the case where I modify the components, setting different year, month, day, etc., then use the components to get a date, I get the unexpected result that the new date has all the modified components except the year, which remains unchanged. 在我修改组件,设置不同的年,月,日等的情况下,然后使用组件来获取日期,我得到意外的结果,即新日期具有除年份之外的所有修改组件,其保持不变。

In the case where I create a DateComponents object and fill it out then create a Date from it, it works as expected. 在我创建一个DateComponents对象并填充它然后从中创建一个Date的情况下,它按预期工作。

The output of the code is shown below: 代码的输出如下所示:

Current Date:
3/9/2017 19:5:30   GMT-0700 (fixed)
2017-03-10 02:05:30 +0000

Modified Date:
2/24/2010 19:0:30   GMT-0700 (fixed)
2017-02-25 02:00:30 +0000

New Date:
12/25/2014 10:12:34   GMT-0700 (fixed)
2014-12-25 17:12:34 +0000

I expected the modified Date to be 2010-02-25 02:00:30 +0000 rather than 2017-02-25 02:00:30 +0000 . 我预计修改日期为2010-02-25 02:00:30 +0000而不是2017-02-25 02:00:30 +0000 Why isn't it? 为什么不呢? Why does it work in the second case? 为什么它适用于第二种情况?

The docs for DateComponents say: "An instance of NSDateComponents is not responsible for answering questions about a date beyond the information with which it was initialized...". DateComponents的文档说:“NSDateComponents的一个实例不负责回答有关超出初始化信息的日期的问题......”。 Being that the DateComponents object was initialized with a year, it doesn't seem like this would apply, but it's the only thing I saw in the docs that might explain the behavior I observe. 由于DateComponents对象是用一年初始化的,所以它似乎不适用,但这是我在文档中看到的唯一可以解释我观察到的行为的东西。

If you log now and dc you will see the problem. 如果您now登录dc您将看到问题。 now is being created from a Date . now正在从Date创建。 This fills in all of the date components including yearForWeekOfYear and several of the weekday related components. 这将填写所有日期组件,包括yearForWeekOfYear和几个与工作日相关的组件。 These components are causing modDate to come out incorrectly. 这些组件导致modDate错误地出现。

newDate works as expected because only the specific components are being set. newDate按预期工作,因为只设置了特定的组件。

You can get modDate to come out correctly if you reset some of the extra components. 如果重置一些额外组件,可以让modDate正确显示。 Specifically, adding: 具体来说,添加:

now.yearForWeekOfYear = nil

just before creating modDate will result in the expected date for modDate . 之前创建modDate将导致预期的日期modDate Of course the best solution is to create a new instance of DateComponents and use specific values from the previous DateComponents as needed: 当然,最好的解决方案是创建DateComponents的新实例,并根据需要使用之前DateComponents特定值:

let mod = DateComponents()
mod.timeZone = now.timeZone
mod.year = 2010
mod.month = 2
mod.day = 24
mod.hour = now.hour
mod.minute = 0
mod.second = now.second
print("\nModified Date:")
print("\(mod.month!)/\(mod.day!)/\(mod.year!) \(mod.hour!):\(mod.minute!):\(mod.second!)   \(mod.timeZone!)")
let modDate = calendar.date(from: mod)
print("\(modDate!)")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM