6

アップデート

iOS 7 の時点で、 NSDateFormatter、この形式の文字列が提示されたときに実際に NSDate を作成します。

NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:@"@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ""];

NSLog(@"non–nil date, even honoring the 7–minute–offset in the time–zone on iOS 7: %@",
     [formatter dateFromString:@"2011-07-12T18:07:31+02:07"]);

iOS 6 の場合、答えは NSDateFormatter を使用しないことです…</p>


さて、ここまで読んできました

NSDateFormatter文字列から文字列を作成するための使用方法についてNSDate

Peter Hosey のISO8601DateFormatterにも出くわしました。
彼の実装を調べてみると、次のように思います。

このような文字列を に取得するための正しく正気な方法はありませんか?2011-07-12T18:07:31+02:00NSDate

  • 最後のコロンがなくても問題ありません。
  • GMT「+」記号が前に付いていれば問題ありませんが...
  • そうではありません。

私のアプリケーションで動作するようにハックすることはできますが(フォーマットを使用) 、タイムゾーンの分単位の情報が破棄されるため@"yyyy'-'MM'-'dd'T'HH':'mm':'ssz':'00"、もちろんそれは正しくありません。

最後のコロンを空の文字列に置き換えることもできますが、それもハックだと思います。

NSDateFormatterそれで、上からその文字列を取り、有効で正しいものを私に与えるための秘密のソースはありますNSDateか?


余談:

+[NSDate dateWithNaturalLanguageString:]私の目標を達成するために使用できるヒントをどこかで見つけました。ただし、これは日付を設定するだけで、時刻は設定しません! (まあ、それ時間を設定しますが、タイムゾーンオフセットのみを考慮し、HH:mm:ss 部分は考慮しません...)

4

2 に答える 2

2

この質問は少し古いですが、私は同じ問題を抱えていました。私は答えであり、他の人に役立つかもしれないいくつかのコードを思いつきました...

正規表現を使用して ISO-8601 文字列を解析し、出力を一連の文字列に取得してから、NSDateFormatter に渡す独自の文字列を作成する (つまり、コロンなどを削除する) か、常に同じ出力が必要な場合に使用できます。文字列、NSRegularExpression への呼び出しの結果から作成するだけです。

//    ISO-8601 regex: 
//        YYYY-MM-DDThh:mm[:ss[.nnnnnnn]][{+|-}hh:mm]
// Unfortunately NSDateFormatter does not parse iso-8601 out of the box,
// so we need to use a regex and build up a date string ourselves.
static const char * REGEX_ISO8601_TIMESTAMP = 
            "\\A(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})" // Mandatory - YYYY-MM-DDThh:mm
            "(?:"
            ":(\\d{2})"                                       // Optional - :ss
            "(?:"
            "[.](\\d{1,6})"                                   // Optional - .nnnnnn
            ")?"
            ")?"
            "(?:"
            "([+-])(\\d{2}):(\\d{2})|Z"                       // Optional -[+-]hh:mm or Z
            ")?\\z";

// Extract all the parts of the timestamp
NSError *error = NULL;
NSString *regexString = [[NSString alloc] initWithUTF8String:REGEX_ISO8601_TIMESTAMP];

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString
                                                                       options:NSRegularExpressionCaseInsensitive
                                                                         error:&error];

NSArray *matches = [regex matchesInString:timestamp
                              options:0
                                range:NSMakeRange(0, [timestamp length])];

// Groups:
//
// elements start at 1 in the array returned from regex, as [0] contains the original string.
//
// MANDATORY - must exist as per ISO standard
//  1  - YYYY
//  2  - MM
//  3  - DD
//  4  - hh
//  5  - mm
// OPTIONAL (each one can be optional)
//  6  - ss
//  7  - nn (microseconds)
//  8  - offset sign (+/-)
//  9  - offset hour
//  10 - offset min
// put the parts into a string which will then be recognised by NSDateFormatter
// (which is acutally RFC822 format)

// mandatory init'd to nil, optional set to defaults.
NSString *YYYY, *MM, *DD, *hh, *mm, *ss, *nn, *sign, *Zhh, *Zmm;
NSRange tempRange;

for (NSTextCheckingResult *match in matches) {
    NSRange matchRange = [match range];
    NSInteger matchCount = [match numberOfRanges] - 1;
    NSUInteger idx = 1;

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        YYYY = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        MM   = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
         tempRange = [match rangeAtIndex:idx++];
         DD   = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        hh   = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        mm   = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        ss   = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        nn = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        sign = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        Zhh  = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }

    if (idx < matchCount) {
        tempRange = [match rangeAtIndex:idx++];
        Zmm  = tempRange.location != NSNotFound ? [timestamp substringWithRange:tempRange] : nil;
    }
}

これが誰かを助けることを願っています!

于 2012-05-03T06:40:47.827 に答える