В чем разница между NSRepublicOfChinaCalendar и NSGregorianCalendar?

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

- (NSDate*) stringToDate{
   NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
   [dateFormat setDateFormat:@"yy-MM-dd HH:mm"];
   NSDate *date = [dateFormat dateFromString:self];

   return date;

}

Работа с датой/временем довольно сложна - только разница во времени между системой и местным временем - в любом случае, описанный выше метод должен позаботиться об этом. (Так что я надеюсь, поскольку форматирование NSDate в NSString возвращает правильное местное время вместо просмотра переменной NSDate в отладчике, которая в моем случае показывает разницу в 2 часа)

Таких вычислений также много:

    NSCalendar *calendar = [NSCalendar currentCalendar];   <------

    NSDateComponents *components = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSYearCalendarUnit |NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:someDate];

    NSInteger now_hour = [components hour];
    NSInteger now_minute = [components minute];
    NSInteger yearx =  [components year];
    NSInteger monthx =  [components month];
    NSInteger dayx =  [components day];

где мне нужно установить/изменить/создать определенные даты/время, выполнить вычисления и снова получить/сохранить их в основных данных как NSStrings.

Мой вопрос касается использования соответствующего календаря.

Должен ли я всегда писать:

NSCalendar *calendar = [NSCalendar currentCalendar]; ?

or

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

и

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSRepublicOfChinaCalendar];

особ. в зависимости от того, используется ли приложение в Европе/США или Китае?


person user387184    schedule 25.07.2012    source источник
comment
Цитата из документа: A Chinese calendar can be created, and you can do calendrical calculations with it, but you should not use it for formatting as the necessary underlying functionality is not working correctly yet.   -  person nhahtdh    schedule 25.07.2012


Ответы (1)


Ваш метод stringToDate на самом деле не будет работать, см. QA1480. Краткая версия: у NSDateFormatter, к сожалению, есть две, немного противоречащие друг другу роли — декодирование и кодирование определенных текстовых форматов и преобразование дат для отображения. Поскольку последнее связано с локалью, оно используется по умолчанию. Чтобы гарантировать, что вы получите прежнее поведение, вы должны явно установить локаль en_US_POSIX, которая гарантированно точно соответствует вашей строке даты.

При этом вы, кажется, немного запутались в том, что такое NSDate. Это не NSString или любое другое письменное представление даты. Это абстрактная запись точного момента. Таким образом, это совершенно не связано с текущим календарем. Календарь и языковой стандарт пользователя будут влиять на печать дат, но не на сами даты. Теперь все еще сейчас, как бы вы это ни писали. Вот почему, когда вы применяете средство форматирования к дате, вы получаете правильную локальную дату, но если вы просто записываете дату в консоль, вы получаете что-то абстрактное и не обязательно в вашем местном часовом поясе. NSDate не имеет представления о часовых поясах или различных календарях.

Core Data может хранить даты напрямую (т. е. вам нет необходимости вручную преобразовывать в строки from больше, чем для числовых значений), поэтому я не совсем уверен, к чему вы клоните. Но нормальным поведением является использование currentCalendar, когда вы хотите что-то отобразить для пользователя. Это будет отображаться в соответствии с их часовым поясом и другими настройками.

Согласно QA, для применения строк с фиксированной датой вы должны использовать средство форматирования даты с явно заданным языковым стандартом и вообще не думать о календаре.

person Tommy    schedule 25.07.2012
comment
Я чувствовал, что в этом есть что-то хитрое, но никогда не ожидал, что это будет так опасно. Основная причина преобразования дат в строки заключалась в том, что я думал, что с этим будет проще справиться во время разработки приложения, поскольку я всегда могу видеть правильную дату/время вместо странного результата, который я вижу при просмотре переменной в отладчике. Если бы я знал, что форматирование в строку и обратно может вызвать эти ошибки, я бы просто использовал обычные даты с основными данными. Итак, теперь я буду использовать en_US_POSIX, надеюсь, это гарантирует его правильную работу. Большое спасибо, что указали на это! - person user387184; 25.07.2012
comment
Но будет ли это также работать, если я получу текущую дату/время с помощью [NSDate date], а затем сравню час и минуту с сохраненными датами/временем? Или сохраненные даты/время будут в американском времени (потому что я использовал en_US_POSIX), в то время как местное время совершенно другое? - person user387184; 25.07.2012
comment
В качестве последнего комментария - если кто-то сам создаст строки и получит их обратно, проблем не будет - нет необходимости использовать en_US_POSIX. Пока приложение хранит и использует только даты и строки, созданные им самим (разумеется, без каких-либо изменений в соответствующих настройках), все будет в порядке во всех странах и настройках календаря.... - person user387184; 25.07.2012