IOS 6数据格式化程序

IOS 6数据格式化程序,ios,ios6,nsdateformatter,Ios,Ios6,Nsdateformatter,请帮助我在IOS6上使用dateformatter,请参阅下面的代码 NSString stringDate = @"12/31/9999"; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; [dateFormatter setDateFormat:@"MM/dd/yyyy"]; NSDate *dateCheck = [dateFormatter dateFromString:stringDate]; NS

请帮助我在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
这是将字符串日期转换为日期12/31/9999时的输出

从以前版本的IOS6中,输出为

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

我为公司的企业应用程序修复了这个问题

对于使用已知格式字符串的日期格式化程序(如我们用于从sqlite数据库解析日期的字符串),它应该解决这个问题

但是,它不会修复:

  • IsLenent设置为true的NSDateFormatters
  • 使用样式而不是格式字符串进行解析的NSDateFormatters
  • 它似乎不会对iOS 5或5.1造成负面副作用。在此之前,我没有测试过任何东西。但是,我确实稍微弄乱了NSDateFormatter的内部结构,因此这可能无法通过应用商店提交过程。但是,如果您在企业程序下编写程序(或者只使用临时部署),这应该不会是一个问题。此外,如果您已打开Islent,它将试图避开,但无法保证您不会遇到任何问题

    我要强调,这是一个临时解决办法。我没有在所有可能的情况下测试这个,所以您应该自行承担风险

    我创建了以下类别:

    NSDateFormatter+HotFix.h

    #import <Foundation/Foundation.h>
    
    @interface NSDateFormatter (HotFix)
    
    - (NSDate*)dateFromString:(NSString *)string;
    
    @end
    
    #导入
    @接口NSDateFormatter(修补程序)
    -(NSDate*)dateFromString:(NSString*)字符串;
    @结束
    
    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+HotFix.h”
    #进口
    @实现NSDateFormatter(修补程序)
    -(NSDate*)dateFromString:(NSString*)string
    {
    如果(!string)返回nil;
    //HACK:使用原始实现
    void*baseFormatter=nil;
    对象\u getInstanceVariable(self、\u formatter、&baseFormatter);
    如果(!baseFormatter)返回nil;
    //使用底层的CFDateFormatter来解析字符串
    CFDateRef rawDate=CFDateFormatterCreateDateFromString(kCFAllocatorDefault,(CFDateFormatterRef)baseFormatter,(CFStringRef)string,NULL);
    NSDate*来源=(NSDate*)原始日期;
    //我们不支持对日期(或样式)、句号进行宽松的解析。
    if(source&&!self.islenent&&self.dateStyle==NSDateFormatterNoStyle&&self.timeStyle==NSDateFormatterNoStyle)
    {
    //如果有效,则找出格式字符串是否包含一年(任何1到5个y字符的集群)
    NSString*格式=[self dateFormat];
    NSRegularExpression*regex=[NSRegularExpression regular expressionwithpattern:@“y{1,5}”选项:nsregularexpressioncase不敏感错误:NULL];
    NSArray*matches=[regex matchesInstalling:格式选项:0范围:NSMakerRange(0,[格式长度])];
    如果([匹配计数]>0)
    {
    for(NSTextCheckingResult*匹配结果)
    {
    //检查引号中是否包含y分组。如果是,请忽略它
    if(result.range.location>0&&result.range.location+result.range.length<[格式长度]-1)
    {
    如果([格式字符索引:result.range.location-1]='\''&&
    [格式字符索引:result.range.location+result.range.length+1]=='\''继续;
    }
    NSString*possibleYearString=[string substringWithRange:result.range];
    NSInteger possibleYear=[possibleYearString integerValue];
    如果(可能大于3500)
    {
    NSCalendar*日历=[NSCalendar currentCalendar];
    NSDateComponents*dateComp=[日历组件:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:source];
    dateComp.year=可能的年份;
    返回[calendar dateFromComponents:dateComp];
    }
    }
    }
    }
    返回[源自动释放];
    }
    @结束
    
    它将替换NSDateFormatter的现有dateFromString方法。它的工作原理是尝试正常解析字符串,然后检查formatString是否包含一组年份格式字符。如果是,则手动提取年份并检查其是否大于3500。最后,如果是这种情况,它将重写输出以获得正确解析的年份

    只要将它包含在您的项目中,它就会生效。您不需要将头导入到每个使用NSDateFormatter的文件中,只需在中编译.m即可修改该类。如果有任何其他类别更改了dateFromString:,则无法定义此类的效果


    我希望这会有所帮助。

    关于iOS6日期格式化程序中可能存在的错误,还有其他报告,这似乎是一个错误。格式化程序似乎只能在未来1500年内使用(3512)哦,但是对于不同的格式,如MM dd yyyy,它不是1500年的间隔。我不理解这个评论,它与格式没有任何关系,只是你放在哪一年——当然9999是1500年以后的事了。如果您尝试3512,您将看到它是有效的,而3513不是。