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
仅包含日期/时间以及它是"本地"(在系统时区中)还是UTC的信息DateTimeOffset
包含有关日期/时间及其到UTC的偏移量的信息,但这与其时区不同
不过,您可以将TimeZoneInfo
和DateTimeOffset
组合在一个结构中。
或者,如果你愿意使用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();
}
}
}