Solved (Sorta): My Mac Thinks its in UTC Timezone

I was working on a project and was trying to convert an ISO-8601 timestamp string from my server into localtime for display. Most libraries should handle that automatically, since the js Date object is pretty much always in local time. But it kept showing me a time that was off by a few hours.

Eventually I figured out that certain systems in my environment were using UTC time, even though I live in Kansas City and it should be using America/Chicago.

Check that out: even though system preferences are set to America/Chicago, the terminal date command is still reporting a UTC time. Opening node and running new Date() also shows a UTC time. The javascript Date issue reproduced in both firefox and safari.

Searching the internet, this seems to happen to other people sometimes. I haven’t found a definitive fix, but here’s what I learned.

Many system tools consult /etc/localtime to determine the timezone. This file is a symlink to the actual timezone database.

$ ls -l /etc/localtime
lrwxr-xr-x  1 root  wheel  41 Mar 29 17:07 /etc/localtime -> /var/db/timezone/zoneinfo/America/Chicago

However, running the file command on /etc/localtime said it was a broken symlink.

Indeed, many of the American cities are missing from /var/db/timezone/zoneinfo:

$ ls /var/db/timezone/zoneinfo/America
Adak          Cordoba       Guadeloupe    Menominee     Sitka
Anchorage     Costa_Rica    Hermosillo    Mexico_City   St_Johns
Anguilla      Curacao       Indiana       Miquelon      St_Kitts
Araguaina     Danmarkshavn  Iqaluit       Montevideo    Swift_Current
Argentina     Dawson_Creek  Juneau        Montserrat    Thule
Aruba         Ensenada      Kentucky      Nome          Thunder_Bay
Asuncion      Fort_Nelson   Louisville    North_Dakota  Tijuana
Atka          Glace_Bay     Maceio        Ojinaga       Toronto
Barbados      Godthab       Marigot       Panama        Virgin
Cambridge_Bay Grand_Turk    Martinique    Pangnirtung   Winnipeg
Caracas       Grenada       Mendoza       Shiprock

Notice there is no Chicago, New York, Los Angeles, etc.

I noticed that many of the entries in /var/db/timezone are in turn more symlinks to the versioned timezone database, in this case 2024a.1.0.

➜  db/timezone
$ ls -l
total 0
lrwxr-xr-x  1 root  wheel  35 Apr  6 00:19 icutz -> /var/db/timezone/tz/2024a.1.0/icutz
drwxr-xr-x  3 root  wheel  96 Mar 16 22:21 tz
lrwxr-xr-x  1 root  wheel  29 Feb 21 03:46 tz_latest -> /var/db/timezone/tz/2024a.1.0
lrwxr-xr-x  1 root  wheel  38 Apr  6 00:19 zoneinfo -> /var/db/timezone/tz/2024a.1.0/zoneinfo

I have another macbook from my employer, which reports the correct time. It does contain the expected database files for America/Chicago and is on the same tz database, 2024a.1.0. I’m not sure what happened to break it for my personal machine.

Both machines are Sonoma 14.4.1.

One random forum user fixed this issue by backing up the timezone database from a working mac and restoring it, but you have to turn off system integrity protection to do that. I didn’t want to try all that unless I really had to.

Luckily, I found that /var/db/timezone/zoneinfo/US/Central does exist. US/Central and America/Chicago are aliases in the timezone database: they are equivalent.

So in my case, I just changed the etc/localtime symlink to point to US/Central instead of America/Chicago:

$ sudo ln -s /var/db/timezone/zoneinfo/US/Central /etc/localtime

And now my date commands and javascript are correctly reporting the CDT timezone

date
Thu Apr 11 08:46:10 CDT 2024

node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> new Date()
2024-04-11T13:46:37.247Z
> new Date().getTimezoneOffset()
300