2013-03-18 50 views
5

我正在开发运行24/7/365全天候GPS设备报告的软件。部分报告输出要求我们将存储的数据库时间(保留在中央标准时间)转换为用户计时器(任何请求的时区)。当人们每天运行两次报告时,我们会遇到DST问题,这些报告会在时间更改之前开始并结束。它未能在一个行:转换DayLight附近的日期时间节省时间?

return TimeZoneInfo.ConvertTime(dateToConvert, DatabaseTime, UserTime); 

dateToConvert是要转换一个DateTimeDatabaseTimeUserTime都是TimeZoneInfo对象。我没有做任何棘手或复杂的事情,但靠近DST时间更改的日期时间会引发异常。例如3/10/2013 2:02:11 AM即使它正在从中央时间“转换”到中央时间。

在DST时间变化附近处理DateTimes的最佳方法是什么?

+3

这可能更大修的比你想要的,但它可能是更好的储存所有的日期/格林尼治标准时间(因为CST经历了DST的变化,也有规模不连续性是在格林尼治标准时间不在那里),只有转换为显示目的(以及可能转换输入参数)。 – twalberg 2013-03-18 17:23:48

+0

如果我从头开始,我肯定会这样做。我喜欢这些数据尽可能中立的想法,我认为这将是实现这一目标的方式。 – 2013-03-18 17:28:07

+0

只是为了确认:是否有可能在数据库中存储'3/10/2013 2:02:11 AM',因为它在跳过的小时内? – 2013-03-18 17:31:21

回答

1

转换应该正常工作,因为时间不是真正的垃圾,正如汉斯所说,而只是没有调整(我刚刚发明的一个术语)。 3/10/2013 2:02:11 AM CDT == 3/10/2013 8:02:11 AM UTC == 3/10/2013 3:02:11 AM CDT ......它们都是语义等价的。如果你不相信我,请在timeanddate.com处进行转换,看看他们是否相等(尽管他们的计算器为四舍五入到最接近的5分钟)。无论.NET代码是否允许这种语义等价,我还没有尝试过,因为我目前不在我的开发箱前面。

更新#1:

运行下面的代码设置为CST时区的计算机上:

using System; 

namespace TimeZoneSample 
{ 
    public static class Program 
    { 
     public static void Main() 
     { 
      DateTime t = DateTime.Parse("3/10/2013 2:02:11 AM"); 
      Console.WriteLine(t); 
      Console.WriteLine(t.ToUniversalTime()); 
      Console.WriteLine(t.ToUniversalTime().ToLocalTime()); 
     } 
    } 
} 

我们得到以下控制台输出:

3/10/2013 2:02:11 AM 
3/10/2013 8:02:11 AM 
3/10/2013 3:02:11 AM 

证明我原来的解释是正确的。 狴ERAT demonstrandum

+0

我同意并且完全和你在一起,但.Net的DateTime似乎并没有这样工作。 – 2013-03-18 19:07:43

+0

按照您的编辑,如果我暂停调试器,将其插入观察名单,但是当代码实际上试图执行'返回TimeZoneInfo.ConvertTime的作品(dateToConvert.ToUniversalTime()ToLocalTime(),DatabaseTime,UserTime); '我得到一个错误,说'DatabaseTime'需要'TimeZoneInfo.Local'。我不知道这是否是我们系统中可以接受的假设。 – 2013-03-18 21:52:17

+0

我和我的团队交谈过。事实证明,自从我们托管自己的服务器以来,这是一个足够安全的假设。 – 2013-03-18 22:12:16

3

我遇到了这个问题。我通过添加新的GMT时间列来修复它。这使得应用程序可以使用原始数据和任何修补程序与GMT一起工作。然后我改变了应用程序,以便任何夏令时存在问题的代码都可以访问这个新列。另外,随着时间的推移,我重新将用于计算的代码重新指向这个新列,使显示器与旧列一起工作。这不是优雅的,但它的工作原理很简单。

4

你的数据库中有垃圾,3/10/2013 2:02:11 AM从来不存在。那天凌晨1点59分那天凌晨3点,钟表移动了一个小时。 .NET不会忍受那个垃圾日期。

您将需要了解垃圾时间戳记如何在您的dbase中结束。很明显,将时间从一个时区转换到另一个时区忽略夏令时规则,比如在一个时间段内活动,而不是在另一个时间活动,这很可能是垃圾的来源。如果你不能修复你的dbase使用UTC,那么至少在你的代码中使用它。首先在一个时区前往UTC,然后再返回到另一个时区的当地时间。使用TimeZoneInfo类,ConvertTimeFrom/ToUtc方法。

+0

后端代码,采用GPS条目并将其推入数据库都写在VB6(我讨厌它,我不能等到我们把我们的C#的变化),我想,也许我们VB6没有给予足够在计算过程中注意DST。 – 2013-03-18 18:16:03

+0

是的,VB6后端很可能不会这样做。 – 2013-03-18 18:51:24

1

我会按照其他的答案中的一个,如果这是在所有可能的 - 要正确地解决这个问题。如果在秋季过渡期间你的时间不正确,它不会产生异常,它只会随机关闭一个小时。

有一种解决方法可以让您摆脱目前的困境。由于这只是在春季的缺失小时内会导致异常,因此您可以捕捉异常并在重复转换之前添加一小时。

+0

作为一个快速解决方案,我在过去的半个小时里一直在玩弄它。 – 2013-03-18 21:04:54