iPhone - правильный способ получения текущей даты и времени для данного места / часового пояса и сравнения его с другой датой / временем в том же месте - PullRequest
17 голосов
/ 09 сентября 2011

Я ищу правильный способ получить фактическую дату и время для данного места / часового пояса и могу сравнить его с указанной датой / временем для того же места.

Скажем, например, Париж, это GMT +1. Как и сейчас, Париж также может быть GMT + 2 из-за перехода на летнее время, но, насколько я знаю, это исключение, поэтому оно должно быть учтено в ответе, а не общим параметром. Важными словами здесь являются «данное место».

Итак, если я хочу узнать, какая дата и время в Сиднее, Австралия или Париже, Франция, и перенести эту дату в NSDate, чтобы иметь возможность сравнить ее с другой NSDate, которая будет представлять другую дату / время в том же самом место, как я могу сделать?

Я прочитал страницы и страницы вопросов и ответов с комментариями, даже на принятый ответ, в котором говорится от опытных пользователей: не очень хороший ответ -1, неправильный, неправильный способ сделать это, абсолютно неправильный, .. .

Итак, знаете ли вы правильный реальный способ сделать это?

В идеальном мире эта дата / время были бы абсолютными, даже если телефон пользователя не в нужное время и / или в дате и / или часовом поясе, или в чем-либо, что может быть близко к этому совершенству, без необходимости подключения к нему. сервер даты / времени.

Ответы [ 3 ]

34 голосов
/ 09 сентября 2011

Я ищу правильный способ получения фактической даты и времени для данного места / часового пояса.

[NSDate date] возвращает объект даты, представляющий текущую дату и время,не важно где вы находитесь.NSDate s не зависят от мест или часовых поясов.Существует только одна NSDate, которая представляет сейчас или любой другой момент в этом отношении, а не разные объекты даты для каждого временного пояса.Поэтому не следует пытаться преобразовать дату между часовыми поясами.

NSDate объекты представляют абсолютное мгновение во времени.Рассмотрим следующий пример того, как два представления даты в разных часовых поясах (9/9/11 3:54 PM в Париже и 9/9/11 11:54 PM в Сиднее) на самом деле являются одинаковыми датами.

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

Когда дело доходит до вывода даты, имейте в виду, что метод NSDate description возвращает время в 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, как я могу это проверить?

Создайте объект NSDate, который представляет сегодня в 15:00 (местное время), и сравните его с «сейчас»:

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 по парижскому времени (не местноевремя).Пример того, как это сделать, см. В ответе Оливера.Просто чтобы быть ясным, мой третий фрагмент кода показывает, как проверить, если это после 15:00 по местному времени.

12 голосов
/ 10 сентября 2011

После большой головной боли и начала понимать, что такое 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, что может быть неверным.

9 голосов
/ 09 сентября 2011

Используйте 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...