c# TimeZoneInfo.FindSystemTimeZoneById在Linux上运行时返回错误的adjustm



当使用有效的Windows时区在Windows上运行以下代码时,它返回带有1 AdjustmentRule的正确TimeZoneInfo:

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

然而,当在Linux容器中运行时,将时区名称转换为正确的IANA等效名称后,返回的TimeZoneInfo有154个重叠的adjustmenrules:

var ianaTimezone = TZConvert.WindowsToIana("Central Europe Standard Time"); // returns 'Europe/Budapest'
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(ianaTimezone);

这导致System.InvalidTimeZoneException: The elements of the AdjustmentRule array must be in chronological order and must not overlap.在尝试对TimeZoneInfo做任何事情之后。

我迷失了如何解决这个问题,因为我在寻找解决方案时找不到任何类似的东西。

任何帮助将非常感激!

升级到。net 6并没有解决这个问题。最后,我只是诉诸于发送时区名称并生成一个新的TimeZoneInfo,而不是在发送之前序列化TimeZoneInfo,并在收到消息后反序列化。

不是一个理想的解决方案,但对我的情况有效!

仅供参考,时区不是由。net直接处理的。. net运行时只是从主机操作系统请求时区信息,这就是这个错误的来源。

时区逻辑实际上是操作系统的一部分,因此TimeZoneInfo . net组件只是查询操作系统上可用的时区。如果操作系统找不到您要的时区,TimeZoneInfo类将弹出您上面概述的InvalidTimeZoneException

当涉及到Linux,特别是Linux Docker容器时,标准时区有点用词不当。不同版本的Linux在可用时区方面通常存在很大差异。

如果您在Linux容器上运行,大多数较小的容器发行版不包含任何时区信息,除了标准的"Etc/utc"。因此,当有人调用获取TimeZoneInfo的给定Id(从上面的字符串),因为操作系统没有这个时区的概念,它告诉TimeZoneInfo所以,因此你的异常。

不过,你也不是没运气。

你可以在你的发行版上安装tzdata包。tzdata是一个标准的时区集,它应该涵盖大多数时区映射场景。
下面是使用apt-get

安装tzdata的示例apt-get install -y --no-install-recommends tzdata

不可能确定是否会找到时区ID(您在上面发布的字符串"中欧标准时间"),因此我已经养成了在搜索时区时添加一些保护性逻辑的习惯,以便在找不到时区的情况下,我不会在我的应用程序中获得堆栈跟踪,而是以默认时区结束。总比没有好。

var timeZoneId = "Central Standard Time";
var finalTimeZone = TimeZoneInfo.Utc;
if (string.IsNullOrEmpty(timeZoneId))
return finalTimeZone;
try
{
finalTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
}
catch(InvalidTimeZoneException)
{
_logger.Warn("Timezone ID of '{timeZoneId}' not found");
finalTimeZone = TimeZoneInfo.Utc;
}
return finalTimeZone;

最新更新