DateTime必须包含时区信息并考虑夏令时

本文关键字:夏令时 信息 包含时 DateTime | 更新日期: 2023-09-27 17:57:33

我的程序有两个面向第三方系统的集成。集成包括1)TCP/IP上的XML协议和2)WCF中的Web服务。

在任何一种情况下,集成合作伙伴都需要我传递给他们的TimeStamps/DateTimes来包含有关时区和夏令时的信息,这样他们就可以显示正确的时间,而不管客户的时区/位置如何。

我宁愿不更改当前的协议,在这两种情况下,他们都期望DateTime,所以我的问题是:是否可以将时区和夏令时信息作为DateTime的一部分传递?

现在我的时间戳是这样的:

2011-04-27T15:14:13.963

我希望它看起来像这样(我位于丹麦,所以我们使用CEST),并且能够使用DateTime对象传输信息

 2011-04-27T15:14:13.963 +01:00

然而,我不知道我应该如何实现这一点,也不知道如何将夏令时因素考虑在内

DateTime必须包含时区信息并考虑夏令时

如果你需要知道日期/时间时区,你必须想出自己的封装:

  • DateTime仅包含日期/时间以及它是"本地"(在系统时区中)还是UTC的信息
  • DateTimeOffset包含有关日期/时间及其到UTC的偏移量的信息,但这与其时区不同

不过,您可以将TimeZoneInfoDateTimeOffset组合在一个结构中。

或者,如果你愿意使用beta-quality,API-could-still-change软件,你可以使用Noda Time,我开始的这个项目基本上是将Joda Time API移植到.NET.

这是在过程中的表现。。。至于传递信息,您需要了解您的集成合作伙伴使用了什么。例如,他们可能想要UTC时间和Olsen时区名称。。。或者他们可能只是想要偏移。

如果您只需要知道创建时间戳时用户的本地时间,那么包括UTC的"当前"偏移量就足够了,而不包括完整的时区信息。这只是意味着你不知道2秒后的当地时间是多少。。。

使用DateTimeOffset而不是DateTime,后者包含时区偏移信息。

至于夏令时,您需要使用Olsen数据库。

请参阅此相关问题。

使用UTC时间,您可以坚持使用DateTime。UTC转换为当地时间(或任何其他时间)。这也解决了夏令时的问题。使用UTC是最好的解决方案,我已经有了一些经验。

小型演示:

namespace TimeZoneTest
{
  using System;
  using System.Globalization;
  class Program
  {
      static void Main(string[] args)
      {
          // get local time
          DateTime localTime = DateTime.Now;
          Console.WriteLine(string.Format(
              CultureInfo.CurrentCulture, 
              "localTime = {0}, localTime.Kind = {1}", 
              localTime, 
              localTime.Kind));
          // get local time zone, or use TimeZoneInfo to get any time zone you want
          TimeZone ltz = TimeZone.CurrentTimeZone;
          Console.WriteLine(string.Format("local time zone = {0}", ltz.StandardName));
          // convert local time to UTC
          DateTime utcTime = ltz.ToUniversalTime(localTime);
          Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
              "utcTime = {0}, utcTime.Kind = {1}",
              utcTime,
              utcTime.Kind));
          // transfer date via service, as ISO time string
          string isoUtc = utcTime.ToString("o");
          Console.WriteLine("...");
          Console.WriteLine(string.Format("transfer: isoUtc = {0}", isoUtc));
          Console.WriteLine("...");
          // now on the other side
          DateTime utcTimeRecieved = DateTime.ParseExact(
              isoUtc, 
              "o", 
              CultureInfo.InvariantCulture, 
              DateTimeStyles.RoundtripKind);
          Console.WriteLine(string.Format(CultureInfo.CurrentCulture, 
              "utcTimeRecieved = {0}, utcTimeRecieved.Kind = {1}", 
              utcTimeRecieved, 
              utcTimeRecieved.Kind));
          // client time zone, or use TimeZoneInfo to get any time zone you want
          TimeZone ctz = TimeZone.CurrentTimeZone;
          Console.WriteLine(string.Format("client time zone = {0}", ctz.StandardName));
          // get local time from utc
          DateTime clientLocal = ctz.ToLocalTime(utcTimeRecieved);
          Console.WriteLine(string.Format(
              CultureInfo.CurrentCulture,
              "clientLocal = {0}, clientLocal.Kind = {1}",
              clientLocal,
              clientLocal.Kind));
          Console.WriteLine("'nPress any key to exit..");
          Console.ReadKey();
      }
  }

}