6

でバグを発見した可能性があるNSDateFormatterと思いますが、これがシステム環境設定でブラジルのタイム ゾーンを指定するようにローカライズされているかどうかはわかりません。

完全なプロジェクトはこちら: http://www.idanfe.com/dl/nsDateFormatterPuzzle.zip

関連するコードの抜粋を以下に示します。

NSArray *unformattedDatesArray = [[NSArray alloc] initWithObjects:@"2011-09-18",
     @"2011-10-16",@"2011-11-13",@"2011-12-11",@"2012-01-08",@"2012-02-05", nil];

NSString *resultedString = @"";
int ii = 0;
NSUInteger items = [unformattedDatesArray count];
for (ii=0; ii<items; ii++) {
    NSLog(@"original item # %d = %@",ii,[unformattedDatesArray objectAtIndex:ii]);
    resultedString = [resultedString stringByAppendingString:@"original item # "];
    resultedString = [resultedString stringByAppendingString:[NSString stringWithFormat: @"%d = ",ii]];
    resultedString = [resultedString stringByAppendingString:[unformattedDatesArray objectAtIndex:ii]];
    resultedString = [resultedString stringByAppendingString:[NSString stringWithFormat:@"\n"]];
}
NSDateFormatter *originalFormat = [[NSDateFormatter alloc] init];
[originalFormat setDateFormat:@"yyyy-MM-dd"]; // hh:mm:ss
NSDateFormatter *newFormat = [[NSDateFormatter alloc] init];
[newFormat setDateFormat:@"dd/MM/yyyy"]; // hh:mm:ss
NSString *formattedDate;
for (ii=0; ii<items; ii++) {
    formattedDate = [newFormat stringFromDate:[originalFormat
                                               dateFromString:[unformattedDatesArray objectAtIndex:ii]]];
    NSLog(@"formatted item # %d = %@",ii,formattedDate);
    resultedString = [resultedString stringByAppendingString:@"formatted item # "];
    resultedString = [resultedString stringByAppendingString:[NSString stringWithFormat: @"%d = ",ii]];
    resultedString = [resultedString stringByAppendingString:(formattedDate == nil ? @"ERROR" : formattedDate)];
    resultedString = [resultedString stringByAppendingString:[NSString stringWithFormat:@"\n"]];
}
[resultingStringTextView insertText:resultedString];

NSString基本的に、日付を表す5 つの配列から始めます。私は 2 つNSDateFormatterの s:を作成しています: は、日付の元の文字列表現を実際の;originalFormatに変換するために使用されます。日付フォーマッタで生成された の新しい目的の文字列表現を作成するために使用されます。NSDatenewFormatNSDateoriginalFormat

これは私の結果のログです:

2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 0 = 2011-09-18
2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 1 = 2011-10-16
2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 2 = 2011-11-13
2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 3 = 2011-12-11
2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 4 = 2012-01-08
2012-08-26 nsDateFormatterPuzzle[3261:303] original item # 5 = 2012-02-05
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 0 = 18/09/2011
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 1 = (null)
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 2 = 13/11/2011
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 3 = 11/12/2011
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 4 = 08/01/2012
2012-08-26 nsDateFormatterPuzzle[3261:303] formatted item # 5 = 05/02/2012

[システム環境設定] --> [日付と時刻] --> [タイム ゾーン] に移動すると、

タイム ゾーンをリオ デ ジャネイロに変更しても、同じ結果が得られます。

=============================== 回避策を試す =============== ====================

私はこのバグを回避しようとしていますが、Apple はそれを修正していません。

2 つの問題があります。1 つは、この日付から PDF ファイルをレンダリングすることです。次の方法でこれを解決したと思います。

 if (formated_issue_date == NULL) {
            formated_issue_date = [BHDateFormatter bhDateFormat:data_emissao];

}

このハンドラーの使用:

+(NSString*)bhDateFormat:(NSString *)inputedDate{

    NSString *formattedDate = @"";

    NSRange range82 = NSMakeRange (8, 2);
    NSRange range52 = NSMakeRange (5, 2);
    NSRange range04 = NSMakeRange (0, 4);

    NSString *firstBlock = [inputedDate substringWithRange:range82];
    NSString *secondBlock = [inputedDate substringWithRange:range52];
    NSString *thirdBlock = [inputedDate substringWithRange:range04];

    formattedDate = [formattedDate stringByAppendingString:firstBlock];
    formattedDate = [formattedDate stringByAppendingString:@"/"];
    formattedDate = [formattedDate stringByAppendingString:secondBlock];
    formattedDate = [formattedDate stringByAppendingString:@"/"];
    formattedDate = [formattedDate stringByAppendingString:thirdBlock];

    return formattedDate;
}

2 つ目の問題は、請求書の日付が日付フォーマッタを含むテーブル ビューに読み込まれることです。これを変更すると、テーブルの並べ替えが失われます。

私のハンドラーと同じ原則を使用し、2011 年 10 月 16 日の日付を渡すことを主張すると、テーブル ビューで次のようなエラーが発生します。

これは私がこれまでに見つけた最高のコードです:

if (formatterDate == NULL) {
                        NSLog (@"outprintString '%@' = NULL", dateString);
                        NSString *newDate = [BHDateFormatter bhDateFormat:dateString];
                        if ([newDate isEqualToString:@"16/10/2011"]) {
                            formatterDate = [inputFormatter dateFromString:@"2011-10-17"];
                            NSLog(@"formatterDate = %@", formatterDate);
                            NSAlert *alert = [[[NSAlert alloc]init] autorelease];
                            [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Mountain Lion Bug: I have found a date \"16/10/2011\" in your invoice # %@ issued by %@, I must rename the date in your table view to \"17/10/2011\", the date on the rendered invoice file will be display correctly. I apologize for this, but it is an operating system level bug that has to be fixed by Apple.","A comment here"),invoiceNumber, emitente]];
                            [alert runModal];
                        }
                    }

コメントをお願いします。

ありがとう!

4

2 に答える 2

5

私はあなたが正しいと信じています。これはバグです。報告する必要があります。興味深いことに、タイムゾーンをリオと同じタイムゾーンにあるヌーク グリーンランドに設定すると、正常に動作します。また、"2011-10-15" と "2011-10-17" はリオのタイム ゾーンで問題なく動作しますが、"2011-10-16" では動作しません。これは本当に奇妙です。

これは、これをテストするために使用した単純化されたコードです。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    NSArray *unformattedDatesArray = [[NSArray alloc] initWithObjects:@"2011-09-18",@"2011-10-16",@"2011-11-13",@"2011-12-11",@"2012-01-08",@"2012-02-05", nil];

    NSDateFormatter *originalFormat = [[NSDateFormatter alloc] init];
    [originalFormat setDateFormat:@"yyyy-MM-dd"]; // hh:mm:ss
    NSDateFormatter *newFormat = [[NSDateFormatter alloc] init];
    [newFormat setDateFormat:@"dd/MM/yyyy"]; // hh:mm:ss

    for (NSString * aString in unformattedDatesArray) {
        NSString *formattedDate = [newFormat stringFromDate:[originalFormat dateFromString:aString]];
        NSLog(@"Original date string is: %@  formatted date as string is: %@",aString, formattedDate);
    }
}

追加情報:

この問題の原因を見つけるために、次のコードを使用して 2011 年のすべての日付をループしました。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    NSDateFormatter *originalFormat = [[NSDateFormatter alloc] init];
    [originalFormat setDateFormat:@"yyyy-MM-dd"]; // hh:mm:ss
    NSDateFormatter *newFormat = [[NSDateFormatter alloc] init];
    [newFormat setDateFormat:@"dd/MM/yyyy"]; // hh:mm:ss

    NSDate *start = [originalFormat dateFromString:@"2011-01-01"];
    NSDate *newDate;
    for (int i=0; i<365; i++) {
        newDate = [start dateByAddingTimeInterval:86400 * i];
        NSString *formattedDate = [newFormat stringFromDate:newDate];
        NSLog(@"formatted date as string is: %@",formattedDate);
    }
}

日付文字列を見ると、2 月 19 日が 2 つあり、10 月 16 日がないことがわかります。これが、その日付に対して null を取得する理由です (ただし、日付オブジェクト自体をログに記録すると、すべての日付が正しく取得されます)。

于 2012-08-28T22:30:41.583 に答える
1

バグではありません。10 月 16 日は、ブラジルがその年に南半球の夏時間に移行した日であり、提案された時刻 (明示的な時刻を指定していないため、午前 0 時であると想定されます) は欠落している時間です。ありえない時間です。

于 2014-05-24T00:21:34.203 に答える