Friday, May 10, 2013

NSDateFormatter isLenient example ios


isLenient

Returns a Boolean value that indicates whether the receiver uses heuristics when parsing a string.
- (BOOL)isLenient
Return Value of [NSDateFormatter isLenient]
YES if the receiver has been set to use heuristics when parsing a string to guess at the date which is intended, otherwise NO.
Example of [NSDateFormatter isLenient]
#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