NSCalendar - 2つの日付間の日数を取得する

2010年7月31日土曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

例えば 2010/07/25 と 7/27 の間の日数は2日と返すようなメソッドを作る。

実装


DateUtility というクラスを作り、そこへクラスメソッドを実装する。
@interface DateUtility : NSObject {
}
+ (NSInteger)daysBetween:(NSDate*)startDate and:(NSDate*)endDate;

+ (NSDate*)adjustZeroClock:(NSDate*)date withCalendar:(NSCalendar*)calendar
{
 NSDateComponents *components =
  [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
     fromDate:date];
 return [calendar dateFromComponents:components];
}

+ (NSInteger)daysBetween:(NSDate*)startDate and:(NSDate*)endDate
{
 NSCalendar *calendar = [[NSCalendar alloc]
        initWithCalendarIdentifier:NSGregorianCalendar];
 startDate = [DateUtility adjustZeroClock:startDate withCalendar:calendar];
 endDate = [DateUtility adjustZeroClock:endDate withCalendar:calendar];

 NSDateComponents *components = [calendar components:NSDayCalendarUnit
              fromDate:startDate
             toDate:endDate
            options:0];
 NSInteger days = [components day];

 [calendar release];
 
 return days;
}

NSCalendar を使うと2つの日付間の日数を簡単に取得できる。ポイントとしては +adjustZeroClock:withCalendar: を使い、時刻を 0:00 に合わせていること。これをやらないと日時まで含めた比較となってしまう。
(例)7/25 11:00〜7/27 9:00 のケース
  [A] 時刻補正なし:1日となる。
  [B] 時刻補正あり:2日となる。
補正が不要であれば +ajdustZeroClock:withCalendar: の呼出をやめる。

なお -[NSCalendar components:fromDate:toDate:options:] の最初に引数に NSMonthCalendarUnit を含めると、結果は日数ではなく月数+日数の組み合わせになるので注意が必要。
(例)7/10〜8/19の日のケース
  [A] NSDayCalendarUnit|NSMonthCalendarUnit
   [components month] == 1
   [components day]   == 10

  [B] NSDayCalendarUnit
   [components day]   == 40

参考情報

NSDate Class Reference
NSDateのリファレンス
NSCalendar Class Reference
NSCalendarのリファレンス
NSDateComponents Class Reference
NSDateComponentsのリファレンス
Date and Time Programming Guide
日付関連クラスの解説

Responses

  1. 匿名
    2012年11月11日 1:24

    とても参考になりました。ありがとうございます!
    ビルドしてみたらエラーになりましたが
    メソッド名の
    and:

    別のラベルにしたらOKでした。
    andって予約後でしたっけね。

  2. 匿名
    2012年11月11日 1:24

    とても参考になりました。ありがとうございます!
    ビルドしてみたらエラーになりましたが
    メソッド名の
    and:

    別のラベルにしたらOKでした。
    andって予約後でしたっけね。

  3. 匿名
    2012年11月11日 1:32

    同投稿者です。
    andがだめだったのは、自分の環境では
    Objective-C++にしてたからでした。いやいやすいません。。
    C++だとandは予約語なんですね。

  4. 匿名
    2012年11月11日 1:32

    同投稿者です。
    andがだめだったのは、自分の環境では
    Objective-C++にしてたからでした。いやいやすいません。。
    C++だとandは予約語なんですね。

Leave a Response

人気の投稿(過去 30日間)