为什么NSDateFormatter在巴西时区19/10/2014返回null? [英] Why NSDateFormatter is returning null for a 19/10/2014 in a Brazilian time zone?

查看:130
本文介绍了为什么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)??

Why myDate is null for this specific date (19/10/2014)??

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

If i change the dateString to @"25/10/2014", dateFormatter return the date correctly... What is wrong with my code?

* 当我的iPhone时区为Brasilia,Brasil时,此代码返回null。例如,当我的时区为华盛顿特区,EUA时,代码会返回正确的日期。

* This code returns null when my iPhone time zone is "Brasilia, Brasil". When my time zone is "Washington, D.C., EUA" for example, the code returns the correct date.

推荐答案

我们可以重现通过将时区明确设置为Brazil / East来解决您的问题:

We can reproduce your problem by explicitly setting the time zone to "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 中给出时间,系统会假设午夜。但巴西时区该日期的午夜

Since you didn't give a time in your dateString, the system assumes midnight. But midnight on that date doesn't exist in the Brazilian time zone.

巴西于2014年10月19日从BRT(夏令时区)变为BRST(非夏令时区),直接跳过从18/10/2014的最后一刻到19/10/2014 01:00:00。

Brazil changes from BRT (daylight-saving time zone) to BRST (non-daylight-saving time zone) on October 19, 2014, skipping directly from the last moment of "18/10/2014" to "19/10/2014 01:00:00".

自19/10/2014 00: 00:00不存在, NSDateFormatter 返回 nil 。我认为这是 NSDateFormatter 的不良行为,但我们必须处理它。 - [NSDateFormatter dateFromString:] 最终调用 CFDateFormatterGetAbsoluteTimeFromString ,它使用 udat_parseCalendar function >用于Unicode(icu)库的国际组件来解析日期。

Since "19/10/2014 00:00:00" doesn't exist, NSDateFormatter returns nil. I think this is bad behavior on the part of NSDateFormatter, but we have to deal with it. -[NSDateFormatter dateFromString:] eventually calls CFDateFormatterGetAbsoluteTimeFromString, which uses the udat_parseCalendar function from the International Components for Unicode (icu) library to parse the date.

您可以通过使解析器使用正午而不是午夜来解决问题默认时间。中午没有时区变为夏令时。让我们编写一个辅助函数,返回给定时区中某个任意日期的正午:

You can work around the problem by making the parser use noon instead of midnight as the default time. No time zones change to/from daylight saving time at noon. Let's write a helper function that returns noon of some arbitrary date in a given time zone:

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 到这个中午的日期:

Then we set the date formatter's defaultDate to this noon date:

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

这篇关于为什么NSDateFormatter在巴西时区19/10/2014返回null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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