2

I'm working on a linux embedded project built with buildroot tool and I'm using mono to run my .net application on linux system. It's necessary to have a custom table of daylight saving time periods. The user will insert manually the next few years periods(when daylight saving time starts and when it ends) in a GUI interface that I have done in .net, and the user is allowed to edit those periods if they change by the government. I know maybe there are other way to do that automatically, but like I said, it's necessary to have an user interface to set or edit it manually.

Before I was using this file as my zoneinfo information:

/usr/share/zoneinfo/America/Sao_Paulo

This file has the daylight saving time periods of São Paulo and Linux changes the system clock automatically when it starts, but I found out I can't edit this file, so it doesn't work for me. So I changed to:

/usr/share/zoneinfo/Etc/GMT+3

This file has my zoneinfo without daylight saving time periods. I'm planning to do it manually.

I did the GUI interface which saves the table of custom DST periods in mongodb database. My idea was to set the linux system clock one hour a head when I detect the current time is within of any period saved in my database. It also was working very well but the problem is when my NTP service synchronizes and updates the system clock, setting it to one hour behind back again. And of course, I can't disable the NTP service, I need this as well.

How can I implement this feature ? Is it better implementing this in Linux to do this task or in my .net application running on linux ?

  • 1
    Why not import the data from the zoneinfo files? – ProgrammingLlama May 29 '18 at 11:57
  • 1
    Why do that at all? The [tz database](https://en.wikipedia.org/wiki/Tz_database) files are updated regularly and distributed automatically. In fact they *are* the defacto standard. Whatever the end user enters probably comes *from* a copy of those files – Panagiotis Kanavos May 29 '18 at 12:00
  • See following posting. Unix date one is 1/1/1970 while net is 1/1/1 : https://stackoverflow.com/questions/249760/how-can-i-convert-a-unix-timestamp-to-datetime-and-vice-versa – jdweng May 29 '18 at 12:01
  • If you have an issue either fix your NTP configuration or *update* the tzdata files. Don't try to cover up the problem – Panagiotis Kanavos May 29 '18 at 12:02
  • I can import the data from the zoneinfo file through "localZone.GetDaylightChanges(currentYear)" .NET method. But I think I can't edit and save it dynamically. Can I ? – Guilherme Ramalho May 29 '18 at 12:03
  • Why do that at all? It's automatically updated by a `sudo apt-get upgrade`. The end users will find out about changes *after* the people that administer the tz database. – Panagiotis Kanavos May 29 '18 at 12:08
  • If you don't intend to update regularly, you can use a library that can work with your own tzdatabase files, like NodaTime. – Panagiotis Kanavos May 29 '18 at 12:10
  • I agree with you @PanagiotisKanavos, but this user enters table is mandatory for this project. – Guilherme Ramalho May 29 '18 at 12:10

1 Answers1

1

You can either write your own replacement of localtime(), or use the zic tool.

First of all, however: you probably don't want to do this. Quoting @Panagiotis:

The tz database files are updated regularly and distributed automatically. In fact they are the defacto standard.

In fact, the "regularly updated" is mostly for historical timezone information, because timezones simply don't change that often. In Buildroot, simply install the tzdata package and you have all the timezones in the world.

For applying the timezone information, you always want to do that as late as possible. The system clock must be in UTC. Timestamps on files should be in UTC as well. Modern system loggers (e.g. systemd-journald) also store timestamps in UTC. All times communicated over the network should be in UTC. Only when a time is presented to the user it is necessary to convert it to local time (which may be different for different users).

To solve your problem with custom timezones, the easiest is to not use the normal localtime() (or whatever the .NET equivalent is) but instead use a wrapper function that first checks if the current timezone is one of the custom timezones, and do your own timezone calculations in that case.

Alternatively, you can generate a timezone file and write it to the filesystem. The tzfile format is a binary format, so probably it is easier to generate a text file and convert it with the zic tool. In Buildroot, the zic tool is not currently available for the target, so you'll need to update package/zic/zic.mk and add package/zic/Config.in. You can look at how Buildroot generates the timezone files from the tzdata rules file in package/tzdata/tzdata.mk.

If you really need the timezone to be configured system-wide (which you typically don't need to do), you have to create a symlink to the custom timezone from /etc/localtime and set it in /etc/timezone. And of course, you have to make sure that the custom timezone file is writable. I would advice to give your timezones non-standard names, e.g. starting with Custom/, and make /usr/share/zoneinfo/Custom a symlink to a writable directory.

Arnout
  • 2,927
  • 16
  • 24