如何在不同时区之间转换时间(从UTC到EDT)?

18

我需要一个通用的函数将UTC时间转换为EDT时间。我的服务器在印度,其中的应用程序需要在所有时间相关操作中使用EDT时间。

我正在使用.NET 3.5。

我在某个其他论坛上找到了这个函数。

DateTime eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
        DateTime.UtcNow, "Eastern Standard Time");

当我尝试使用"Eastern Daylight Time"时,出现了错误。

"本地计算机上未找到时区ID 'Eastern Daylight Time'。"

请帮忙解决这个问题或提供其他解决方案。

4个回答

38

东部夏令时并不是一个“完整”的时区名称 - 它实际上是一个“半个”时区,总是比协调世界时慢4个小时。 (可能有正式的术语,但我不知道。)

如果您想要使用未应用夏令时的时间的EDT,为什么呢? 如果您想要一个始终与UTC具有相同偏移量的自定义时区,请使用TimeZoneInfo.CreateCustomTimeZone

请注意,如果您使用获取东部标准时区(TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),则仍将适当地应用夏令时(即在夏季期间)。

例如:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

// Prints True
Console.WriteLine(tzi.IsDaylightSavingTime(new DateTime(2009, 6, 1)));
// Prints False
Console.WriteLine(tzi.IsDaylightSavingTime(new DateTime(2009, 1, 1)));

嗨Jon,感谢您的回复。您认为这两种方案中哪个是最佳解决方案?我应该创建自定义时区还是使用TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");考虑到它将处理夏令时。那么在使用getdate()方法并采用IST时间的存储过程中,我该如何解决这个问题呢? - Shetty
1
说实话,我不太了解存储过程 - 如果可能的话,请将UTC传递给它们并使它们理解UTC。至于是否应该使用东部标准时间的自定义时区,这取决于您是否需要一个始终比UTC晚4小时的时区,还是需要与东部标准时间匹配的时区。您最初表示需要在“所有时间目的”上使用EDT-我建议您检查一下您是否真正需要EDT,或者您是否需要东部标准时间。 - Jon Skeet
好的Jon。我被要求使用波士顿市时间作为所有时间目的的标准时间,这属于EDT。我对夏令时不是很了解。尽管我的应用程序正在IST服务器上运行,但我希望它采用此时间。以前它在一个不同的服务器上运行,该服务器在EDT时区运行,我没有遇到这样的问题。 - Shetty
3
波士顿位于东部时区,夏季会使用EDT。因此,在使用FindSystemTimeZoneById("Eastern Standard Time")函数时需要注意。我同意这整个过程非常令人困惑 :( - Jon Skeet
这真的很有帮助。 我不明白为什么微软文档在他们的示例中使用了这个。 https://learn.microsoft.com/en-us/dotnet/standard/datetime/converting-between-time-zones#converting-utc-to-a-designated-time-zone (我可能提前跳到了这一章) 但是,这个解释很合理。 - Marvin Brouwer

2
我建议在计算时间段时使用协调世界时(UTC),以避免夏令时问题,然后仅在显示时使用本地时间(LocalTime)。
对于从UTC转换为本地时区的情况,请使用DateTime.ToLocalTime,然后使用DateTime.ToUniversalTime将其从本地时间转换为UTC。
如果您想要显示与服务器不同的时区,则可以使用HttpRequest.UserLanguages来创建CultureInfo对象,并使用该对象解析DateTime对象。有关完整说明,请参见此处:Microsoft link on displaying local user time for web pages. 如果是客户端-服务器架构,则如果LocalTime调用在客户端上,则它将为客户端显示LocalTime。然后,您需要将其转换为UTC并发送回服务器。
无论哪种方式,服务器都不需要知道客户端所在的位置,因此如果您有多个位于多个时区的客户端,则所有计算都将匹配。这还将允许您通过使用不同的Culture对象来显示任何时区的时间。
您可以从服务器获取UTC格式的时间数据。然后,根据需要使用DateTime.ToLocalTime或DateTime.ToUniversalTime进行转换。如果还包括日期,并且需要处理例如美国MM/dd/yyyy和欧洲dd/MM/yyyy格式,则可以使用CultureInfo类相应地解析DateTime值。这听起来比您目前拥有的更费力,但这意味着如果再次移动服务器,则无需重新编写DateTime处理。
另一个要注意的问题是使用NTP(网络时间协议)或SNTP(简单网络时间协议)同步服务器和客户端之间的时钟,如果准确度足够高。我不知道您使用的操作系统是什么,但这是Windows Server时间服务用于同步网络的方法。

嗨,克里斯,感谢您的回复。如果我没错的话,如果服务器运行在IST时区,从UTC转换为本地时间的Datetime.ToLocalTime将会给出IST时间。是这样吗? - Shetty
没错。我编辑了我的回答,来解释LocalTime与客户端服务器代码,并提供显示本地时间给Web用户的指针。 - ChrisBD
嗨,克里斯,你说得对。我正在显示不同于服务器时区的时区。这是一个客户端服务器架构。但我不想依赖于客户端系统时间,因为所有客户端机器的时间可能不完全相同。而如果使用服务器时间,它将对所有客户端都是统一的。 - Shetty
在这种情况下,您可以从服务器以UTC格式获取时间数据。然后,根据需要使用DateTime.ToLocalTime或DateTime.ToUniversalTime进行转换。如果您还包括日期,并且需要处理美国MM/dd/yyyy和欧洲dd/MM/yyyy格式,则可以使用CultureInfo类相应地解析DateTime值。这似乎比您目前所拥有的更多工作,但这意味着如果您再次移动服务器,则无需重新编码DateTime处理。 - ChrisBD

0

牛仔方法是获取UTC时间,从中减去四小时的秒数(时区偏移量),使用UTC格式化函数进行格式化,并在其上贴上“EDT”标签。

如果您需要有时使用夏令时,有时使用标准时间,则可以创建一个切换日期的查找表,或使用某些日历功能。


0

TimeZoneInfo.ConvertTimeFromUtc将根据您提供的DateTime具有正确的偏移量。例如:

3AM UTC/11PM ET(4小时偏移):

DateTime timeSummerET = TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime("08/01/2019 03:00:00"), zoneET);

UTC时间凌晨3点/美东时间晚上10点(相差5个小时):

DateTime timeWinterET = TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime("12/01/2019 03:00:00"), zoneET);

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