iOS 4.xおよびmacos x 10.6でのNSDateFormatterでRFC3339を解析する日付:不可能?
-
30-09-2019 - |
質問
一般的なケースでは、nsdateFormatterでRFC3339日付を解析することは不可能であると思われます。私が間違っている? [2年後の編集:今すぐあります!以下と脚注を参照してください。
特に当てはまるWebサービスは、次のような日付を与えています。
2009-12-31T00:00:00-06:00
RFC3339コンプライアント、使用しているJAXBライブラリのデフォルト出力。 RFC3339であるコロンに注意してください 必要 オフセットが文字通りの「Z」ではない場合:
time-numoffset = ("+" / "-") time-hour ":" time-minute time-offset = "Z" / time-numoffset
これらをnsdatesに解析したいです。
NSDateFormatterは、指定された構文のパターンを望んでいます Unicode, 、「PDT」、「-0800」、「GMT-08:00」などのタイムゾーンの日付フィールドシンボルを提供しますが、「-08:00」ではありません。
グーグルや他の同様の質問は、次のような日付形式のみを生成します
[myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
/* or: */ [myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
後者は文字通りの「Z」を必要とし、前者は結腸の欠如または「GMT」の存在のいずれかを主張します。ただし、iOS 4.xの前に動作しているように見えました(おそらくTZオフセットを完全に破棄することで、データは明確ではありません。)
この時点での私の選択肢はごめんなさい:
- 文書化されていない形式の仕様、またはnsdateFormatterを入れる奇妙なモードを発見してください。 [脚注
- 私のサービス出版社に、すべての日付をZuluの時間に変え、「Z」を指定するよう説得します。政治的に挑戦的です。
- 自分のnsformatterサブクラスを書いたり、古き良きを調査したりしてください
strptime_l
: : 仕事。 :) - 文字列 - 入力を操作し、最後のコロンを剥がします:脆性とugい、抵抗が最も少ない可能性があります。
状況を正確に理解したことがありますか?また、Unicode形式はRFC3339日付を完全に説明するには不十分ですか?
脚注 私はこの3年後に小さな補遺に戻るために戻ってきました:UnicodeとAppleはiOS6/OSX10.8のようにフォーマット文字列にこの機能を追加しました。比較 この執筆時点での最新の改訂 と その前任者, 、および5 "z" sの追加に注意してください。これにより、「-08:00」などのゾーン形式が得られます。したがって、5.x/10.7の溝のサポートで逃げることができれば、それを行うための新しい正しい方法があります。以前の回答スタンドは、後方互換性が必要な場合でも最良のアプローチであるためです。
解決
特に.NETベースのWebサービスによって生成された日付に対処する必要がある場合、ココアでの日付文字列の解析は痛みになる可能性があります。
GitHubでのMWFeedParserプロジェクトの一環として、Michael WaterfallがNSDateに持っているNSDate+InternetDateTimeカテゴリを見ることをお勧めします。あなたが説明する日付の形式を正確に解析するのはうまくいきました。
他のヒント
- getObjectValue:forstring:range:error:実際にRFC3339日付を正しく解析できます。理由がわからない - デートワーストリング:できない:
// 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標準を指す文書に深く隠されたリンクがあります
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;
}