iOS日付に関する操作

もうひとつのプロフェッショナルプログラマーからの転載です。
Objective-C で日付などを扱うには, NSDateを使いました。

今回は, 日付に関して, 以前ColorDosというアプリを開発していたときに出てきた副産物を公開します。

Samples

  • 月初めって何曜日?
  • 今月は何日まであるのか?
  • 先月末の日付をとってこよう
  • 1か月後の日付をとってこよう

ここで扱う[NSDate date]はGMT時間ですよ。

月初めって何曜日?

– まず, 月はじめが欲しい日付(たとえば今日とか)の日付を NSDate * でとってくる
– NSDateComponents で,現地時間を取得
– その現地時間に 日付の1をセット
– それをもとにもう一度 NSDate * をつくる
– NSDateComponents を再度つくり, 要素に NSWeekdayCalendarUnit を入れる
– NSDateComponents の weekday で, 今日が何番目の曜日かを取得
(1:日曜日 ~ 7:土曜日)

NSDate *date = [NSDate date];                    // 現在の GMT時間
NSDateComponents *comps;
NSCalendar *calendar = [NSCalendar currentCalendar];
comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit fromDate:date];
[comps setDay:1];

NSDate *d = [calendar dateFromComponents:comps];
comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit fromDate:d];
int week_day = [comps weekday];

今月は何日まであるのか?

– NSCalendar で, 日付などのlimitationがどこまであるかを表す rangeOfUnit
を利用する
– NSRange の length で最終日を取得できる

NSDate *date = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSRange range = [cal rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:date];
int last =  range.length;

先月末の日付を取ってこよう

※ある種のテクニックですね
– NSDateComponents で, 年, 月を取得しておきます
– 新しいNSDateComponentsをつくって, setDay で -1 を入れます
– これをもとに, NSDate *をつくります

NSDate *date = [NSDate date];
NSDateComponents *comps;
NSCalendar *calendar = [NSCalendar currentCalendar];
comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit fromDate:date];
NSInteger year = [comps year];
NSInteger month = [comps month];
NSDateComponents *ret_comps = [[NSDateComponents alloc] init];
[ret_comps setYear:year];
[ret_comps setMonth:month];
[ret_comps setDay:-1];
//[ret_comps setHour:0];
//[ret_comps setMinute:0];
//[ret_comps setSecond:0];
NSDate *prevMonth =  [calendar dateFromComponents:ret_comps];

1か月後の日付をとってこよう

※うまい方法が見つからなかったので, 地道に場合分けでmonthが 12 ならしゃーなしで。

NSDateComponents *comps;
NSCalendar *calendar = [NSCalendar currentCalendar];
comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit fromDate:date];
NSInteger year = [comps year];
NSInteger month = [comps month];
NSInteger day = [comps day];
   
NSDateComponents *ret_comps = [[NSDateComponents alloc] init];
   
if ( month == 12 )
{
    month = 1;
    year++;
}
else
{
    month++;
}
[ret_comps setYear:year];
[ret_comps setMonth:month];
[ret_comps setDay:day];
[ret_comps setHour:0];
[ret_comps setMinute:0];
[ret_comps setSecond:0];
NSDate *next =  [calendar dateFromComponents:ret_comps];