On 2024-06-06 17:03, Bruno Haible wrote:
Paul Eggert wrote:
tzname is used in three places:
    - time_rz,

This should be fixed to use strftime instead.

This seems wrong for two reasons:

   * time_rz is a small module, without textual I/O.

Fair enough, and the changes I recently installed into Gnulib solved this problem in a different way, which make time_rz even smaller. As you suggested, the updated time_rz does not use strftime.


   * It is bad design to require calling a complicated function
     in order to get elementary data about something.

True, but unfortunately strftime %Z is the only widely supported and portable way to get the time zone abbreviation.

In the long run I suppose we can assume struct tm's tm_zone instead. But this is standardized only in POSIX.1-2024, and for many years apps will need to deal with less-capable systems, notably Microsoft Windows.

We could create a new module to get a time zone abbreviation. It could define a new function that is given BUF, SIZE, TM and TZ and would be the equivalent of strftime (BUF, SIZE, "%Z", TM) in the timezone TZ, and tuned for the common case where TM->tm_zone exists. Offhand I know of only one program that could use this function: GNU Emacs (which currently just does strftime and doesn't bother tuning for tm_zone), but if there are others then such a module might be worth writing.

Regardless of whether we add such a module, though, we should remove the tzname module from Gnulib, as Gnulib doesn't need it any more and nobody should use it. Proposed patch attached.


> >    - parse-datetime,
> > Likewise. (This usage of tzname is simply wrong, by the way, but it can > be compatibly wrong.)

That would require two (!) strftime calls, one to get the time zone
without DST abbrev, and one to get the time zone with DST abbrev. This is
gross.

Although strftime may be gross it's more portable than tzname, and more reliable than tzname even on platforms that have tzname.

Also, parse-datetime.y is not a good argument for the utility of tzname as it has an incorrect model for how time zone abbreviations work. It ignores the recommendation in <https://data.iana.org/time-zones/tz-link.html#notation> that says, "Alphabetic time zone abbreviations should not be used as unique identifiers for UT offsets as they are ambiguous in practice." And it doesn't even ignore the recommendation correctly, as it wrongly assumes that there are at most two time zone abbreviations for any particular time zone setting. We shouldn't rely on parse-datetime.y for insight as to what primitives Gnulib should be supporting in this area.
From 668e8c9f0ea08a273797507f29179de419f155f3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sun, 16 Jun 2024 16:34:03 -0700
Subject: [PATCH] tzname: remove module

This recently-introduced module was used only internally by Gnulib,
and as all uses have been removed the module can be removed.
As discussed in the Gnulib manual, tzname is problematic
and GNU programs should generally avoid it.
* MODULES.html.sh, NEWS, doc/posix-functions/tzname.texi:
Adjust to module removal.
* lib/time.in.h tzname [@GNULIB_TZNAME@ && NEED_DECL_TZNAME]:
Remove decl and macro.
* m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Remove GNULIB_TZNAME.
* m4/tzname.m4, modules/tzname, modules/tzname-tests:
* tests/test-tzname.c: Remove.
* modules/time-h (time.h): Do not substitute GNULIB_TZNAME.
---
 ChangeLog                       | 14 ++++++++
 MODULES.html.sh                 |  1 -
 NEWS                            |  3 ++
 doc/posix-functions/tzname.texi |  9 ++---
 lib/time.in.h                   | 17 ---------
 m4/time_h.m4                    |  3 +-
 m4/tzname.m4                    | 62 ---------------------------------
 modules/time-h                  |  1 -
 modules/tzname                  | 23 ------------
 modules/tzname-tests            | 11 ------
 tests/test-tzname.c             | 36 -------------------
 11 files changed, 23 insertions(+), 157 deletions(-)
 delete mode 100644 m4/tzname.m4
 delete mode 100644 modules/tzname
 delete mode 100644 modules/tzname-tests
 delete mode 100644 tests/test-tzname.c

diff --git a/ChangeLog b/ChangeLog
index 52c07bde4f..6907435460 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2024-06-16  Paul Eggert  <egg...@cs.ucla.edu>
 
+	tzname: remove module
+	This recently-introduced module was used only internally by Gnulib,
+	and as all uses have been removed the module can be removed.
+	As discussed in the Gnulib manual, tzname is problematic
+	and GNU programs should generally avoid it.
+	* MODULES.html.sh, NEWS, doc/posix-functions/tzname.texi:
+	Adjust to module removal.
+	* lib/time.in.h tzname [@GNULIB_TZNAME@ && NEED_DECL_TZNAME]:
+	Remove decl and macro.
+	* m4/time_h.m4 (gl_TIME_H_REQUIRE_DEFAULTS): Remove GNULIB_TZNAME.
+	* m4/tzname.m4, modules/tzname, modules/tzname-tests:
+	* tests/test-tzname.c: Remove.
+	* modules/time-h (time.h): Do not substitute GNULIB_TZNAME.
+
 	nstrftime: omit never-used code
 	* lib/strftime.c (__strftime_internal): Remove code protected by
 	‘#ifndef my_strftime’.  my_strftime is always defined.  This
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 4df6497fc3..7575228c4c 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1264,7 +1264,6 @@ tsearch
 ttyname
 ttyname_r
 twalk
-tzname
 tzset
 ulimit
 umask
diff --git a/NEWS b/NEWS
index 57540c8375..0e172c0b43 100644
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,9 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2024-06-16  tzname          This recently-introduced module is removed.
+                            It's problematic and no longer needed in Gnulib.
+
 2024-05-16  putenv          This module is renamed to 'putenv-gnu'.
 
 2024-02-21  *printf-posix   These modules no longer support the 'n' directive
diff --git a/doc/posix-functions/tzname.texi b/doc/posix-functions/tzname.texi
index dbc98c0751..4adc9ce04e 100644
--- a/doc/posix-functions/tzname.texi
+++ b/doc/posix-functions/tzname.texi
@@ -4,18 +4,19 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/tzname.html}
 
-Gnulib module: tzname
+Gnulib module: ---
 
 Portability problems fixed by Gnulib:
 @itemize
-@item
-This variable is called @code{_tzname} on some platforms:
-mingw with @code{-DNO_OLDNAMES}, MSVC.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+This variable is called @code{_tzname} on some platforms:
+mingw with @code{-DNO_OLDNAMES}, MSVC.
+@item
+@item
 This variable's contents are unreliable if you use a geographical
 @env{TZ} setting like @code{TZ="America/Los_Angeles"}.
 @item
diff --git a/lib/time.in.h b/lib/time.in.h
index b91018937a..df99c8abca 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -122,23 +122,6 @@ struct __time_t_must_be_integral {
 #  endif
 # endif
 
-# if @GNULIB_TZNAME@
-/* tzname[0..1]: Abbreviated time zone names, set by the tzset() function.  */
-#  if NEED_DECL_TZNAME
-extern
-#   ifdef __cplusplus
-  "C"
-#   endif
-  char *tzname[];
-#  endif
-#  if defined _WIN32 && !defined __CYGWIN__
-/* On native Windows, map 'tzname' to '_tzname' etc., so that -loldnames is not
-   required.  */
-#   undef tzname
-#   define tzname _tzname
-#  endif
-# endif
-
 /* Set *TS to the current time, and return BASE.
    Upon failure, return 0.  */
 # if @GNULIB_TIMESPEC_GET@
diff --git a/m4/time_h.m4 b/m4/time_h.m4
index 4ca7305792..678a30a5ce 100644
--- a/m4/time_h.m4
+++ b/m4/time_h.m4
@@ -1,5 +1,5 @@
 # time_h.m4
-# serial 26
+# serial 27
 dnl Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -145,7 +145,6 @@ AC_DEFUN([gl_TIME_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMESPEC_GETRES])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_R])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_RZ])
-    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZNAME])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZSET])
     dnl Support Microsoft deprecated alias function names by default.
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_TZSET], [1])
diff --git a/m4/tzname.m4 b/m4/tzname.m4
deleted file mode 100644
index b600e56d01..0000000000
--- a/m4/tzname.m4
+++ /dev/null
@@ -1,62 +0,0 @@
-# tzname.m4
-# serial 1
-dnl Copyright (C) 2024 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl gl_TZNAME tests how the time zone can be obtained.
-dnl It is similar AC_STRUCT_TIMEZONE, but also supports MSVC.
-dnl It defines
-dnl   * the C macro HAVE_STRUCT_TM_TM_ZONE to 1 if 'struct tm' has a field
-dnl     'tm_zone',
-dnl   * otherwise:
-dnl     - the C macro HAVE_TZNAME_ARRAY to 1 if there the rvalue 'tzname'
-dnl       or (on native Windows) '_tzname' is usable,
-dnl     - the C macro NEED_DECL_TZNAME to 1 if 'tzname' needs to be declared
-dnl         extern char *tzname[];
-dnl       before use.
-AC_DEFUN([gl_TZNAME],
-[
-  AC_REQUIRE([AC_CANONICAL_HOST])
-
-  dnl Set ac_cv_member_struct_tm_tm_zone,
-  dnl     ac_cv_var_tzname, ac_cv_have_decl_tzname.
-  dnl Possibly define HAVE_STRUCT_TM_TM_ZONE,
-  dnl                 HAVE_TZNAME, HAVE_DECL_TZNAME.
-  AC_REQUIRE([AC_STRUCT_TIMEZONE])
-
-  dnl If 'struct tm' has a field 'tm_zone', don't test for tzname or _tzname.
-  dnl Rationale: Some code assumes that HAVE_STRUCT_TM_TM_ZONE and HAVE_TZNAME
-  dnl are exclusive.
-  if test "$ac_cv_member_struct_tm_tm_zone" != yes; then
-    if test $ac_cv_var_tzname = yes && test $ac_cv_have_decl_tzname != yes; then
-      AC_DEFINE([NEED_DECL_TZNAME], [1],
-        [Define to 1 if tzname exists but needs to be declared.])
-    fi
-    AC_CACHE_CHECK([for tzname array],
-      [gl_cv_var_tzname],
-      [AC_LINK_IFELSE(
-         [AC_LANG_PROGRAM(
-            [[#include <time.h>
-              #if NEED_DECL_TZNAME
-              extern char *tzname[];
-              #endif
-              #if defined _WIN32 && !defined __CYGWIN__
-               #undef tzname
-               #define tzname _tzname
-              #endif
-            ]],
-            [[return tzname[0][0];
-            ]])
-         ],
-         [gl_cv_var_tzname=yes],
-         [gl_cv_var_tzname=no])
-      ])
-    if test $gl_cv_var_tzname = yes; then
-      AC_DEFINE([HAVE_TZNAME_ARRAY], [1],
-                [Define to 1 if 'struct tm' does not have a field 'tm_zone'
-                 but instead 'tzname' is usable.])
-    fi
-  fi
-])
diff --git a/modules/time-h b/modules/time-h
index e84100bf93..3b07845b56 100644
--- a/modules/time-h
+++ b/modules/time-h
@@ -44,7 +44,6 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's/@''GNULIB_TIMESPEC_GETRES''@/$(GNULIB_TIMESPEC_GETRES)/g' \
 	      -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
 	      -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
-	      -e 's/@''GNULIB_TZNAME''@/$(GNULIB_TZNAME)/g' \
 	      -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \
 	      -e 's/@''GNULIB_MDA_TZSET''@/$(GNULIB_MDA_TZSET)/g' \
 	      -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
diff --git a/modules/tzname b/modules/tzname
deleted file mode 100644
index 4195d74f8e..0000000000
--- a/modules/tzname
+++ /dev/null
@@ -1,23 +0,0 @@
-Description:
-tzname variable: abbreviated time zone names, set by the tzset() function.
-
-Files:
-m4/tzname.m4
-
-Depends-on:
-time-h
-
-configure.ac:
-gl_TZNAME
-gl_TIME_MODULE_INDICATOR([tzname])
-
-Makefile.am:
-
-Include:
-<time.h>
-
-License:
-LGPL
-
-Maintainer:
-all
diff --git a/modules/tzname-tests b/modules/tzname-tests
deleted file mode 100644
index b2c590eaff..0000000000
--- a/modules/tzname-tests
+++ /dev/null
@@ -1,11 +0,0 @@
-Files:
-tests/test-tzname.c
-
-Depends-on:
-tzset
-
-configure.ac:
-
-Makefile.am:
-TESTS += test-tzname
-check_PROGRAMS += test-tzname
diff --git a/tests/test-tzname.c b/tests/test-tzname.c
deleted file mode 100644
index 385d594cc3..0000000000
--- a/tests/test-tzname.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Test of tzname array.
-   Copyright (C) 2024 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* Written by Bruno Haible <br...@clisp.org>, 2024.  */
-
-#include <config.h>
-
-/* Specification.  */
-#include <time.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int
-main ()
-{
-  const char *tz = getenv ("TZ");
-  tzset ();
-  printf ("TZ=%s -> tzname[0]=\"%s\", tzname[1]=\"%s\"\n",
-          tz != NULL ? tz : "(null)",
-          tzname[0], tzname[1]);
-  return 0;
-}
-- 
2.43.0

Reply via email to