NSDateFormatter拼图!这是新的山狮虫吗?

fun*_*dor 6 macos cocoa objective-c nsdateformatter

我相信我可能发现了一个错误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];
Run Code Online (Sandbox Code Playgroud)

基本上,我从一个5 NSString秒的数组开始,代表日期.我正在创建2 NSDateFormatters:originalFormat用于将日期的原始字符串表示转换为实际NSDate; newFormat用于创建NSDate使用originalFormat日期格式化程序生成的新的所需字符串表示形式.

这是我的结果日志:

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
Run Code Online (Sandbox Code Playgroud)

请注意,如果您转到系统偏好设置 - >日期和时间 - >时区

并将您的时区更改为里约热内卢,您将获得相同的结果.

================================尝试解决方法=============== ====================

我试图找到解决这个错误的同时苹果公司没有解决它.

我有两个问题,一个是从这个日期渲染PDF文件,我想我已经通过以下方式解决了这个问题:

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

}
Run Code Online (Sandbox Code Playgroud)

使用此处理程序:

+(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;
}
Run Code Online (Sandbox Code Playgroud)

第二个问题是发票日期被加载到包含日期格式化程序的表视图中,更改此值会导致表的排序丢失.

使用与我的处理程序相同的原则,并坚持传递16/10/2011日期会导致表视图出错,如: - [__ NSCFString timeIntervalSinceReferenceDate]:无法识别的选择器发送到实例0x40265f3a0

这是我到目前为止找到的最好的代码:

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];
                        }
                    }
Run Code Online (Sandbox Code Playgroud)

你能评论一下吗?

谢谢!

rde*_*mar 5

我相信你是对的 - 这是一个错误,你应该报告它.有趣的是,如果你将时区设置为与里约相同的时区Nuuk-Greenland,它可以正常工作.此外,"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);
    }
}
Run Code Online (Sandbox Code Playgroud)

补充信息:

为了找到这个问题的根源,我使用以下代码遍历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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当您查看日期字符串时,您会发现有2月19日和10月16日,这就是为什么您在该日期获得null(尽管如果您自己记录日期对象,则可以正确获取所有日期).