01/04/2010 00:00
说这是一个国家,例如观察DST(夏令时间)的英国,在这个特定时间我们正在夏令时.当我将此日期转换为UTC并将其存储在数据库中时,实际存储为:
31/03/2010 23:00
由于DST的日期将调整为-1小时.当您在提交时观察DST时,此功能正常.但是,当时钟被调整回来时会发生什么?当我从数据库中提取该日期并将其转换为当地时间,特定的日期时间将被视为31/03/2009 23:00,实际上它被处理为01/04/2010 00:00.
纠正我,如果我错了,但这不是一个缺点,当存储时间作为UTC?
时区转换示例
基本上我正在做的是将信息提交到我的系统的日期/时间,以允许用户做范围报告.这是我如何存储日期/时间:
public DateTime LocalDateTime(string timeZoneId) { var tzi = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,tzi).ToUniversalTime().ToLocalTime(); }
存储为UTC:
var localDateTime = LocalDateTime("AUS Eastern Standard Time"); WriteToDB(localDateTime.ToUniversalTime());
解决方法
然而,有一个问题,当地的一些时代是不明确的.例如,2010年10月31日上午1:30在英国可以代表UTC 01:30或UTC 02:30,因为时钟从上午2点到凌晨1点.您可以从UTC所表示的任何瞬间获得当前时间显示的时间,但操作不可逆.
同样地,您可能有一个从不发生的当地时间 – 例如,2010年3月28日上午1:30在英国没有发生,因为在凌晨1点,时钟向上跳到凌晨2点.
很长一段时间,如果你想要及时表达一个瞬间,你可以使用UTC并得到一个明确的表示.如果您想要在特定时区表示时间,则需要使用时区本身(例如欧洲/伦敦)以及即时的UTC表示或当地日期和时间以及该特定时间的偏移量(消除DST转换周围的歧义).另一个选择是只存储UTC和它的偏移量;这可以让您在当时的时间告诉当地时间,但这意味着您无法预测当地时间将在一分钟之后,因为您不太了解时区. (这是DateTimeOffset存储的,基本上是)
我们希望能够在Noda Time中使用起来非常方便,但您仍然需要将其视为可能.
编辑:
您显示的代码不正确.这就是为什么我已经改变了代码的结构,使其更容易看到,但您会看到它执行相同的调用.
var tzi = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time"); var aussieTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,tzi); var serverLocalTime = aussieTime.ToLocalTime(); var utcTime = serverLocalTime.ToUniversalTime();
所以,现在让我们考虑一下 – 当地时间是13:38(UTC 1,伦敦),12:38 UTC,22:39在悉尼.
您的代码将给出:
aussieTime = 22:39 (correct) serverLocalTime = 23:39 (*not* correct) utcTime = 22:39 (*not* correct)
你不应该在TimeZoneInfo.ConvertTimeFromUtc的结果上调用ToLocalTime – 它将假定它在UTC DateTime上被调用(除非它实际上有DateTimeKind.Local,在这种情况下不会).
因此,如果您在这种情况下准确保存22:39,则无法准确保存UTC的当前时间.