まず、iOS6でのNSDateFormatterの変更点について

で書かれているようにYYYYを使った場合の挙動が変わっている。
基本的はyyyyを使うべきな場合が殆どなので、yyyyをつかうのを推奨

ここから先は、<strong>iOS6だけではなく他のバージョンも共通</strong>で、<br />iOS設定とNSDateFormmaterでよく発生させてしまうバグについて

和暦バグ

iOSの設定.app -> 一般 -> 言語環境 -> カレンダー -> 和暦 or タイ歴 を設定したい場合に、
平成xx年のxxがyyyyに入ってしまい、表示がおかしくなったり、この結果を取得して加算などを行なっていた場合にはアプリがクラッシュするなどのバグが発生する。

解決方法は上記のサイトのように、NSGregorianCalendarをNSDateFormatterに設定してあげればよい。


NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; [formatter setCalendar:calendar];

12時間表示バグ

もう一つ似たような問題があり、iOSの設定.app -> 一般 -> 日付と時刻 -> 24時間表示(オフ) とした時に、
午前/午後といった文字列がHH等(DateFormatの時刻)が入ってしまい、数字っぽい文字列が返ってくることを想定した場合はクラッシュが起きたり、
文字数が多くなり表示が見切れるなどの問題も発生する。

また、iOS6からは24時間表示(オフ)とした時のNSDateFormatterの動作が異なる気がする。
iOSシミュレーターにはこの設定が存在しないため、デバッグするには実機を使って行う必要がある。

これの解決方法は [NSLocale systemLocale]をNSDateFormatterに設定すること


NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setLocale:[NSLocale systemLocale]]; [formatter setTimeZone:[NSTimeZone systemTimeZone]];

無駄にLocaleを設定しているようにみえるが、これ行うことで常に24時間表示の時間を取得することができる。

毎回、このような設定を行うのは大変なので、自分の場合はNSDateFormatterカテゴリを使っている


NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] initWithGregorianCalendar];

ただし、この場合に[NSLocale systemLocale]を設定しているため、DateFormatでEEE(曜日)を取ろうと思った場合に、曜日が数字となってしまうため、
以下のように改めてcurretLocaleを設定する


 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] initWithGregorianCalendar]; [dateFormatter setLocale:[NSLocale currentLocale]]; dateFormatter.dateFormat = @"MM月dd日(EEE)";

これで、NSDateFormatterに関するバグが発生する確率が大分すくなると思う。

基本的にはNSDateFormatterは文字を表示するためだけに使い、NSDateから数字として日付などを取得したい場合は、NSDateComponents等を使って取得したほうが良い(NSDate-Extensions)。
また、設定データ等で日付を NSDateFormatter を使い文字列として保存する場合は、iOSの設定によって異なるケースが存在するため(上記のカテゴリで大体統一はできるが)
NSDateのオブジェクトとして保存する方が問題が少ない。

NSDateは比較周りも意外と厄介な部分が多いため、ライブラリ等を活用したほうがいい場合も多い

 

 

 

 

Post Navigation