3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSでの日付設定(dateBySettingUnit)

Last updated at Posted at 2015-10-24

EventKitを使う準備として日付の操作を試していていて気づいた注意点です。
日付を設定する時に以前は、NSDateのイニシャライザに

onvenience init?(string description: String)

というメソッドが用意されていましたが、OSX10.10 でdepriciated になってしまいました。現在 NSDate クラスで日付を設定するために使用できるイニシャライザは、

  • init(timeIntervalSinceNow secs: NSTimeInterval)
  • init(timeInterval secsToBeAdded: NSTimeInterval,
    sinceDate date: NSDate)
  • init(timeIntervalSinceReferenceDate ti: NSTimeInterval)
  • init(timeIntervalSince1970 secs: NSTimeInterval)

になり、全て特定の日付からの TimeInterval での指定になりました。
従って必要な日付のNSDateインスタンスは、 NSDate() でそのときの日付時刻を得て、そこからNSCalendar のメソッドを使って欲しい日付のNSDate インスタンスを得る方法にほぼ限定されています。
これに使用できそうなNSCalendar のメソッドは

  • dateByAddingComponents:toDate:options:
  • dateByAddingUnit:value:toDate:options:
  • dateFromComponents:
  • dateBySettingHour:minute:second:ofDate:options:
  • dateBySettingUnit:value:ofDate:options:

といったところです。
この中で dateBySettingUnit:value:ofDate:option: は注意が必要です。Class Reference では与えられた日付のコンポーネントを与えられた値に設定すると説明されていますが、このメソッドの実行結果は与えられた日付よりも後の日付にしかなりません。

date.swift
var myCalendar = NSCalendar.currentCalendar()

let today = NSDate()
// "Oct 24, 2015, 9:43 PM"
var day1 = myCalendar.dateBySettingUnit(NSCalendarUnit.Day, value: 1, ofDate: today, options: NSCalendarOptions())
// "Nov 1, 2015, 12:00 AM"
var day30 = myCalendar.dateBySettingUnit(NSCalendarUnit.Day, value: 30, ofDate: today, options: NSCalendarOptions())
// "Oct 30, 2015, 12:00 AM"
var day20 = myCalendar.dateBySettingUnit(NSCalendarUnit.Day, value: 20, ofDate: today, options: NSCalendarOptions())
// "Nov 20, 2015, 12:00 AM"
day1 = myCalendar.dateBySettingUnit(NSCalendarUnit.Month, value: 1, ofDate: day1!, options: NSCalendarOptions())
// "Jan 1, 2016, 12:00 AM"
day1 = myCalendar.dateBySettingUnit(NSCalendarUnit.Year, value: 2015, ofDate: day1!, options: NSCalendarOptions())
// nil
let firstDayOf2015Comp = NSDateComponents()
firstDayOf2015Comp.day = 1
firstDayOf2015Comp.month = 1
firstDayOf2015Comp.year = 2015
day1 = myCalendar.dateFromComponents(firstDayOf2015Comp)
// "Jan 1, 2015, 12:00 AM"

上の例のday1のように10月24日の日付に対して"Day" を1に設定すると11月1日になります。day30のように10月24日に対して"Day"を30にすると10月30日になります。day20 のように10月24日の"Day"を20にすると11月20日になります。11月1日になっているday1 の"Month" を1に設定すると2016年1月1日になります。さらにこのday1の"Year" を2015に設定すると nil になってしまいます。2016年以後に2015年にはならないのでnilになってしまいます。
ということで、日付を設定する時には例えばNSDate() を基準にして、

  • dateByAddingComponents:toDate:options:
  • dateByAddingUnit:value:toDate:options:

を使用する方がよいようです。
なお、例の最後にあるようにNSDateComponets で日付コンポーネントを用意してやれば、

  • dateFromComponents:

で直接日付を設定することができます。
DateByAddingComponets を使うと、月初めの日付から月末の日付を得るには、NSDateComponets インスタンスの month に1、day に-1 を設定して
dateByAddingComponents を使うと簡単に計算できます。

endOfMonth.swift
let endOfMonthComp = NSDateComponents()
endOfMonthComp.month = 1
endOfMonthComp.day = -1

let endOfMonth = myCalendar.dateByAddingComponents(endOfMonthComp, toDate: day1!, options: NSCalendarOptions())
// "Jan 31, 2015, 12:00 AM"
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?