2012/09/04更新

[XCODE] NSDateの内容をローカル時間(時差を考慮した時間)で表示する方法

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

こんにちは、iPhoneアプリ開発に没頭中の@yoheiMuneです。
今日は、NSDateを文字列として画面に表示する際に、時差を意識した時間を表示する方法を学んだので、 ブログに書きたいと思います。

A man is watching iPhone.



NSDateを文字列で表現する際の問題点

NSDateを文字列で表現する際に、NSDateFormatterなどを使うと、以下のような出力結果を得ることが出来ます。
NSDate *now = [NSDate date];NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

// パターン1
[formatter setDateFormat:@"yyyy-MM-dd hh:mm:ss.SSSZZZ"];
NSString *dateString = [formatter stringFromDate:date];
NSLog(@"%@", dateString); // 2012-09-03 12:13:01.432+0900

// パターン2
[formatter setDateFormat:@"yyyy-MM-dd hh:mm:ss.SSS"];
NSString *dateString = [formatter stringFromDate:date];
NSLog(@"%@", dateString); // 2012-09-03 12:13:01.432

上記の結果を見るとお分かりの通り、世界標準時の時間で表示されてしまい、 日本のような世界標準時から時差がある国でiPhoneを使っている場合に、ユーザーの考える現在時刻とは 異なってしまうという問題があります。

2012/09/04追記
ご覧頂きました方から、ご指摘をいただきまして修正します。
「2012-09-03 12:13:23.456 +0900」といった表示の「2012-09-03 12:13:23.456」は、 既にローカル時間が表示されています。「+0900」は標準時からどれだけずれているかを示している内容です。
そのため、上記の出力結果で既にローカル時間(時差を考慮した時間)を取得できます。

不備の指摘ありがとうございました。




NSDateの内容を時差を考慮でした時間で表示する

上記の問題に対応する際に、いくつかの対応方法があります。
  • 「ZZZ」で取得できる時差(上記の場合は+0900)をNSDateに加算して、日付文字列を出力し直す。
  • (特定の国のみにリリースする場合)決めうちで時差を加算して、日付文字列を出力する。
  • iPhoneユーザー設定に使われているカレンダーを用いて、日付文字列を出力する。
以下では、「iPhoneユーザー設定に使われているカレンダーを用いて、日付文字列を出力する」の方法を解説したいと思います。

iPhoneの設定アプリでユーザーが設定したカレンダーを以下のように簡単に取得することが出来ます。
NSCalendar *userCalendar = [NSCalendar currentCalendar];
このカレンダーを用いて、日付を出力することで、時差を考慮した時間を取得することが出来ます。
実際の実装は以下のようになります。
// 表示したい時間を保持するNSDateオブジェクト。
NSDate *now = [NSDate date];

// ユーザー設定カレンダー
NSCalendar *userCalendar = [NSCalendar currentCalendar];

// 出力する内容を作成する。
// 下記例では、年、月、日、時、分、秒。
NSUInteger flag
   = NSYearCalendarUnit
     | NSMonthCalendarUnit
     | NSDayCalendarUnit
     | NSHourCalendarUnit
     | NSMinuteCalendarUnit
     | NSSecondCalendarUnit;

// ユーザーカレンダーと出力内容を使って、
// NSDateComponentsオブジェクトを作成する。
NSDateComponents *c = [userCalendar components:flag fromDate:date];

// NSDateComponentsオブジェクトから値を取り出しながら、
// 日付文字列を作成する。
NSString *dateStr = [NSString stringWithFormat:@"%d-%d-%d %d:%d:%d", [c year], [c month], [c day], [c hour], [c minute], [c second]];

最後の日付文字列作成時のNSDateのFormatはちょっと面倒ですが、上記のようにユーザーカレンダーを使う事で、 ユーザーカレンダーにちなんだ時差が考慮された時間を取得することが出来ます。
こーすれば日付の国際化対応も出来ます。



参考資料

上記で利用したNSCalendarとNSDateComponentsのクラスリファレンスを掲載させて頂きます。
- NSCalendar Class Reference
- NSDateComponents Class Reference



最後に

NSDateのローカライズ対応は、調べてもなかなか良い記事が出て来ませんでした。
上記の対応が個人的には気に入ったので、ブログにも掲載させて頂きました。
この記事が、少しでもお役に立てば幸いです。

最後までお読み頂きましてありがとうございました。ぜひRSSへの登録も宜しくお願いします☆





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。