忘備録

日々の調べ物をまとめる。アウトプットする。基本自分用。

【Objective-C】NSDateFormatterにまつわるエトセトラ

NSDateFormatterでやらかしそうなやらかしたミスをメモっておく。

24時間表示をOFFにした際、dateFromStringによる正しく評価されない

前提として、「設定」>「一般」>「日付と時刻」>「24時間表示」 をOFFにしているものとします。

やらかした例

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
     NSDate *theDay = [formatter dateFromString:@"2013/09/01 15:00:00"];
    
    NSLog(@"%@", [theDay descriptionWithLocale:[NSLocale currentLocale]]);

コンソール出力

(null)

Oops...

正しい実装

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
    [formatter setLocale:[NSLocale systemLocale]]; // ロケールにsystemLocaleを設定する
    NSDate *theDay = [formatter dateFromString:@"2013/09/01 15:00:00"];
    
    NSLog(@"%@", [theDay descriptionWithLocale:[NSLocale currentLocale]]);

コンソール出力

2013年9月1日日曜日 午後3:00:00 日本標準時

※ちなみにシュミレータの設定には24時間表示のON/OFFがないため、実機でしか再現できないです。

ユーザ設定の暦によってstringFromDateの出力が意図しないものになる

前提として、「設定」>「一般」>「言語と地域」>「暦法」 を「和暦」に指定しているものとします。

やらかした例

    NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
    [formatter2 setDateFormat:@"yyyy年MM月dd日 HH時mm分ss秒"];
    NSString *dayString = [formatter2 stringFromDate:[NSDate date]];
    
    NSLog(@"%@", dayString);

コンソール出力

0027年10月31日 午前5時52分55秒

Ooooops!

正しい実装

    NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    [formatter2 setCalendar:calendar]; // setCalendarで表示したい暦を指定する。今回はグレゴリオ暦(西暦)。
    [formatter2 setDateFormat:@"yyyy年MM月dd日 HH時mm分ss秒"];
    NSString *dayString = [formatter2 stringFromDate:[NSDate date]];
    
    NSLog(@"%@", [theDay descriptionWithLocale:[NSLocale currentLocale]]);

コンソール出力

2015年10月31日 午前5時54分32秒

参考

iOS6とNSDateFormatterと和暦と24時間表示オフで発生しやすいバグについて | Technology-Gym

iOSの日付処理まとめ