使用时区城市坐标和当地时间进行时区转换[重复]

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 了解更多详情。

【讨论】:

以上是关于使用时区城市坐标和当地时间进行时区转换[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Postgres UTC时区vs当地时区

PostgreSQL中的时区转换不一致[重复]

如何在给定时间和状态信息的情况下获取当地时区

JSON.NET 将 +00:00 时区解析为当地时间,但 Z 解析为 UTC

c#时区转换

js将UTC时间转化为当地时区时间