summaryrefslogtreecommitdiff
path: root/lib/mktime.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2017-04-30 16:34:54 +0200
committerBruno Haible <bruno@clisp.org>2017-04-30 19:26:38 +0200
commitdb1ee11e2168af7137db53289a92e306d2277b0b (patch)
tree2a232e2feff7c79640ba9bab203d58926b728b3e /lib/mktime.c
parent16778a29111e48e1f8f4afa07f77cfc3651c6040 (diff)
downloadgnulib-db1ee11e2168af7137db53289a92e306d2277b0b.tar.gz
mktime: Work around TZ problem on native Windows.
* lib/mktime.c: Add #ifs to make the algorithmic workaround independent from the native Windows workaround. * m4/mktime.m4 (gl_FUNC_MKTIME_WORKS): New macro, extracted from gl_FUNC_MKTIME. If guessing, set gl_cv_func_working_mktime to 'guessing no'. (gl_FUNC_MKTIME): Require it. Require AC_CANONICAL_HOST. Set REPLACE_MKTIME to 1 on native Windows. Define NEED_MKTIME_WORKING, NEED_MKTIME_WINDOWS. (gl_FUNC_MKTIME_INTERNAL): Require gl_FUNC_MKTIME_WORKS, not gl_FUNC_MKTIME. Set WANT_MKTIME_INTERNAL, not REPLACE_MKTIME. Define NEED_MKTIME_INTERNAL. * m4/timegm.m4 (gl_FUNC_TIMEGM): Require gl_FUNC_MKTIME_WORKS, not gl_FUNC_MKTIME. Cope with 'guessing yes' value. * modules/mktime-internal (configure.ac): Test WANT_MKTIME_INTERNAL, not REPLACE_MKTIME. * doc/posix-functions/mktime.texi: Mention the native Windows workaround.
Diffstat (limited to 'lib/mktime.c')
-rw-r--r--lib/mktime.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/mktime.c b/lib/mktime.c
index 2efd44a226..a78d960e53 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -23,6 +23,19 @@
# define DEBUG_MKTIME 0
#endif
+/* The following macros influence what gets defined when this file is compiled:
+
+ Macro/expression Which gnulib module This compilation unit
+ should define
+
+ NEED_MKTIME_WORKING mktime rpl_mktime
+ || NEED_MKTIME_WINDOWS
+
+ NEED_MKTIME_INTERNAL mktime-internal mktime_internal
+
+ DEBUG_MKTIME (defined manually) my_mktime, main
+ */
+
#if !defined _LIBC && !DEBUG_MKTIME
# include <config.h>
#endif
@@ -51,6 +64,13 @@
# define mktime my_mktime
#endif
+#if NEED_MKTIME_WINDOWS /* on native Windows */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#if NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME
+
/* A signed type that can represent an integer number of years
multiplied by three times the number of seconds in a year. It is
needed when converting a tm_year value times the number of seconds
@@ -458,25 +478,46 @@ __mktime_internal (struct tm *tp,
return t;
}
+#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME */
+
+#if NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME
+# if NEED_MKTIME_WORKING || DEBUG_MKTIME
static mktime_offset_t localtime_offset;
+# endif
/* Convert *TP to a time_t value. */
time_t
mktime (struct tm *tp)
{
-#ifdef _LIBC
+# if NEED_MKTIME_WINDOWS
+ /* If the environment variable TZ has been set by Cygwin, neutralize it.
+ The Microsoft CRT interprets TZ differently than Cygwin and produces
+ incorrect results if TZ has the syntax used by Cygwin. */
+ const char *tz = getenv ("TZ");
+ if (tz != NULL && strchr (tz, '/') != NULL)
+ _putenv ("TZ=");
+# endif
+
+# if NEED_MKTIME_WORKING || DEBUG_MKTIME
+# ifdef _LIBC
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
time zone names contained in the external variable 'tzname' shall
be set as if the tzset() function had been called. */
__tzset ();
-#elif HAVE_TZSET
+# elif HAVE_TZSET
tzset ();
-#endif
+# endif
return __mktime_internal (tp, __localtime_r, &localtime_offset);
+# else
+# undef mktime
+ return mktime (tp);
+# endif
}
+#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME */
+
#ifdef weak_alias
weak_alias (mktime, timelocal)
#endif