Проблемы с NSDate - или как игнорировать дату / часовой пояс? - PullRequest
3 голосов
/ 10 июня 2011

Хорошо, я отказался от этого.Вот что я пытаюсь сделать: у меня есть восход, закат и текущее время в определенном часовом поясе.Я хочу знать, день это или ночь, выяснив, находится ли текущее время между временем восхода и захода солнца.

Вот что у меня есть:

NSLog(@"%@ - %@ - %@",currTime,sunrise,sunset);

NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:@"hh:mm a"];
[formatter2 setDateFormat:@"EEE, dd MMM yyyy h:mm a z"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
NSDate *time = [formatter2 dateFromString:currTime];    
[formatter1 release];
[formatter2 release];

unsigned int flags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components1 = [calendar components:flags fromDate:rise];
NSDateComponents *components2 = [calendar components:flags fromDate:set];
NSDateComponents *components3 = [calendar components:flags fromDate:time];

NSDate *Sunrise = [calendar dateFromComponents:components1];
NSDate *Sunset = [calendar dateFromComponents:components2];
NSDate *Time = [calendar dateFromComponents:components3];

NSLog(@"\nSunrise: %@ \nSunset:%@ \nTime:%@",rise,set,time);
NSLog(@"\nSunrise: %@ \nSunset:%@ \nTime:%@",Sunrise,Sunset,Time);

Вот первый вывод:

Пт, 10 июня 2011 4:00 утра SAST - 7:46 утра - 5:41 вечера

И вот второй (прежде чем он обеспокоен тольковремя, а не дата)

Восход: 1969-12-31 22:46:00 +0000

Закат: 1970-01-01 08:41:00 + 0000

Время: 2011-06-10 02:00:00 + 0000

И, наконец, вот последний вывод (обратите внимание, как запуталось время?):

Восход: 0001-12-31 22:27:01 +0000

Закат: 0001-01-01 08:22:01 +0000

Время: 0001-01-01 01:41:01 + 0000

Итак, я хотел вставить эти итоговые даты в мой метод, который проверяет, находится ли он между датами:

+(BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
    return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}

Однако, пока яПолучите, что проблема с датой выяснила, что метод не будет работать.:/ Мне нужна помощь!Что я делаю не так?


Хорошо, поэтому я перестал пытаться заставить NSDate s работать на меня.Проблемы с часовым поясом просто убили мой мозг на выходные.В любом случае, я решил использовать предложение BoopMeister, но оно не работает так, как я ожидал.Вот пример:

Используя настройки сверху, я добавил следующие строки:

NSInteger riseHour = [components1 hour];
NSInteger setHour = [components2 hour];
NSInteger timeHour = [components3 hour];

NSLog(@"Rise: %i  Set: %i  Time: %i",riseHour,setHour,timeHour);

Теперь, когда я подключаю эти переменные: Текущее время: Fri, 10 Jun 2011 9:07 am CDT Восход солнца: 6:33 amЗакат: 8:32 pm

Однако, когда я вывожу строки из описанных выше методов, вот что я получаю:

Подъем: 6 Набор: 20 Время: 23

Что за?

Ответы [ 2 ]

0 голосов
/ 10 июня 2011

Одним из ключевых моментов NSDate является то, что оно в GMT.Всегда.Однако, когда вы регистрируете его, он печатает в соответствии с локалью пользователя.

Теперь, когда вы это делаете,

NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];
[formatter1 setDateFormat:@"hh:mm a"];
NSDate *rise = [formatter1 dateFromString:sunrise];
NSDate *set = [formatter1 dateFromString:sunset];
[formatter1 release];

Вы просто предоставляете информацию о часах, минутах и ​​времени AM / PM,Как узнать, к какому времени относится время?Это заполняет этот недостаток информации, по умолчанию 01.01.1970 и часовой пояс, основанный на локали пользователя.Вы предоставляете информацию о часовом поясе в текущем времени, которая может совпадать или не совпадать с локалью пользователя.

Чтобы это исправить, необходимо сгенерировать строку, содержащую информацию о дате и часовом поясе для времени заката, и передать ее в устройство форматирования даты с правильным форматом, чтобы получить дату.Я предполагаю, что у вас должно быть это (или как еще вы узнаете, что это время заката или восхода для этого дня?).Поскольку вы знаете место, вы также сможете получить информацию о часовом поясе.Если у вас есть правильная информация для построения дат, все методы сравнения, которые вы использовали, будут работать.

0 голосов
/ 10 июня 2011

Я бы использовал компоненты, которые у вас уже есть, и не делал новых дат.

Начиная с этой точки в вашем коде:

NSDateComponents *riseComponents = [calendar components:flags fromDate:rise];
NSDateComponents *setComponents = [calendar components:flags fromDate:set];
NSDateComponents *timeComponents = [calendar components:flags fromDate:time];

А потом что-то вроде

NSInteger riseHour = [riseComponents hour];
NSInteger setHour = [setComponents hour];
NSInteger timeHour = [timeComponents hour];

// Do some checks here
// If necessary do the same for the minutes ([components minute])

Сравнение дат было проблемой производительности в моем приложении, и, поскольку у вас уже есть dateComponents, было бы быстрее выполнить собственную проверку и использовать NSIntegers.


Хорошо, как видно из вопроса, он дает числовое представление часов. То же самое работает за минуты. Постройте ваши чеки после этого.

Что, вероятно, является проблемой с текущим временем, это календарь, который вы используете. Он автоматически преобразует время в часовой пояс используемого вами календаря. Вы также можете создать календарь со строковым представлением часового пояса. Я думаю, это в API NSCalendar. Затем, после того, как вы сделали этот календарь, используйте его для текущего времени.

...