2012-09-27 35 views
3

請幫我在iOS6的的dateformatter,請參見下面IOS 6 NSDateFormatter

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 

這是字符串日期轉換爲日期12/31當輸出/ 9999。

從以前版本的iOS6的輸出是

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

關於iOS中日期格式化程序可能存在的錯誤,還有其他的報告 - 這似乎是一個錯誤。格式化程序似乎只能工作到未來1500年(3512) – rdelmar

+0

哦,但具有不同的格式,如MM-dd-yyyy,它不是1500年的差距。 – dianz

+0

我不明白那個評論,它與格式沒有任何關係,你投入什麼年份 - 當然是9999年,距離現在還有1500多年。如果您嘗試3512,您會看到這是有效的,而3513不會。 – rdelmar

回答

4

我給這個修復爲我公司的企業應用程序。

它應該使用已知的格式字符串(例如我們用來解析日期從我們的sqlite數據庫)日期格式化程序修復此問題。

但是,它不會修復:

  1. NSDateFormatters有isLenient設置爲true。
  2. NSDateFormatters使用樣式而不是格式字符串進行分析。

它似乎不會在iOS 5或5.1上造成負面影響。我還沒有測試過任何東西。但是,我搞砸了NSDateFormatter的內部,所以這可能無法通過App Store提交過程。但是,如果您在Enterprise程序下編寫程序(或者只是使用臨時部署),這應該不成問題。此外,如果您有任何問題,它會盡力避開,但不保證您不會遇到任何問題。

我想強調這是一個臨時解決方案。我沒有在所有可能的情況下對此進行測試,因此您應該自行承擔風險。

我創建了以下類別:

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方法。它的工作原理是試圖正常解析字符串,然後檢查formatString是否在其中包含一組年份格式化字符。如果確實如此,它會手動拉出年份並檢查它是否大於3500.最後,如果是這種情況,它將重寫輸出以具有正確解析的年份。

只需將其包含在您的項目中即可生效。您不需要將頭文件導入到使用NSDateFormatter的每個文件中,只需將編譯的.m文件修改該類即可。如果您有任何其他類別更改了dateFromString:那麼無法定義此類的效果。

我希望這會有所幫助。

+0

不適用於我..它返回null –