Диаграмма RFC3339 даты с NSDateFormatter в iOS 4.x и macOS X 10.6: невозможно?
-
30-09-2019 - |
Вопрос
Расположение даты RFC3339 с NSDateFormatter, по -видимому, невозможна в общем случае. Я ошибся? [Редактировать 2 года спустя: теперь есть способ! Смотрите ниже и сноску.
Не в значительной степени веб-сервис кормит мне даты, такие как:
2009-12-31T00:00:00-06:00
RFC3339, совместимый, вывод по умолчанию библиотеки JAXB, который они используют. Обратите внимание на толстую кишку, которая RFC3339 требует Когда смещение не буквально "Z":
time-numoffset = ("+" / "-") time-hour ":" time-minute time-offset = "Z" / time-numoffset
Я хочу разобрать их в NSDATE.
NSDateFormatter хочет закономерности в синтаксисе, указанном Unicode, который предлагает символы поля даты для таких часовых поясов, как «PDT», «-0800», «GMT-08: 00», но не «-08: 00».
Googling и другие подобные вопросы, создают только форматы даты, такие как
[myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
/* or: */ [myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
Последнее из которых требует буквального «Z», а первое настаивает на отсутствии толстой кишки или присутствия «Гринвита». Тем не менее, они, по -видимому, работали до iOS 4.x (возможно, полностью отбрасывая смещение TZ; мои данные не ясны.)
Мои варианты на данный момент - это жалкое участие:
- Откройте для себя какой -то нерекукументированный спецификатор формата или какой -то странный режим, чтобы поместить NSDateFormatter, который примет бездомную толстую кишку: Longshot, вероятно, отсутствует. [Сноска
- Убедитесь, что мой издатель сервисов превратил все даты во время Zulu и указал «Z»: политически сложные.
- Напишите мой собственный подкласс nsformatter или исследовать старый старый
strptime_l
: Работа. :) - Строка манипулирует моим входом и разделяет последний толстой кишки: хрупкий и уродливый, но вероятный путь наименьшего сопротивления.
Я точно понял ситуацию, что текущий NSDateFormatter следует строго без расширений Unicode; А форматы Unicode недостаточны для полного описания даты RFC3339?
Сноска Я возвращаюсь к этому три года спустя, чтобы забрать небольшое приложение: Unicode и Apple добавили эту функцию в строки формата, по состоянию на iOS6/OSX10.8. Сравнивать Последняя редакция на момент написания статьи с его непосредственный предшественник, и обратите внимание на добавление 5 "z", которое дает формат зоны, как "-08: 00". Так что, если вы можете уйти с помощью адаптации поддержки 5.x/10.7, есть новый правильный способ сделать это. Я оставлю предыдущий стенд ответа, так как это все еще лучший подход, когда требуется обратная совместимость.
Решение
Диаграмма строки даты в какао может быть болью, особенно если вам приходится иметь дело с датами, сгенерированными .NET на основе веб -сервисов.
Я бы посоветовал посмотреть на категорию NSDATE+InternetDateTime, которую Майкл Уотерфолл имеет на NSDATE в рамках своего проекта MWFeedParser на GitHub. Для меня это хорошо сработало, разрабатывая именно тот формат даты, который вы описываете.
Другие советы
- getObjectValue: ForString: Диапазон: Ошибка: может фактически разобрать RFC3339 Даты правильно. Я понятия не имею, почему - DateWithString: невозможно:
// RFC3339 date formatting
NSString *dateString = @"2012-04-11T18:34:19+00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
NSDate *date;
NSError *error;
[formatter getObjectValue:&date forString:dateString range:nil error:&error];
Символы формата строк не задокументированы нигде в документации Apple. Вместо этого в некотором документе, указывающем на стандарт Unicode, есть ссылка, указывающая на стандарт Unicode
http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#date_format_patterns
Использование информации по этой ссылке это довольно просто:
- (NSDate*)dateFromRFC3339String:(NSString*)aString
{
static NSDateFormatter* sRFC3339DateFormatter = nil;
static NSDateFormatter* sRFC3339DateFormatterSubSeconds = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
[sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
[sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssXXXXX"];
[sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
sRFC3339DateFormatterSubSeconds = [[NSDateFormatter alloc] init];
[sRFC3339DateFormatterSubSeconds setLocale:enUSPOSIXLocale];
[sRFC3339DateFormatterSubSeconds setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSSXXXXX"];
[sRFC3339DateFormatterSubSeconds setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
});
NSDate* date = [sRFC3339DateFormatter dateFromString:aString];
if (date == nil)
date = [sRFC3339DateFormatterSubSeconds dateFromString:aString];
return date;
}