Time Zones, tz Database, and Linux

alias now='date --iso-8601=seconds'
alias utc='date -u +"%Y-%m-%dT%H:%M:%S"'
$ now
2022-06-26T18:40:30+03:00
$ utc
2022-06-26T16:40:39

Time zones

I probably don’t need to explain what time zones are (a Wiki page does it better). I want to focus a bit on other aspects.

Time zones and Linux

I touched on the fact that I needed to change my time zone, how can it be done in Linux?

$ pacman -Qs tzdata
local/tzdata 2022a-1
Sources for time zone and daylight saving time data
$ sudo ln -sf /usr/share/zoneinfo/Europe/vilnius /etc/localtime
#!/usr/bin/env bashLOCALTIME_PATH=/etc/localtime
ZONEINFO_PATH=/usr/share/zoneinfo
get_timezone() {
realpath $LOCALTIME_PATH | rev | cut -d'/' -f1,2 | rev
}
get_timezones() {
local region="$1"
find $ZONEINFO_PATH/$region/* | rev | cut -d'/' -f1,2 | rev
}
get_regions() {
find $ZONEINFO_PATH/ -maxdepth 1 -type d | rev | cut -d'/' -f1,2 | rev | sed 's/zoneinfo\///;/^[[:space:]]*$/d'
}
set_timezone() {
local new_timezone_path="$1"
ln -sf "$ZONEINFO_PATH/$new_timezone_path" $LOCALTIME_PATH
}
print_help() {
cat<<END
timezone [OPTIONS]
OPTIONS:
-a <region> get all timezone in a region, e.g. Europe
-c get current timezone
-s <timezone> new timezone, e.g. Europe/Tallinn
-r get all regions
-h print this help
END
}
while getopts "cs:ha:r" opt; do
case $opt in
a) get_timezones "$OPTARG" ;;
c) get_timezone ;;
h) print_help ;;
s) set_timezone "$OPTARG" ;;
r) get_regions ;;
*) print_help ;;
esac
done
[ -z "$1" ] && print_helpexit 0
$ zdump -v Europe/Brussels | head -10
Europe/Brussels -9223372036854775808 (gmtime failed) = -9223372036854775808 (localtime failed)
Europe/Brussels -67768040609741851 (gmtime failed) = -67768040609741851 (localtime failed)
Europe/Brussels -67768040609741850 (gmtime failed) = Thu Jan 1 00:00:00 -2147481748 LMT isdst=0 gmtoff=1050
Europe/Brussels -67768040609740801 (gmtime failed) = Thu Jan 1 00:17:29 -2147481748 LMT isdst=0 gmtoff=1050
Europe/Brussels Thu Jan 1 00:00:00 -2147481748 UT = Thu Jan 1 00:17:30 -2147481748 LMT isdst=0 gmtoff=1050
Europe/Brussels Wed Dec 31 23:42:29 1879 UT = Wed Dec 31 23:59:59 1879 LMT isdst=0 gmtoff=1050
Europe/Brussels Wed Dec 31 23:42:30 1879 UT = Thu Jan 1 00:00:00 1880 BMT isdst=0 gmtoff=1050
Europe/Brussels Sat Apr 30 23:59:59 1892 UT = Sun May 1 00:17:29 1892 BMT isdst=0 gmtoff=1050
Europe/Brussels Sun May 1 00:00:00 1892 UT = Sun May 1 00:00:00 1892 WET isdst=0 gmtoff=0
Europe/Brussels Sat Nov 7 23:59:59 1914 UT = Sat Nov 7 23:59:59 1914 WET isdst=0 gmtoff=0

tz database

However, let’s have a look at iana’s tz database. There’s also a GitHub repository:

$ git clone https://github.com/eggert/tz
$ cd tz/
$ git grep -n Vilnius
NEWS:2150: Europe/Kaliningrad and Europe/Vilnius changed from +03/+04 to
europe:1918:# (Europe/Vilnius) was changed.
europe:1943:Zone Europe/Vilnius 1:41:16 - LMT 1880
tzfile.h:110:/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
zone.tab:256:LT +5441+02519 Europe/Vilnius
zone1970.tab:213:LT +5441+02519 Europe/Vilnius
# Zone NAME  STDOFF RULES FORMAT [UNTIL]
Zone Europe/Vilnius 1:41:16 - LMT 1880
1:24:00 - WMT 1917 # Warsaw Mean Time
1:35:36 - KMT 1919 Oct 10 # Kaunas Mean Time
1:00 - CET 1920 Jul 12
2:00 - EET 1920 Oct 9
1:00 - CET 1940 Aug 3
3:00 - MSK 1941 Jun 24
1:00 C-Eur CE%sT 1944 Aug
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 Russia EE%sT 1991 Sep 29 2:00s
2:00 C-Eur EE%sT 1998
2:00 - EET 1998 Mar 29 1:00u
1:00 EU CE%sT 1999 Oct 31 1:00u
2:00 - EET 2003 Jan 1
2:00 EU EE%sT
  • it belongs to Europe/Vilnius time zone
  • they are +2 hours from UTC
  • it refers to EU rule record
  • the time is called EET or EE*T where the star is a character or characters from LETTER/S column from the rule record for EU
$ grep -P -B1 '^Rule[[:space:]]EU' europe 
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S
Rule EU 1977 only - Sep lastSun 1:00u 0 -
Rule EU 1978 only - Oct 1 1:00u 0 -
Rule EU 1979 1995 - Sep lastSun 1:00u 0 -
Rule EU 1981 max - Mar lastSun 1:00u 1:00 S
Rule EU 1996 max - Oct lastSun 1:00u 0 -
  • the summer time rule was applied in 1981
  • the change to the summer time (applying daylight saving time) happens on the last Sunday in March at 1a.m. UTC, the clock should be ahead by 1 hour at this time; in case of Vilnius it means that when the wall clock is 3a.m., the time should be ahead by 1 hour, so it makes 4a.m., that means that Vilnius is UTC+03:00 when EEST is applied
  • the rule for the time change back from the summer time was changed in 1996 for the last time; the time used to change on the last Sunday in September (between 1979 and 1995) but now changes on the last Sunday in October; and again, at 1a.m. UTC, the wall clock should be 0 hour ahead, so in case of Vilnius, when the wall clock shows 4a.m., the time goes back to 3a.m.

Privacy considerations

Lastly, reading your device time zone is fairly easy. It can locate you at a certain geographical area. That can even be as specific as one country if your time zone is something like UTC+05:45 :)

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store