17

一般的な場合、NSDateFormatterを使用してrfc3339の日付を解析することは不可能のようです。私が間違っている?[2年後に編集:今や方法があります!以下および脚注を参照してください。]

特に柔軟ではないWebサービスは、次のような日付を私に提供しています。

2009-12-31T00:00:00-06:00

Rfc3339に準拠し、使用しているjaxbライブラリのデフォルト出力。オフセットがリテラル「z」でない場合にrfc3339が必要とするコロンに注意してください。

time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

これらをNSDatesに解析したいと思います。

NSDateFormatterは、Unicodeで指定された構文のパターンを必要とします。これは、「PDT」、「-0800」、「GMT-08:00」などのタイムゾーンの日付フィールドシンボルを提供しますが、「-08:00」は提供しません。

グーグル、および他の同様のSOの質問は、次のような日付形式のみを生成します

[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を配置するための奇妙なモードを発見します。これは、漂遊コロンを受け入れます。ロングショット、おそらく存在しません。[脚注]
  • すべての日付をズールー時間に変換し、「Z」を指定するようにサービス発行者を説得します。これは政治的に困難です。
  • 私自身のNSFormatterサブクラスを作成するか、古き良き研究を行ってstrptime_lください。:)
  • 文字列-入力を操作し、最後のコロンを取り除きます。もろくて醜いですが、抵抗が最も少ない可能性が高いパスです。

現在のNSDateFormatterは拡張機能なしで厳密にユニコードに従うという状況を正確に理解しましたか。そしてユニコードフォーマットはrfc3339の日付を完全に記述するのに不十分ですか?

[脚注]私は3年後にこれに戻って、小さな補遺に取り組みます。UnicodeとAppleは、iOS6 / OSX10.8の時点で、この機能をフォーマット文字列に追加しました。この記事の執筆時点での最新のリビジョンその直前のリビジョンと比較し、5つの「Z」が追加されていることに注意してください。これにより「-08:00」のようなゾーン形式が生成されます。したがって、5.x / 10.7のディッチングサポートを回避できる場合は、それを行うための新しい正しい方法があります。下位互換性が必要な場合でも、これが最善のアプローチであるため、前の回答スタンドはそのままにしておきます。

4

3 に答える 3

11

– getObjectValue:forString:range:error:実際に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];
于 2012-04-12T17:58:44.750 に答える
8

特に.NETベースのWebサービスによって生成された日付を処理する必要がある場合、Cocoaでの日付文字列の解析は面倒な場合があります。

MichaelWaterfallがgithubのMWFeedParserプロジェクトの一部としてNSDateに持っているNSDate+InternetDateTimeカテゴリを確認することをお勧めします。あなたが説明する日付の形式を正確に解析することは私にとってうまくいきました。

https://github.com/mwaterfall/MWFeedParser/

于 2010-12-02T02:52:56.347 に答える
5

文字列形式の文字は、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;
}
于 2014-04-09T16:35:27.080 に答える