为什么NSDateFormatter在巴西时区19/10/2014返回null? [英] Why NSDateFormatter is returning null for a 19/10/2014 in a Brazilian time zone?
问题描述
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屋!