Ответ 1
Мы можем воспроизвести вашу проблему, явно установив часовой пояс на "Бразилия/Восток":
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSString *dateString = @"19/10/2014";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Brazil/East"];
[dateFormatter setDateFormat:@"dd/MM/yyyy"];
NSDate *myDate = [dateFormatter dateFromString:dateString];
NSLog(@"myDate = %@", myDate);
}
return 0;
}
Здесь вывод:
2014-06-06 14:22:28.254 commandLine[31169:303] myDate = (null)
Поскольку вы не указали время в dateString
, система принимает полночь. Но полночь в эту дату не существует в бразильском часовом поясе.
Бразилия изменила с BRT (летнее время) на BRST (не дневной свет часовой пояс) 19 октября 2014 года, пропуская непосредственно с последнего момента "18/10/2014" до "19/10/2014 01:00:00".
Так как "19/10/2014 00:00:00" не существует, NSDateFormatter
возвращает nil
. Я думаю, что это плохое поведение со стороны NSDateFormatter
, но мы должны справиться с этим. -[NSDateFormatter dateFromString:]
в конечном итоге вызывает CFDateFormatterGetAbsoluteTimeFromString
, в котором используется функция udat_parseCalendar
из Международные компоненты для библиотеки Unicode (icu) для анализа даты.
Вы можете обойти проблему, заставив парсер использовать полдень вместо полуночи как время по умолчанию. Никакие часовые пояса не меняются в/из летнего времени в полдень. Давайте напишем вспомогательную функцию, которая возвращает полдень некоторой произвольной даты в данном часовом поясе:
static NSDate *someDateWithNoonWithTimeZone(NSTimeZone *timeZone) {
NSDateComponents *components = [[NSDateComponents alloc] init];
components.timeZone = timeZone;
components.era = 1;
components.year = 2001;
components.month = 1;
components.day = 1;
components.hour = 12;
components.minute = 0;
components.second = 0;
return [[NSCalendar autoupdatingCurrentCalendar] dateFromComponents:components];
}
Затем мы устанавливаем формат даты defaultDate
к этой дате полудня:
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSString *dateString = @"19/10/2014";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Brazil/East"];
dateFormatter.dateFormat = @"dd/MM/yyyy";
dateFormatter.defaultDate = someDateWithNoonWithTimeZone(dateFormatter.timeZone);
NSDate *myDate = [dateFormatter dateFromString:dateString];
NSLog(@"myDate = %@", myDate);
}
return 0;
}
И вот вывод:
2014-06-06 14:52:31.939 commandLine[31982:303] myDate = 2014-10-19 14:00:00 +0000