iPhone-poprawny sposób na uzyskanie aktualnej daty i godziny dla danego miejsca / strefy czasowej i porównanie jej z inną datą/godziną w tym samym miejscu

Szukam poprawnego sposobu, aby uzyskać rzeczywistą datę i godzinę dla danego miejsca / strefy czasowej i jestem w stanie porównać ją do danej daty/godziny dla tego samego miejsca.

Powiedzmy, dla przykładu, Paryż, czyli GMT + 1. Jak teraz, Paryż może być również GMT + 2 ze względu na czas letni, ale jest to część wyjątku, o ile wiem, więc należy wziąć pod uwagę odpowiedź, ale nie wziąć jako ogólny param. Najważniejsze słowa To "dane miejsce".

Więc jeśli Chcę wiedzieć, która Data i godzina jest w Sidney Australia, lub Paryż Francja, i dostać tę datę do NSDate za możliwość porównania go z innym NSDate, które reprezentowałyby inną datę / czas w tym samym miejscu, jak Mogę zrobić?

Przeczytałem strony i strony pytań i odpowiedzi z komentarzami, nawet na zaakceptowaną odpowiedź, która mówi od doświadczonych użytkowników: nie dobra odpowiedź -1, źle, nie prawidłowy sposób, absolutnie źle, ...

Czy znasz poprawny naprawdę ?

W idealnym świecie data / godzina byłaby absolutna, nawet jeśli telefon użytkownika nie znajduje się w odpowiednim czasie i/lub dacie i/lub strefie czasowej, lub cokolwiek, co może być blisko tej doskonałości bez potrzeby łączenia się z serwerem daty/czasu.

Author: Oliver, 2011-09-09

3 answers

Szukam poprawnego sposobu, aby uzyskać rzeczywistą datę i godzinę dla danego miejsca / strefy czasowej.

[NSDate date]zwraca obiekt date reprezentujący bieżącą datę i czas, bez względu na gdzie jesteś. NSDates nie podlegają miejscom ani strefom czasowym. Jest tylko jeden NSDate, który reprezentuje teraz lub jakikolwiek inny moment, a nie różne obiekty daty dla każdej strefy czasowej. Dlatego nie należy próbować konwertować daty między czasem strefy.

NSDate obiekty reprezentują absolutną natychmiastową w czasie. Rozważmy poniższy przykład, w jaki sposób dwie reprezentacje daty w różnych strefach czasowych (9/9/11 3:54 PM w Paryżu i 9/9/11 11:54 PM w Sydney) są faktycznie tą samą datą.

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?");
}
Zapisuje ostatnią wiadomość, ponieważ w Paryżu i Sydney są w tej samej chwili. Kiedy jest 9/9/11 3:54 PM w Paryżu, jest 9/9/11 11:54 PM w Sydney.

Zarówno daje w debuggerze jak i NSLog 2011-09-09 14: 26: 02, ale teraz jest 16: 26 więc chyba powinno wrócić 16:26:02 +0200

Jeśli chodzi o wyjście daty, Należy pamiętać, że NSDate'S description metoda zwraca czas w GMT i trzeba użyć NSDateFormatter aby utworzyć łańcuch daty reprezentujący czas lokalny w Paryżu, Sydney, itp. od daty:

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

Ok, ale jeśli chcę wiedzieć, czy ten czas jest po 15: 00, Jak mogę to przetestować ?

Utwórz obiekt NSDate, który reprezentuje dzisiaj w 15: 00 (czasu lokalnego) i porównaj go z "teraz":

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");
}

Okazuje się, że @ Oliver musiał sprawdzić, czy jest po 15: 00 w Paryżu więc musiał utworzyć datę, która reprezentuje dzisiaj o 15: 00 czasu paryskiego (Nie czasu lokalnego). Aby uzyskać przykład, jak to zrobić, zobacz odpowiedź @ Oliver. Dla jasności, mój trzeci fragment kodu pokazuje, jak sprawdzić, czy jest po 15: 00 czasu lokalnego.

 34
Author: albertamg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-10 11:08:19

Po wielkim bólu głowy i zrozumieniu, czym jest NSDate, wyobraziłem sobie takie rozwiązanie. Co myślisz o tym sposobie działania ?

// 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);

Niektóre odniesienia : http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtTimeZones.html#//apple_ref/doc/uid/20000185-SW4

Ale, o ile wiem i przetestowałem, ten dzień/czas nie może być naprawdę absolutny. Opiera się na dacie/godzinie/strefie czasowej iPhone ' a, co może być błędne.

 12
Author: Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-10 10:53:21

Użyj NSCalendar i metody 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
Author: zaph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 15:10:08