Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] strftime: respect empty TZ
- X-seq: zsh-workers 54159
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Cc: "Bart Schaefer" <schaefer@xxxxxxxxxxxxxxxx>
- Subject: [PATCH] strftime: respect empty TZ
- Date: Tue, 20 Jan 2026 19:57:46 -0600
- Archived-at: <https://zsh.org/workers/54159>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
i recently noticed this with zsh/datetime's strftime:
% ( unset TZ; strftime '%a %F %T %z' 1234567890 )
Sat 2009-02-14 06:31:30 +0700
% ( unset TZ; TZ= strftime '%a %F %T %z' 1234567890 )
Sat 2009-02-14 06:31:30 +0700
what i expected:
% ( unset TZ; date -jf%s 1234567890 '+%a %F %T %z' )
Sat 2009-02-14 06:31:30 +0700
% ( unset TZ; TZ= date -jf%s 1234567890 '+%a %F %T %z' )
Fri 2009-02-13 23:31:30 +0000
this apparently isn't prescribed by posix but it's the documented
behaviour on most platforms. e.g. from glibc's tzset(3):
> If the TZ variable does appear in the environment, but its value is
> empty, ... then Coordinated Universal Time (UTC) is used.
was it a conscious choice not to pass through empty TZ? workers/34596
doesn't explicitly say
if not, is there any issue with changing it (whether now or after 5.10)?
attached patch does that + fixes a typo in the documentation
dana
diff --git a/Doc/Zsh/mod_datetime.yo b/Doc/Zsh/mod_datetime.yo
index 5475bd6cc..84f49086d 100644
--- a/Doc/Zsh/mod_datetime.yo
+++ b/Doc/Zsh/mod_datetime.yo
@@ -33,7 +33,7 @@ function tt(strptime); see manref(strptime)(3). This means that zsh
format extensions are not available, but for reverse lookup they are not
required.
-In most implementations of tt(strftime) any timezone in the
+In most implementations of tt(strptime) any timezone in the
var(timestring) is ignored and the local timezone declared by the tt(TZ)
environment variable is used; other parameters are set to zero if not
present.
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 085e4cc26..eb6b9e65f 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -190,7 +190,7 @@ bin_strftime(char *nam, char **argv, Options ops, int func)
char *tz = getsparam("TZ");
startparamscope();
- if (tz && *tz) {
+ if (tz) {
Param pm = createparam("TZ", PM_LOCAL|PM_SCALAR|PM_EXPORTED);
if (pm)
pm->level = locallevel; /* because createparam() doesn't */
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 622bdf6ed..0eae31687 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -134,3 +134,13 @@
strftime -n 'one line%n' 2> /dev/null
0:-n option
>one line
+
+# most platforms treat a set-but-empty TZ as UTC. however, it's not actually
+# required by POSIX, so we'll only test on systems we can be fairly sure about
+ if [[ $OSTYPE != (darwin|freebsd|netbsd|openbsd|linux-gnu)* ]]; then
+ ZTST_skip='unsure of empty-TZ behaviour'
+ else
+ ( unset TZ; TZ= strftime '%F %T' 1234567890 )
+ fi
+0:empty TZ respected
+>2009-02-13 23:31:30
Messages sorted by:
Reverse Date,
Date,
Thread,
Author