IOS 6 NSDateFormatter

请帮我在IOS6上的dateformatter,请看下面的代码

NSString stringDate = @"12/31/9999"; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; [dateFormatter setDateFormat:@"MM/dd/yyyy"]; NSDate *dateCheck = [dateFormatter dateFromString:stringDate]; NSLog(@"Date = %@", dateCheck); 

输出是

 Date = 1999-12-31 08:00:00 +0000 

这是将stringdate转换为date12/31/9999时的输出。

从以前的IOS6版本输出

 Date = 9999-12-31 08:00:00 +0000 // Correct 

我为我公司的企业应用程序做了一个修复。

它应该使用已知的格式string(如我们用来parsingdate从我们的sqlite数据库)的date格式化程序修复这个问题。

但是,它不会修复:

  1. 将isLenient设置为true的NSDateFormatters。
  2. NSDateFormatters使用样式而不是格式string进行分析。

它似乎不会导致iOS 5或5.1的负面影响。 我还没有testing过任何东西。 但是,我搞砸了NSDateFormatter的内部有点,所以这可能不会通过App Store提交过程。 但是,如果您在企业程序下编写程序(或者只是使用临时部署),这应该不成问题。 另外,如果你有耐心,它会尽量避开,但是不能保证你不会遇到任何问题。

我想强调这是一个临时解决scheme。 我没有在所有可能的情况下对此进行testing,因此您应该自行承担风险。

我创build了以下类别:

NSDateFormatter + HotFix.h

 #import <Foundation/Foundation.h> @interface NSDateFormatter (HotFix) - (NSDate*)dateFromString:(NSString *)string; @end 

NSDateFormatter + HotFix.m

 #import "NSDateFormatter+HotFix.h" #import <objc/runtime.h> @implementation NSDateFormatter (HotFix) - (NSDate*)dateFromString:(NSString *)string { if (!string) return nil; //HACK: Use the original implementation void* baseFormatter = nil; object_getInstanceVariable(self, "_formatter", &baseFormatter); if (!baseFormatter) return nil; //Use the underlying CFDateFormatter to parse the string CFDateRef rawDate = CFDateFormatterCreateDateFromString(kCFAllocatorDefault, (CFDateFormatterRef)baseFormatter, (CFStringRef)string, NULL); NSDate* source = (NSDate*)rawDate; //We do not support lenient parsing of dates (or styles), period. if (source && !self.isLenient && self.dateStyle == NSDateFormatterNoStyle && self.timeStyle == NSDateFormatterNoStyle) { //If it worked, then find out if the format string included a year (any cluster of 1 to 5 y characters) NSString* format = [self dateFormat]; NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"y{1,5}" options:NSRegularExpressionCaseInsensitive error:NULL]; NSArray* matches = [regex matchesInString:format options:0 range:NSMakeRange(0, [format length])]; if ([matches count] > 0) { for (NSTextCheckingResult* result in matches) { //Check for the y grouping being contained within quotes. If so, ignore it if (result.range.location > 0 && result.range.location + result.range.length < [format length] - 1) { if ([format characterAtIndex:result.range.location - 1] == '\'' && [format characterAtIndex:result.range.location + result.range.length + 1] == '\'') continue; } NSString* possibleYearString = [string substringWithRange:result.range]; NSInteger possibleYear = [possibleYearString integerValue]; if (possibleYear > 3500) { NSCalendar* calendar = [NSCalendar currentCalendar]; NSDateComponents* dateComp = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:source]; dateComp.year = possibleYear; return [calendar dateFromComponents:dateComp]; } } } } return [source autorelease]; } @end 

它将取代NSDateFormatter的现有的dateFromString方法。 它的工作原理是试图正常parsingstring,然后检查formatString是否有一组年份格式的字符。 如果是这样,它会手动拉出年份并检查它是否大于3500.最后,如果是这种情况,它将重写输出以具有正确parsing的年份。

只要把它包括在你的项目中,它就会生效。 您不需要将头文件导入到每个使用NSDateFormatter的文件中,只需要将.m编译进去即可修改该类。 如果你有其他的类别改变了dateFromString:那么这个类的效果就不能被定义。

我希望这有帮助。