ios – 为什么NSDateFormatter在巴西时区的19/10/2014返回null?

NSString *dateString = @"19/10/2014";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd/MM/yyyy"];
NSDate *myDate = [dateFormatter dateFromString:dateString];

为什么myDate在这个特定的日期是空的(19/10/2014)?

如果我将dateString更改为@“25/10/2014”,dateFormatter正确返回日期…我的代码有什么问题?

*当我的iPhone时区为“巴西利亚,巴西”时,此代码返回null.例如,当我的时区是“华盛顿特区,EUA”时,代码返回正确的日期.

解决方法

我们可以通过明确将时区设置为“Brazil / East”来重现您的问题:
#import <Foundation/Foundation.h>

int main(int argc,const char * argv[])
{

    @autoreleasepool {
        NSString *dateString = @"19/10/2014";
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Brazil/East"];
        [dateFormatter setDateFormat:@"dd/MM/yyyy"];
        NSDate *myDate = [dateFormatter dateFromString:dateString];
        NSLog(@"myDate = %@",myDate);
    }
    return 0;
}

以下是输出:

2014-06-06 14:22:28.254 commandLine[31169:303] myDate = (null)

由于您没有在dateString中给出时间,因此系统将采取午夜.但是那个日子午夜在巴西时区不存在.

Brazil changes from BRT (daylight-saving time zone) to BRST (non-daylight-saving time zone) on October 19,2014,从“18/10/2014”的最后一刻直接跳到“19/10/2014 01:00:00”.

由于“19/10/2014 00:00:00”不存在,NSDateFormatter返回nil.我认为这是NSDateFormatter方面的不好的行为,但我们必须处理它. – [NSDateFormatter dateFromString:]最终调用CFDateFormatterGetAbsoluteTimeFromString,它使用International Components for Unicode (icu) library udat_parseCalendar function来解析日期.

您可以通过使解析器使用中午而不是午夜作为默认时间来解决问题.没有时区在中午之前/从夏令时更改.让我们在一个给定的时区中写一个帮助函数返回中午的某个任意日期:

static NSDate *someDateWithNoonWithTimeZone(NSTimeZone *timeZone) {
    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.timeZone = timeZone;
    components.era = 1;
    components.year = 2001;
    components.month = 1;
    components.day = 1;
    components.hour = 12;
    components.minute = 0;
    components.second = 0;
    return [[NSCalendar autoupdatingCurrentCalendar] dateFromComponents:components];
}

然后我们将日期格式化程序的defaultDate设置为中午日期:

int main(int argc,const char * argv[])
{

    @autoreleasepool {
        NSString *dateString = @"19/10/2014";
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"Brazil/East"];
        dateFormatter.dateFormat = @"dd/MM/yyyy";
        dateFormatter.defaultDate = someDateWithNoonWithTimeZone(dateFormatter.timeZone);
        NSDate *myDate = [dateFormatter dateFromString:dateString];
        NSLog(@"myDate = %@",myDate);
    }
    return 0;
}

这里的输出:

2014-06-06 14:52:31.939 commandLine[31982:303] myDate = 2014-10-19 14:00:00 +0000

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...