web-dev-qa-db-ja.com

iPhone-特定の場所/タイムゾーンの現在の日付と時刻を取得し、同じ場所の他の日付/時刻と比較する正しい方法

指定された場所/タイムゾーンの実際の日時を取得する正しい方法を探しており、同じ場所の特定の日時と比較できます。

たとえば、パリの場合、それはGMT +1です。今のところ、パリは夏時間のためにGMT + 2になることもありますが、私が知る限り、これは例外の一部であるため、回答に考慮する必要がありますが、一般的なパラメーターとしては考慮されません。ここで重要な言葉は「与えられた場所」です。

したがって、シドニーオーストラリアまたはパリフランスの日付と時刻を知りたい場合は、その日付をNSDateに入れて、同じ場所にある別の日付/時刻を表す別のNSDateと比較できるようにします。いいですか?

受け入れられた回答であっても、経験豊富なユーザーからのコメント付きのページと質問と回答のコメント付きページを読みました:良い答えではない-1間違っている、これを行う正しい方法ではない、絶対に間違っている、...

それで、あなたはそれを行う正しい正しい方法を知っていますか?

完璧な世界では、ユーザーの電話が適切な時間、日付、タイムゾーン、あるいはその両方に達していない場合でも、日付/時刻は絶対的なものになります。タイムサーバー。

17
Oliver

大きな頭痛の種とNSDateが何であるかを理解し始めた後、私はそのような解決策を想像しました。そのやり方についてどう思いますか?

// Now, an absolute date and time that represent now all around the world, that is made to play with
NSDate *now = [NSDate date];

// A specific calendar for a specific place in the world
NSCalendar* parisCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[parisCalendar setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];

// Now components seen from Paris
NSDateComponents* componentsNowInParis = [parisCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit|NSTimeZoneCalendarUnit fromDate:now];

// Tricking a copy of "Now components seen from Paris" to force 15:00:00, in Paris
NSDateComponents* componentsInParisAt15 = [[componentsNowInParis copy] autorelease];
[componentsInParisAt15 setHour:15];
[componentsInParisAt15 setMinute:0];
[componentsInParisAt15 setSecond:0];

// Getting an universal date reference that represent what could be 15:00:00 seen from paris, Or 19:00:00 from GMT+4
NSDate* dateAt15 = [parisCalendar dateFromComponents:componentsInParisAt15];

// We now have two universal dates that can be compared each other
// If "now" is 16:00:00, those date will show a 60 minutes difference all around the world
NSLog(@"%@", now);
NSLog(@"%@", dateAt15);

一部の参照: http://developer.Apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtTimeZones.html#//Apple_ref/doc/uid/20000185-SW4

しかし、私が知り、テストした限りでは、その日/時間は本当に絶対的なものではありません。これは、iPhoneの日付/時刻/タイムゾーンに基づいていますが、間違っている可能性があります。

12
Oliver

特定の場所/タイムゾーンの実際の日時を取得する正しい方法を探しています。

[NSDate date]returnは、whereに関係なく、現在の日付と時刻を表す日付オブジェクトを返します。 NSDatesは場所やタイムゾーンの影響を受けません。 nowまたはその他の瞬間を表すNSDateは1つだけであり、タイムゾーンごとに異なる日付オブジェクトではありません。したがって、タイムゾーン間で日付を変換しないでください。

NSDateオブジェクトはabsoluteの瞬間を表します。 2つの日付表現が異なるタイムゾーン(9/9/11 3:54 PMパリと9/9/11 11:54 PM in Sydney)は実際にはsameの日付です。

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];
NSDate *aDate = [formatter dateFromString:@"9/9/11 3:54 PM"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];
NSDate *anotherDate = [formatter dateFromString:@"9/9/11 11:54 PM"];
NSLog(@"%@",anotherDate);
if ([aDate isEqualToDate:anotherDate]) {
    NSLog(@"How about that?");
}

9/9/11 3:54 PMパリと9/9/11 11:54 PMシドニーの実際の時間は同じです。 9/9/11 3:54 PMパリでは9/9/11 11:54 PMシドニー。

デバッガとNSLogの両方で2011-09-09 14:26:02が表示されますが、現在は16:26なので、16:26:02 +0200を返すはずです。

日付を出力する場合、NSDatedescriptionメソッドはGMTで時刻を返すため、NSDateFormatterを使用して現地時間を表す日付文字列を作成する必要があることに注意してください。パリ、シドニーなどの日付から:

NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];
NSLog(@"%@",[formatter stringFromDate:now]); //--> 9/9/11 11:54 PM
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];
NSLog(@"%@",[formatter stringFromDate:now]); //-->  9/9/11 3:54 PM

わかりましたが、その時間が15:00以降かどうかを知りたい場合は、どうすればテストできますか?

今日の15:00(現地時間)を表すNSDateオブジェクトを作成し、「現在」と比較します。

NSDate *now = [NSDate date];
NSCalendar* myCalendar = [NSCalendar currentCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit 
                                             fromDate:[NSDate date]];
[components setHour: 15];
[components setMinute: 0];
[components setSecond: 0];
NSDate *todayAt15 = [myCalendar dateFromComponents:components];
if ([now compare:todayAt15] == NSOrderedDescending) {
    NSLog(@"After 15:00 local time");
}

@ -Oliverがパリの15:00以降であるかどうかを確認する必要があることが判明したため、今日の現地時間ではない15:00のパリ時間を表す日付を作成する必要がありました。その方法の例については、@ Oliverの回答を参照してください。明確にするために、私のコードの3番目のスニペットは、現地時間の15:00以降かどうかを確認する方法を示しています。

34
albertamg

NSCalendarとsetTimeZoneメソッドを使用します。

NSDate *newDate;
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:~ NSTimeZoneCalendarUnit fromDate:[NSDate date]];

newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSLog(@"newDate: %@", newDate);
NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate:2011-09-09 15:02:09 +0000
newDate:337273330

[dateComponents setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];
newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSLog(@"newDate: %@", newDate);
NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate:2011-09-09 00:52:03 +0000
newTimeInterval:337222930

[dateComponents setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];
newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSLog(@"newDate: %@", newDate);
NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate:2011-09-09 08:52:03 +0000
newTimeInterval:337251730

9
zaph