IOS 6 NSDateFormatter [英] IOS 6 NSDateFormatter

查看:139
本文介绍了IOS 6 NSDateFormatter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请帮助我使用IOS6上的dateformatter,请看下面的代码

Please help me with the dateformatter on IOS6, please see the code below

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时的输出。

This was the output when converting the string date to date 12/31/9999.

从以前版本的IOS6开始输出

From the previous version of IOS6 the output is

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


推荐答案

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

I made a fix for this for my company's enterprise applications.

应该解决这个问题使用已知格式字符串的日期格式化程序的问题(就像我们用来从我们的sqlite数据库中解析日期的那些)。

It should fix this issue for date formatters using a known format string (like the ones we use to parse dates from our sqlite database).

但是,它不会修复:


  1. 将isLenient设置为true的NSDateFormatters。

  2. 使用样式而非格式字符串的NSDateFormatters解析。

它似乎不会对iOS 5或5.1造成负面影响。我没有比那更早地测试过任何东西。但是,我确实搞乱了NSDateFormatter的内部,所以这可能无法通过App Store提交过程。但是,如果您在Enterprise程序下编写程序(或只是使用临时部署),这应该不是问题。此外,如果你有isLenient,它会试图摆脱困境,但不保证你不会遇到任何问题。

It does not seem to cause negative side effects on iOS 5 or 5.1. I have not tested anything earlier than that. However, I do mess with the internals of NSDateFormatter a bit, so this may not pass the App Store submission process. However, if you write programs under the Enterprise program (or just use ad hoc deployment), this shouldn't be a problem. Also, it will try to get out of the way if you have isLenient on, but there are no guarantees that you won't run into any issues.

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

I would like to stress that this is a Temporary Solution. I have not tested this in all possible situations, so you should implement this at your own risk.

我创建了以下类别:

NSDateFormatter + HotFix.h

NSDateFormatter+HotFix.h

#import <Foundation/Foundation.h>

@interface NSDateFormatter (HotFix)

- (NSDate*)dateFromString:(NSString *)string;

@end

NSDateFormatter + HotFix.m

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

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

It will replace the existing dateFromString method of NSDateFormatter. It works by trying to parse the string normally, then checking to see if the formatString has a set of year formatting characters inside it. If it does, it manually pulls the year out and checks if it is greater than 3500. Finally, if this is the case, it rewrites the output to have the correctly parsed year.

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

Simply include it in your project and it will take effect. You do not need to import the header into every file that uses a NSDateFormatter, just having the .m compiled in will modify the class. If you have any other categories that change dateFromString: then the effects of this class cannot be defined.

我希望这会有所帮助。

这篇关于IOS 6 NSDateFormatter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆