2017-03-10 9 views
1

以下のサンプルコードは、現在のDateからDateComponentsを取得し、コンポーネントを変更し、変更されたコンポーネントから新しいDateを作成します。また、新しいDateComponentsオブジェクトを作成し、それを埋め込み、それから新しいDateを作成することも示しています。Swift:DateComponents年の設定時の予期しない動作

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!)") 
私は別の年に設定し、コンポーネントを変更する場合には

、月、日、など、日付を取得するためにコンポーネントを使用し、私は新しい日付が変更されたすべてのコンポーネントを持っていることを予期しない結果を得ます変わらない年を除いて。

DateComponentsオブジェクトを作成して記入してからDateを作成する場合、期待通りに機能します。

コードの出力を以下に示す:

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が修正日付2010-02-25 02:00:30 +0000なく2017-02-25 02:00:30 +0000ことが期待。それはなぜですか?なぜ2番目のケースでうまくいくのですか?

DateComponentsのdocsは、「NSDateComponentsのインスタンスは、初期化された情報以外の日付についての質問に答える責任がありません...」と述べています。 DateComponentsオブジェクトは1年で​​初期化されていたので、これは当てはまるようには見えませんでしたが、私が観察した振る舞いを説明する可能性のある唯一の文書です。

答えて

1

nowdcを記録すると、問題が表示されます。 nowDateから作成されています。これにより、yearForWeekOfYearなどのすべての日付コンポーネントと、平日関連コンポーネントのいくつかが埋められます。これらのコンポーネントにより、modDateが正しく出力されません。

newDateは、特定のコンポーネントのみが設定されているため、正常に動作します。

余分なコンポーネントの一部をリセットすると、modDateが正しく出力されることがあります。具体的には、追加:

now.yearForWeekOfYear = nil 

をちょうどmodDateための予定日になりますmodDateを作成する前に。もちろん、最善の解決策は、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!)")