2012年8月26日日曜日

NSDate, NSDateComponents でiOSの時間を制する

こんにちは, iPhone アプリをつくるとき, 時間の操作がどうしてもひつようになります。

日記などデータ保存系のアプリでは, 必ず時間を CoreData などで保存しなくてはなりません。
というわけで, iOS で時間をどう扱うか調べてみました。

NSDate *, NSDateComponent * なんかを使います。

こちらがこのブログの次のやつです その2


さて今回の話題, アプリの話になりますが
これが特定の国だけで使うアプリなら, 問題ないがグローバル展開するなら, タイムゾーンを意識しないといけない。

アプリで利用する場合の基本的な方針

1.  Core Data に保存する値は, 常に GMT 時間を保存
2.  表示するデータ(UIDatePickerも)は, 現地時間
3.  保存したデータの検索は, GMT時間
4.  変換などはどっちでもいい

とします。

ソフトウェアでユーザに見えるところは, 現地時間。内部ではGMTで操作するという方針です。


・ GMT 時間(現在時間)を取得する
NSDate *now = [NSDate date];

NSDate を何も考えずに利用すると, GMT時間が得られます。


・現在時間を取得する(現地時間)

NSDate *date = [NSDate date];

NSTimeZone *tz = [NSTimeZone systemTimeZone];
NSInteger seconds = [tz secondsFromGMTForDate: date];
NSDate *local_date = [date dateByAddingTimeInterval:seconds];


※ポイントは, タイムゾーンを取得し, GMTとの差分を求めて
dateByAddingTimeInterval で, 現地時間を取得します

・ 現地時間の23:59:59を取得する

NSDate *date = [NSDate date];

NSDateComponents *comps;
NSCalendar *calendar = [NSCalendar currentCalendar];

comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];


NSDateComponents *new_comps = [[NSDateComponents alloc] init];
[new_comps setYear:comps.year];
[new_comps setMonth:comps.month];
[new_comps setDay:comps.day];

[new_comps setHour:23];
[new_comps setMinute:59];
[new_comps setSecond:59];

NSDate *tmp = [calendar dateFromComponents:new_comps];


NSTimeZone *tz = [NSTimeZone systemTimeZone];
NSInteger seconds = [tz secondsFromGMTForDate:tmp];
NSDate *local_date = [tmp  dateByAddingTimeInterval:seconds];



※応用編です。
NSCalendar を利用しています  NSCalendar, NSDateCompoenents で得られたcomponentは
, 現地時間になります。(currentCalendar は現地時間を表します)

[NSDate date] で, GMTを得たはずなのに, currentCalendar を通すと, 現地時間に変わってしまいます

さらに, NSDateComponents を使って, 時間の操作をしました。またカレンダーを使って, 時間を得ていますが, この時間はGMTに戻っています。そこで再び現地時間に戻します。


○UIDatePicker の場合
UIDatePicker は, タイムゾーンをstoryboard 上もしくは, コードで設定します

ex) コードで設定(datePicker は, UIdatePicker オブジェクトのインスタンス or リファレンス)
datePicker.timezone = [NSTimeZone systemTimeZone];

これで現地時間になります。

このUIDatePicker で得られた値を再度, GMT時間に戻すには, 以下のコードを押し込みます

NSDate *local_date = [datePicker date];

NSTimeZone *tz = [NSTimeZone systemTimeZone];
NSInteger seconds = [tz secondsFromGMTForDate: local_date];
[local_date dateByAddingTimeInterval:-(seconds)];


※これは現地時間を取得したときと逆の計算をしています。



GMT時間で保存しておけば, のちにタイムゾーンを変更しても, そのタイムゾーンに合わせた時間によしなに変更してくれるということです。


もう少し, 詳しくみて, まとめていきたいです。



0 件のコメント:

コメントを投稿