使用时区城市坐标和当地时间进行时区转换[重复]
Posted
技术标签:
【中文标题】使用时区城市坐标和当地时间进行时区转换[重复]【英文标题】:Time zone conversion using time zone city coordinates and local time [duplicate] 【发布时间】:2016-10-09 06:40:00 【问题描述】:我正在开发一个日程安排网站,您可以在其中指定日期、时间、时区城市。我想在 UTC 时间将其保存在后端。所以我必须在服务器上以某种方式转换它。我还想提供即时转换到不同时区的能力。
在 javascript 中,我有一个日期/时间值以及一个时区城市(来自http://www.citytimezones.info,它给了我地理坐标)。我没有UTC时间,只有指定时区的时间。
现在我需要将这个未来的本地时间转换为 UTC。当然,它必须考虑到那时将应用的夏令时偏移量。
此外,我想使用第二个时区城市转换为不同的当地时间。
我曾考虑使用 Google Maps Time Zone API,但这会迫使您输入 UTC 时间,而我没有,因为我正在尝试计算它。
换句话说,理想情况下,我需要一个可以采用这些参数的系统:
未来时间/日期 源时区城市坐标 目标时区城市坐标(或 null = UTC 时间)并将返回转换后的时间。
知道我能做些什么来实现这一点吗?
这可以是 Web 服务或 Windows C# 库。
【问题讨论】:
如果将来时区规则发生变化,那么您未来的 UTC 时间可能会变得不正确。时区规则经常变化惊人。显然,这个问题适用于所有多时区调度应用程序,我认为唯一的解决方案是存储原始本地时间,以便在将来适用的时区规则发生变化时能够重新计算 UTC 时间。 @MartinLiversage 是的,我打算存储它。调度还保存了本地时间,因此我们可以重新计算 UTC 时间。 我不知道为什么这被标记为“DateTime vs DateTimeOffset”重复。这太荒谬了,因为其他问题甚至没有谈到时区之间的转换。充其量这可能是“Google Maps Time Zone API vs DateTimeOffset”,但这是在拉伸它。 最终解决方案是,正如 +Matt Johnson 删除的答案所述,DateTimeOffset 类提供了我正在寻找的时区转换功能。也就是说,我不能取消删除或投票支持这个答案,因为它已被删除。这让我有点沮丧,因为我无法为自己的问题写出正确的答案。 【参考方案1】:您需要一个时区数据库来执行所需的日期和时间转换。时区比简单的偏移更复杂,因为许多时区都包含夏令时规则。
.NET 框架允许您通过使用 TimeZoneInfo
类来使用底层的 Windows 时区数据库。但是,您可以认为 Windows 时区数据库是专有的。 IANA 维护Time Zone Database (TZDB),在Best Current Practice (BCP) 175 中进行了描述。
库 Noda Time 支持 TZDB,并提供了一个本地时间戳作为 .NET DateTime
和一个时区标识符,您可以计算相应的 UTC 时间戳:
var localDateTime = LocalDateTime.FromDateTime(dateTime);
var timeZoneId = "America/New_York"];
var timeZone = DateTimeZoneProviders.Tzdb[timeZoneId];
var zonedDateTime = timeZone.AtLeniently(localDateTime);
var utcDateTime = zonedDateTime.ToDateTimeUtc();
请注意,本地时间戳可能不明确或无效。这发生在夏令时转换期间,本地时钟向后移动(产生歧义)或向前移动(产生无效时间)。 AtLeniently
方法对如何处理歧义和无效时间戳做了一些假设。这可能是您的应用程序中的错误来源。
当您有 UTC 时间戳和时区 ID 时,您可以以类似的方式转换为本地时间:
var instant = Instant.FromDateTimeUtc(utcDateTime);
var timeZone = DateTimeZoneProviders.Tzdb[timeZoneId];
var zonedDateTime = instant.InZone(timeZone);
var localDateTime = zonedDateTime.ToDateTimeUnspecified();
查看http://www.citytimezones.info/ 后,cities.txt
似乎在最后一列中包含每个城市的 Windows 时区 ID。这使您可以根据城市查找 Windows 时区 ID。
然后您可以使用以下代码将本地 DateTime
转换为 UTC:
var timeZoneId = "Eastern Standard Time";
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
var utcDateTime = TimeZoneInfo.ConvertTimeToUtc(localDateTime, timeZoneInfo);
请注意,如果本地时间戳不明确或无效,ConvertTimeToUtc
将抛出 ArgumentException
。
UTC到本地时间的逆向转换:
var localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZoneInfo);
【讨论】:
【参考方案2】:把问题分成两部分:
根据位置坐标确定时区 在时区之间转换时间你会找到几种方法来做每一个。
对于第 1 步,您提到了 Google Time Zone API 和 CityTimeZones。这两个are listed here,以及其他几种方法。
对于第 2 步,您对 .NET 的选择主要在 Noda Time 或 TimeZoneInfo
之间。 Martin 为每个in his answer 举了几个很好的例子。
另外,考虑到 调度 是比大多数情况更困难的情况。您应该阅读this post 了解更多详情。
【讨论】:
以上是关于使用时区城市坐标和当地时间进行时区转换[重复]的主要内容,如果未能解决你的问题,请参考以下文章