How to check and update planned day light saving (DST) changes (timezone) in Linux

Daylight Saving Time happens in multiple countries across the globe and in many places the DST keeps changing every couple of years.

IMPORTANT NOTE: If your system is configured with online NTP pool servers then you need not worry about the leap seconds or DST changes as NTP server will take care of all these changes and will adjust your system clock accordingly.

Below article assumes that you don't have a NTP server and are dependent on locally installed timezone (tzdata) rpm.

How do I check the planned DST changes for a timezone?

You can get this information from (https://www.timeanddate.com) but you must make sure that your local system is also in sync with the DST changes as showed under (https://www.timeanddate.com)

For example I would like to see the planned DST changes for CET timezone.
From (https://www.timeanddate.com/time/change/germany/berlin) we get the below information

25 Mar 2018 - Daylight Saving Time Starts
When local standard time is about to reach
Sunday, 25 March 2018, 02:00:00 clocks are turned forward 1 hour to
Sunday, 25 March 2018, 03:00:00 local daylight time instead.

28 Oct 2018 - Daylight Saving Time Ends
When local daylight time is about to reach
Sunday, 28 October 2018, 03:00:00 clocks are turned backward 1 hour to
Sunday, 28 October 2018, 02:00:00 local standard time instead.

Lets match if with the DST changes available on my system

# zdump -v /usr/share/zoneinfo/CET | grep 2018
/usr/share/zoneinfo/CET  Sun Mar 25 00:59:59 2018 UTC = Sun Mar 25 01:59:59 2018 CET isdst=0 gmtoff=3600
/usr/share/zoneinfo/CET  Sun Mar 25 01:00:00 2018 UTC = Sun Mar 25 03:00:00 2018 CEST isdst=1 gmtoff=7200
/usr/share/zoneinfo/CET  Sun Oct 28 00:59:59 2018 UTC = Sun Oct 28 02:59:59 2018 CEST isdst=1 gmtoff=7200
/usr/share/zoneinfo/CET  Sun Oct 28 01:00:00 2018 UTC = Sun Oct 28 02:00:00 2018 CET isdst=0 gmtoff=3600

So we know that my local timeone rpm is capable enough to handle the DST changes.

With RHEL 7 with timedatectl also we can get this information on the planned DST changes

# timedatectl status
      Local time: Sun 2018-03-25 03:00:00 CEST
  Universal time: Sun 2018-03-25 01:00:00 UTC
        RTC time: Sun 2018-03-25 01:25:41
       Time zone: CET (CEST, +0200)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: yes
 Last DST change: DST began at
                  Sun 2018-03-25 01:59:59 CET
                  Sun 2018-03-25 03:00:00 CEST
 Next DST change: DST ends (the clock jumps one hour backwards) at
                  Sun 2018-10-28 02:59:59 CEST
                  Sun 2018-10-28 02:00:00 CET

But do we know it will really work?

Let us validate this by manually tweaking our local timezone and date

First change the local timezone to CET, the existing timezone as you see is 'Asia/Kolkata'

# ll /etc/localtime
lrwxrwxrwx. 1 root root 34 Jan 11 12:28 /etc/localtime -> ../usr/share/zoneinfo/Asia/Kolkata

Change it to CET

# ln -s ../usr/share/zoneinfo/CET /etc/localtime

# ll /etc/localtime
lrwxrwxrwx 1 root root 25 Jan 21 11:51 /etc/localtime -> ../usr/share/zoneinfo/CET

My current date and time

# date
Sun Jan 21 11:52:07 CET 2018

Lets change it to "Sun Mar 25 01:59:59 2018 CET" when we know the DST change should make the system clock shift one hour ahead

# date --set "25 Mar 2018 1:59:56 CET"
Sun Mar 25 01:59:56 CET 2018

On another terminal I have a while loop running to monitor the changing time

# while true;do echo -n checking DST changes with timezone ;date;sleep 1; done
checking DST changes with timezone Sun Mar 25 01:59:56 CET 2018
checking DST changes with timezone Sun Mar 25 01:59:57 CET 2018
checking DST changes with timezone Sun Mar 25 01:59:58 CET 2018
checking DST changes with timezone Sun Mar 25 01:59:59 CET 2018
checking DST changes with timezone Sun Mar 25 03:00:00 CEST 2018
checking DST changes with timezone Sun Mar 25 03:00:01 CEST 2018
checking DST changes with timezone Sun Mar 25 03:00:02 CEST 2018
checking DST changes with timezone Sun Mar 25 03:00:03 CEST 2018

If you notice the time changed from 01:59:59 to 03:00:00 because of the planned DST change

Next lets check the DST end changes which as per the timezone is scheduled at 28th oct 2018 when the time shifts back one hour

# date --set "28 Oct 2018 02:59:56 CEST"
Sun Oct 28 02:59:56 CEST 2018

Using our while loop

# while true;do echo -n "checking DST changes with timezone "; date;sleep 1; done
checking DST changes with timezone Sun Oct 28 02:59:56 CEST 2018
checking DST changes with timezone Sun Oct 28 02:59:57 CEST 2018
checking DST changes with timezone Sun Oct 28 02:59:58 CEST 2018
checking DST changes with timezone Sun Oct 28 02:59:59 CEST 2018
checking DST changes with timezone Sun Oct 28 02:00:00 CET 2018
checking DST changes with timezone Sun Oct 28 02:00:01 CET 2018
checking DST changes with timezone Sun Oct 28 02:00:02 CET 2018
checking DST changes with timezone Sun Oct 28 02:00:03 CET 2018

So the DST ended with expected timeshift from 02:59:59 to 02:00:00.

What should I do if the timezone (tzdata) rpm does not has planned DST changes?

Many times it can happen that the DST schedule changes without much prior notification, so in such situation you are very much dependent on NTP but what if you don't have NTP server?
In that case you have to make sure you have the latest timezone (tzdata) rpm which has the new changes for the specific timezone.

For Red Hat you can get the list of changes done for individual tzdata rpm under below page
https://access.redhat.com/articles/1187353

In case your vendor has not yet released a tzadata rpm file and you need a new fix then you can always download it from the main source of tz database

For latest available tzdata
https://www.iana.org/time-zones

If you want to access older tzdata archive
ftp://ftp.iana.org/tz/

For the sake of this article I will give an example from a recent scenario
In the year 2016 Turkey government announced not to have DST changes anymore so the old tzdata rpm was not aware of this change hence if not updated it will continue to shift the time as per the old planned DST changes

My existing tzdata rpm

# rpm -qa | grep tzdata
tzdata-2016a-1.el7.noarch

which is currently unaware that now for Turkey timezone there should be no more DST changes after the year 2016

# zdump -v /usr/share/zoneinfo/Turkey | grep 2017
/usr/share/zoneinfo/Turkey  Sun Mar 26 00:59:59 2017 UTC = Sun Mar 26 02:59:59 2017 EET isdst=0 gmtoff=7200
/usr/share/zoneinfo/Turkey  Sun Mar 26 01:00:00 2017 UTC = Sun Mar 26 04:00:00 2017 EEST isdst=1 gmtoff=10800
/usr/share/zoneinfo/Turkey  Sun Oct 29 00:59:59 2017 UTC = Sun Oct 29 03:59:59 2017 EEST isdst=1 gmtoff=10800
/usr/share/zoneinfo/Turkey  Sun Oct 29 01:00:00 2017 UTC = Sun Oct 29 03:00:00 2017 EET isdst=0 gmtoff=7200

As you see if I check the planned DST changes for the year 2017, it still shows me that the DST will start on '26th March' from 'EET' to 'EEST' and will end on '29th Oct' from 'EEST' to 'EET' again.

To fix this we need updated tzdata rpm with the necessary changes, this was updated in 2016g tzadata rpm so I downloaded the same from IANA database (ftp://ftp.iana.org/tz/)

and copied the same to my setup

# mkdir /tmp/tzdb
# cp /root/tzdata2016g.tar.gz /tmp/tzdb/
# tar -xzf tzdata2016g.tar.gz

next extract the needed timezone file here

In the NEWS file you should get the information regarding the Turkey time changes

    Turkey switched from EET/EEST (+02/+03) to permanent +03,
    effective 2016-09-07.  (Thanks to Burak AYDIN.)  Use "+03" rather
    than an invented abbreviation for the new time.

Lets extract the needed timezone file and place it on our system

# zic -d zoneinfo europe

This will create a directory zoneinfo and will extract all the timezone files under europe
Here we will have 'Istanbul' timezone which is same as Turkey, overwrite the existing Istanbul timezone with the new one

# cp ./zoneinfo/Asia/Istanbul /usr/share/zoneinfo/Asia/Istanbul
cp: overwrite â/usr/share/zoneinfo/Asia/Istanbulâ? y

If you observe I only modified Istanbul timezone but my 3 files are updated

# rpm -V tzdata
S.5....T.    /usr/share/zoneinfo/Asia/Istanbul
S.5....T.    /usr/share/zoneinfo/Europe/Istanbul
S.5....T.    /usr/share/zoneinfo/Turkey

So now lets see if this timezone has the updated information about the new time changes from Turkey government.

First lets check for the year 2017

# zdump -v /usr/share/zoneinfo/Asia/Istanbul | grep 2017
zdump: warning: zone "/usr/share/zoneinfo/Asia/Istanbul" abbreviation "+04" lacks alphabetic at start

As expected there are no planned DST changes in the year 2017 as Turkey government ended the DST in 2016 itself

For the year 2016 if you will compare the output from our last old tzdata rpm

# zdump -v /usr/share/zoneinfo/Asia/Istanbul | grep 2016
zdump: warning: zone "/usr/share/zoneinfo/Asia/Istanbul" abbreviation "+04" lacks alphabetic at start
/usr/share/zoneinfo/Asia/Istanbul  Sun Mar 27 00:59:59 2016 UTC = Sun Mar 27 02:59:59 2016 EET isdst=0 gmtoff=7200
/usr/share/zoneinfo/Asia/Istanbul  Sun Mar 27 01:00:00 2016 UTC = Sun Mar 27 04:00:00 2016 EEST isdst=1 gmtoff=10800
/usr/share/zoneinfo/Asia/Istanbul  Tue Sep  6 20:59:59 2016 UTC = Tue Sep  6 23:59:59 2016 EEST isdst=1 gmtoff=10800
/usr/share/zoneinfo/Asia/Istanbul  Tue Sep  6 21:00:00 2016 UTC = Wed Sep  7 00:00:00 2016 +03 isdst=0 gmtoff=10800

The DST will end on Sep 7 and the timezone will change from EEST to '+03' instead of 'EET'

IMPORTANT NOTE: The above will only update system level timezone, all the java applications follow their own timezone hence you have to make sure you update the tzdata of your JRE separately or else your java based alarms will continue to use old date and time.

 I will write an article shortly with the steps to update tzdata for JRE

I hope the article was useful.