尝试在iOS6中运行此功能(尚未测试iOS6之前):
NSDateFormatter *julianDayDateFormatter = nil;
julianDayDateFormatter = [[NSDateFormatter alloc] init];
[julianDayDateFormatter setDateFormat:@"g"];
for (NSString *timeZone in [NSTimeZone knownTimeZoneNames]) {
julianDayDateFormatter.timeZone = [NSTimeZone timeZoneWithName: timeZone];
NSDate *date = [julianDayDateFormatter dateFromString:[NSString stringWithFormat:@"%d", 2475213]];
if (date == nil)
NSLog(@"timeZone = %@", timeZone);
}
您将获得以下输出:
America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
任何人都可以解释为什么这四个时区的行为都是这样的,而NSDateFormatter设置为朱利安日数?所有其他时区使NSDateFormatter返回实际的NSDates。
答案 0 :(得分:61)
我怀疑怀疑。只是怀疑,但非常强烈。
该值代表2064年10月19日。巴西时区观察夏令时从当地午夜开始 - 这是他们的时钟前进的时间,因此午夜本身不存在。 10月19日是其中一个转变。
以下是一些使用Noda Time的示例代码,我的.NET日期/时间API。它会检查它所知道的每个时区的当天开始时间是否实际是午夜:
using System;
using NodaTime;
class Test
{
static void Main()
{
var localDate = new LocalDate(2064, 10, 19);
var provider = DateTimeZoneProviders.Tzdb;
foreach (var id in provider.Ids)
{
var zone = provider[id];
var startOfDay = zone.AtStartOfDay(localDate).LocalDateTime.TimeOfDay;
if (startOfDay != LocalTime.Midnight)
{
Console.WriteLine(id);
}
}
}
}
这产生了一个非常相似的列表:
America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Brazil/East
我怀疑巴西/东方可能是America / Sao_Paolo的别名,这就是为什么它不在你的名单上。
无论如何,要回到你的朱利安日问题 - 我怀疑格式化程序总是希望返回当地午夜的NSDate *
。 2064年10月19日在那些时区中存在 ...因此它返回零。就个人而言,我建议它应该返回1am值,但是嘿......
答案 1 :(得分:16)
致Jon Skeet让我走上正轨。但是,我只是想在iOS环境中澄清他的答案。
当您要求NSDateFormatter将朱利安日数转换为NSDate时,您只能在要解析的字符串中指定整数(通常可以指定当天的小时/分钟/秒的小数部分)。 因为Apple在午夜划定了朱利安的日子(而不是天文学的中午,请在这里阅读更多内容:http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table)并且一些中午根本不存在(感谢指出@JonSkeet)NSDateFormatter识别出那个特定的时间点在该时区不存在并返回nil。
为了记录,iOS5不是这样的,我同意Jon Skeet,NSDateFormatter应该返回一个根据DST而不是nil调整的NSDate,因为事实上存在特定的朱利安日!我向Apple提交了一个错误。