使用时区城市坐标和本地时间进行时区转换

3
我正在开发一个调度网站,您可以在其中指定日期、时间和时区城市。我希望将其保存在后端的UTC时间中。因此,我必须在服务器上进行某种转换。我还想提供实时转换到不同时区的功能。
在Javascript中,我有一个日期/时间值以及一个时区城市(来自http://www.citytimezones.info,它给了我地理坐标)。我没有UTC时间,只有指定时区的时间。
现在,我需要将这个未来的本地时间转换为UTC时间。当然,它必须考虑到那个时间应用的夏令时偏移量。
此外,我想使用第二个时区城市将其转换为不同的本地时间。
我考虑使用Google Maps时区API,但这会强制您传递UTC时间,而我没有,因为我正在尝试计算它。
换句话说,理想情况下,我需要一个系统,它将采用以下参数:
  • 未来时间/日期
  • 源时区城市坐标
  • 目标时区城市坐标(或null = UTC时间)

并且将返回转换后的时间。

有什么建议可以让这个实现呢?

这可以是一个网络服务或Windows C#库。


如果时区规则在未来发生变化,那么您未来的UTC时间可能会变得不正确。而且时区规则经常会意外更改。显然,这个问题适用于所有多时区调度应用程序,我认为唯一的解决方案是存储原始本地时间,以便在适用的时区规则未来发生变化时重新计算UTC时间。 - Martin Liversage
@MartinLiversage 是的,我计划存储它。调度还保存本地时间,以便我们可以重新计算UTC时间。 - Emmanuel
我不知道为什么这个问题被标记为“DateTime vs DateTimeOffset”的重复。这太荒谬了,因为那个问题甚至没有涉及到时区之间的转换。最多可能是“Google Maps时区API vs DateTimeOffset”,但这也是牵强附会。 - Emmanuel
最终的解决方案是,正如+Matt Johnson所删除的答案所描述的那样,类DateTimeOffset提供了我所寻找的时区转换功能。话虽如此,我无法将其恢复或投票支持,因为它已被删除。这让我有点沮丧,因为我无法为自己的问题编写一个合适的答案。 - Emmanuel
2个回答

1

将问题分为两个部分:

  • 从位置坐标确定时区
  • 在不同时区之间转换时间

您会发现有几种方法可以完成每个步骤。

对于第一步,您提到了Google时区API和CityTimeZones。这两个在此处列出,以及其他几种方法。

对于第二步,您在.NET中的选择主要是Noda TimeTimeZoneInfo。Martin在他的答案中给出了几个很好的例子。

此外,请考虑“调度”是比大多数情况更困难的场景。有关更多详细信息,请阅读此帖子


1
您需要一个时区数据库才能执行所需的日期和时间转换。时区比仅仅是一个偏移量更加复杂,因为许多时区包括夏令时规则。
.NET框架允许您使用底层的Windows时区数据库,通过使用TimeZoneInfo类。然而,您可以考虑Windows时区数据库是专有的。IANA维护时区数据库(TZDB),该数据库在最佳当前实践(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);

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