首页 > 解决方案 > 如何在 Linux 环境下制作自己的夏令时表?

问题描述

我正在开发一个使用 buildroot 工具构建的 linux 嵌入式项目,并且我正在使用 mono 在 linux 系统上运行我的 .net 应用程序。有必要有一个自定义的夏令时表。用户将在我在 .net 中完成的 GUI 界面中手动插入接下来的几年时间段(夏令时开始和结束时间),如果政府更改这些时间段,则允许用户编辑这些时间段。我知道也许还有其他方法可以自动执行此操作,但就像我说的那样,必须有一个用户界面来手动设置或编辑它。

在我使用这个文件作为我的 zoneinfo 信息之前:

/usr/share/zoneinfo/America/Sao_Paulo

这个文件有圣保罗的夏令时,Linux 启动时会自动更改系统时钟,但我发现我无法编辑这个文件,所以它对我不起作用。所以我改为:

/usr/share/zoneinfo/等/GMT+3

这个文件有我的 zoneinfo 没有夏令时。我打算手动做。

我做了 GUI 界面,将自定义 DST 时段表保存在 mongodb 数据库中。我的想法是当我检测到当前时间在我的数据库中保存的任何时间段内时,将 linux 系统时钟设置为提前一小时。它也运行良好,但问题是当我的 NTP 服务同步和更新系统时钟时,又将其设置为一小时后。当然,我不能禁用 NTP 服务,我也需要这个。

我怎样才能实现这个功能?在 Linux 中执行此任务或在我在 linux 上运行的 .net 应用程序中执行此操作是否更好?

标签: c#linuxmonobuildroot

解决方案


您可以编写自己的 localtime() 替换,或使用 zic 工具

但是,首先:您可能不想这样做。引用@Panagiotis:

tz 数据库文件会定期更新并自动分发。事实上,它们是事实上的标准。

实际上,“定期更新”主要用于历史时区信息,因为时区根本不会经常更改。在 Buildroot 中,只需安装tzdata软件包,您就拥有了世界上所有的时区。

为了应用时区信息,您总是希望尽可能晚地这样做。系统时钟必须采用 UTC。文件的时间戳也应该是 UTC。现代系统记录器(例如 systemd-journald)也以 UTC 存储时间戳。通过网络通信的所有时间都应采用 UTC。只有当时间呈现给用户时,才需要将其转换为本地时间(对于不同的用户可能不同)。

要解决自定义时区的问题,最简单的方法是不使用正常的 localtime() (或任何 .NET 等效项),而是使用包装函数首先检查当前时区是否是自定义时区之一,然后执行在这种情况下,您自己的时区计算。

或者,您可以生成一个时区文件并将其写入文件系统。tzfile格式是二进制格式,因此生成文本文件并使用zic 工具转换可能更容易。在 Buildroot 中,zic 工具当前不可用于目标,因此您需要更新package/zic/zic.mk并添加package/zic/Config.in. 您可以查看 Buildroot 如何tzdatapackage/tzdata/tzdata.mk.

如果您确实需要在系统范围内配置时区(您通常不需要这样做),则必须创建指向自定义时区的符号链接/etc/localtime并将其设置为/etc/timezone. 当然,您必须确保自定义时区文件是可写的。我建议给您的时区提供非标准名称,例如以 Custom/ 开头,并创建/usr/share/zoneinfo/Custom指向可写目录的符号链接。


推荐阅读