如何在C#中将日期时间转换为特定时区?

21
我需要帮助将一个 DateTime 转换为特定的时区。下面的代码不正确。 gmTime = 2013年03月02日 上午1:00:00
 TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
 var time = timeZoneInfo.ConvertTime(gmTime, timeZone);

当我调试time的值时,应该在应用时为03/01/2013 8:00:00 PM,但返回的值为03/02/2013 1:00:00 AM
如果我使用time.ToLocalTime(),那么我会得到正确的值。然而,我需要将time转换为不同的时区。

你有没有考虑使用 Noda Time 来代替呢?https://code.google.com/p/noda-time/ - Ray Cheng
我也想建议使用noda-time,我之前也成功地使用过http://www.babiej.demon.nl/Tz4Net/main.htm。 - JeremyWeir
1
可能是如何将DateTime转换为特定时区?的重复问题。 - Michael Freidgeim
3个回答

20

DateTime对象有一个“Kind”变量,帮助TimeZoneInfo知道如何处理它。在MSDN文档中TimeZone.ConvertTime有如下内容:

DateTimeKind.Local,将本地时间转换为目标时区的时间。

DateTimeKind.Utc,将协调世界时(UTC)转换为目标时区的时间。

DateTimeKind.Unspecified,被认为是本地时间。

例如:

  Console.WriteLine("Local time zone is '{0}'.", TimeZoneInfo.Local.Id);

  var gmTime          = new DateTime(2013, 03, 02, 01, 00, 00, DateTimeKind.Utc);
  var localTime       = new DateTime(2013, 03, 02, 01, 00, 00, DateTimeKind.Local);
  var unspecifiedTime = new DateTime(2013, 03, 02, 01, 00, 00);

  var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

  var gmTimeConverted           = TimeZoneInfo.ConvertTime(gmTime,          timeZone); // 03/02/2013 8:00:00AM
  var localTimeConverted        = TimeZoneInfo.ConvertTime(localTime,       timeZone); // 03/02/2013 
  var unspecifiedTimeConverted  = TimeZoneInfo.ConvertTime(unspecifiedTime, timeZone);

  Console.WriteLine("Converting GMT         to EST: {0}", gmTimeConverted);
  Console.WriteLine("Converting Local       to EST: {0}", localTimeConverted);
  Console.WriteLine("Converting Unspecified to EST: {0}", unspecifiedTimeConverted);

结果如下:

本地时区为'太平洋标准时间'。
将GMT转换为EST:2013年3月1日晚上8:00:00
将本地时间转换为EST:2013年3月2日上午4:00:00
将未指定时区的时间转换为EST:2013年3月2日上午4:00:00

或者如果您的本地时区是'东部标准时间',则会得到以下结果

本地时区为'东部标准时间'。
将GMT转换为EST:2013年3月1日晚上8:00:00
将本地时间转换为EST:2013年3月2日上午1:00:00
将未指定时区的时间转换为EST:2013年3月2日上午1:00:00



如果您希望TimeZoneInfo将“未指定”视为UTC,请使用类似于TimeZoneInfo.ConvertTimeFromUtc的函数。再次来自MSDN文档

DateTimeKind.Local,将引发ArgumentException异常。

DateTimeKind.Unspecified或DateTimeKind.Utc,则从协调世界时(UTC)进行转换。


8

尝试像以下这样做,Chace

TimeZoneInfo estTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime estDateTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, estTimeZone);

1
以下代码将允许您从任意时区转换到另一个时区。我们使用DateTimeOffset,它将允许您传递UTC偏移量。您可以考虑是否只使用DateTimeOffset而不是DateTime来满足您的需求。但如果您想使用DateTime,这里有一些代码可以为您进行转换:
public DateTime ChangeTimeZone(DateTime dateTimeInput, TimeZoneInfo sourceTimeZone, TimeZoneInfo destTimeZone)
{
    var zonedTime = new DateTimeOffset(DateTime.SpecifyKind(dateTimeInput, DateTimeKind.Unspecified),
                                       sourceTimeZone.GetUtcOffset(dateTimeInput));
    var utcTime = zonedTime.UtcDateTime;
    
    return TimeZoneInfo.ConvertTime(utcTime, destTimeZone);
}

你可能会注意到我们明确调用了 SpecifyKind 并将其设置为 Unspecified。这么做的原因是,如果在 dateTimeInput 上指定了 Kind,那么 UtcOffset 必须与该 Kind 匹配 -- 因此,如果它是 DateTimeKind.Utc,则该数字必须为 0。如果是 Local,则必须是本地时区偏移量,否则会出现异常。当然,如果你已经知道了 Kind,那么可以跳过此函数,直接进入 TimeZoneInfo.ConvertTime


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接