GNU date falls back to UTC0 when the timezone is invalid. I guess that
isn't too intuitive, see a twitter user who ran into this gotcha (and an
unhinged reply...) [1].

Perhaps it would be good for 'date --debug' to warning about this on
typical platforms using /usr/share/zoneinfo? Here is the output using an
example parse-datetime patch:

    $ TZ=invalid ./src/date --debug -d '2026'
    date: parsed number part: 20:26:00
    date: input timezone: TZ="invalid" environment value
    date: using specified time as starting value: '20:26:00'
    date: using current date as starting value: '(Y-M-D) 2026-08-09'
    date: starting date/time: '(Y-M-D) 2026-08-09 20:26:00'
    date: '(Y-M-D) 2026-08-09 20:26:00' = 1786307160 epoch-seconds
    date: timezone: TZ="invalid" environment value
    date: warning: TZ="invalid" is not a valid timezone. Falling back to 
Universal Time
    date: final: 1786307160.000000000 (epoch-seconds)
    date: final: (Y-M-D) 2026-08-09 20:26:00 (UTC)
    date: final: (Y-M-D) 2026-08-09 20:26:00 (UTC+00)
    date: output format: ‘%a %b %e %r %Z %Y’
    Sun Aug  9 08:26:00 PM invalid 2026

The message should probably be made shorter, but it is just a draft.
Here is the patch:

diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y
index 22894f3091..e7bd70d4bb 100644
--- a/lib/parse-datetime.y
+++ b/lib/parse-datetime.y
@@ -57,6 +57,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 
 #include "gettext.h"
 
@@ -2361,7 +2362,30 @@ parse_datetime_body (struct timespec *result, char const 
*p,
       else if (streq (tzstring, "UTC0"))
         dbg_fputs (_("timezone: Universal Time\n"));
       else
-        dbg_printf (_("timezone: TZ=\"%s\" environment value\n"), tzstring);
+        {
+          dbg_printf (_("timezone: TZ=\"%s\" environment value\n"), tzstring);
+          struct stat st;
+          char const zoneinfo[] = "/usr/share/zoneinfo/";
+          if (0 <= stat (zoneinfo, &st))
+            {
+              idx_t const tzstring_len = strlen (tzstring);
+              char *name = malloc (sizeof zoneinfo + tzstring_len);
+              if (name)
+                {
+                  memcpy (name, zoneinfo, sizeof zoneinfo - 1);
+                  memcpy (name + sizeof zoneinfo - 1, tzstring,
+                          tzstring_len + 1);
+                  if (stat (name, &st) < 0)
+                    {
+                      dbg_printf (_("warning: TZ=\"%s\" is not a valid "
+                                    "timezone. "
+                                    "Falling back to Universal Time\n"),
+                                  tzstring);
+                    }
+                  free (name);
+                }
+            }
+        }
 
       intmax_t sec = result->tv_sec;
       int nsec = result->tv_nsec;

Collin

[1] https://x.com/trentdotsol/status/2085037902614917230

Reply via email to