bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnulib] new module: timegm


From: Simon Josefsson
Subject: Re: [Bug-gnulib] new module: timegm
Date: Mon, 01 Sep 2003 17:58:12 +0200
User-agent: Gnus/5.1003 (Gnus v5.10.3) Emacs/21.3.50 (gnu/linux)

Simon Josefsson <address@hidden> writes:

> Bruno Haible <address@hidden> writes:
>
>> Simon Josefsson wrote:
>>> How about a timegm module?
>>
>> What do you think about the implementation at
>> http://lists.debian.org/deity/2002/deity-200204/msg00082.html
>> ?
>
> It looks more likely to be reliable (setenv/tzset/mktime doesn't sound
> like a good approach in a threaded environment).  I'll test it.

It seem to work (on >>10 platforms).

New module below, based on the code above.  I used gmtime_r() where
available(*), and added a few (time_t) casts of -1, I think it is
needed if time_t happens to be smaller than int on some platform.
Still, the code treat time_t as an arithmetic type, which I believe is
only permitted by POSIX, not C89.  So I'm not sure how to classify it,
extension of C89 or POSIX?  The interface is an extension of C89, but
the implementation assumes POSIX.  The patch add it as a extra
function based on C89 in MODULES.html.sh, so people will have to send
a bug report if there actually are systems where time_t isn't an
arithmetic type.

Another problem is if it should depend on the mktime module.  What is
the point of the mktime module, exactly?  The description says it
implement mktime, but the m4 file seem to check for various buggy
implementations.  It is listed as a module for systems lacking C89.
mktime is part of C89.  So if modules can assume C89, timegm should
not depend on mktime, but if modules can assume C89 but allow the C89
implementation to be buggy (and should cope with that), timegm should
depend on the mktime module.

(*) This actually caused troubles, e.g. IA64/HP-UX doesn't declare
gmtime_r unless _REENTRANT is defined, which makes all use of it crash
(if _REENTRANT isn't defined).  Hence the AC_CHECK_DECLS(gmtime_r), so
gmtime_r will only be used if the application somehow causes
_REENTRANT to be defined, which seem to be the right solution.

>>> +/* Convert calendar time to simple time, inverse of mktime. */
>>> +extern time_t timegm (struct tm *tm);
>>
>> What about the tm_isdst field? Is the caller expected to set it or not?
>> The comments should say so. I'm asking because the first thing the glibc
>> implementation of timegm does is to erase the tm->tm_isdst field.
>
> I don't know.  The timegm man page and the libc manual are silent on
> the issue.

Still not sure about this.

2003-08-31  Simon Josefsson  <address@hidden>

        * MODULES.html.sh (func_all_modules): Add timegm.

        * modules/timegm: New file.

2003-08-31  Simon Josefsson  <address@hidden>

        * timegm.h, timegm.c: New files.  Based on WGET 1.8.2
        http.c:mktime_from_utc.

2003-08-31  Simon Josefsson  <address@hidden>

        * timegm.m4: New file.

Index: MODULES.html.sh
===================================================================
RCS file: /cvsroot/gnulib/gnulib/MODULES.html.sh,v
retrieving revision 1.35
diff -u -p -r1.35 MODULES.html.sh
--- MODULES.html.sh     20 Aug 2003 19:45:05 -0000      1.35
+++ MODULES.html.sh     1 Sep 2003 15:47:39 -0000
@@ -1533,6 +1533,7 @@ func_all_modules ()
 
   func_begin_table
   func_module getdate
+  func_module timegm
   func_end_table
 
   element="Input/Output <stdio.h>"
Index: lib/timegm.c
===================================================================
RCS file: lib/timegm.c
diff -N lib/timegm.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/timegm.c        1 Sep 2003 15:47:39 -0000
@@ -0,0 +1,95 @@
+/* Convert calendar time to simple time, inverse of mktime.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2003
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  Get mktime and gmtime declaration.  */
+#include "timegm.h"
+
+/* Converts struct tm to time_t, assuming the data in tm is UTC rather
+   than local timezone.
+
+   mktime is similar but assumes struct tm, also known as the
+   "broken-down" form of time, is in local time zone.  mktime_from_utc
+   uses mktime to make the conversion understanding that an offset
+   will be introduced by the local time assumption.
+
+   mktime_from_utc then measures the introduced offset by applying
+   gmtime to the initial result and applying mktime to the resulting
+   "broken-down" form.  The difference between the two mktime results
+   is the measured offset which is then subtracted from the initial
+   mktime result to yield a calendar time which is the value returned.
+
+   tm_isdst in struct tm is set to 0 to force mktime to introduce a
+   consistent offset (the non DST offset) since tm and tm+o might be
+   on opposite sides of a DST change.
+
+   Some implementations of mktime return -1 for the nonexistent
+   localtime hour at the beginning of DST.  In this event, use
+   mktime(tm - 1hr) + 3600.
+
+   Schematically
+   mktime(tm)   --> t+o
+   gmtime(t+o)  --> tm+o
+   mktime(tm+o) --> t+2o
+   t+o - (t+2o - t+o) = t
+
+   Note that glibc contains a function of the same purpose named
+   `timegm' (reverse of gmtime).  But obviously, it is not universally
+   available, and unfortunately it is not straightforwardly
+   extractable for use here.  Perhaps configure should detect timegm
+   and use it where available.
+
+   Contributed by Roger Beeman <address@hidden>, with the help of
+   Mark Baushke <address@hidden> and the rest of the Gurus at CISCO.
+   Further improved by Roger with assistance from Edward J. Sabol
+   based on input by Jamie Zawinski.  */
+time_t
+timegm (struct tm *tm)
+{
+  time_t tl, tb;
+  struct tm *tg;
+
+  tl = mktime (tm);
+  if (tl == (time_t) - 1)
+    {
+      tm->tm_hour--;
+      tl = mktime (tm);
+      if (tl == (time_t) - 1)
+       return (time_t) - 1;
+      tl += 3600;
+    }
+#if HAVE_GMTIME_R && HAVE_DECL_GMTIME_R
+  tg = gmtime_r (&tl, tg);
+#else
+  tg = gmtime (&tl);
+#endif
+  tg->tm_isdst = 0;
+  tb = mktime (tg);
+  if (tb == (time_t) - 1)
+    {
+      tg->tm_hour--;
+      tb = mktime (tg);
+      if (tb == (time_t) - 1)
+       return (time_t) - 1;
+      tb += 3600;
+    }
+  return (tl - (tb - tl));
+}
Index: lib/timegm.h
===================================================================
RCS file: lib/timegm.h
diff -N lib/timegm.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/timegm.h        1 Sep 2003 15:47:39 -0000
@@ -0,0 +1,31 @@
+/* Convert calendar time to simple time, inverse of mktime.
+   Copyright (C) 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_TIMEGM
+
+/* Get timegm declaration.  */
+#include <time.h>
+
+#else
+
+/* Get time_t and struct tm */
+#include <time.h>
+
+/* Convert calendar time to simple time, inverse of mktime. */
+extern time_t timegm (struct tm *tm);
+
+#endif
Index: m4/timegm.m4
===================================================================
RCS file: m4/timegm.m4
diff -N m4/timegm.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/timegm.m4        1 Sep 2003 15:47:39 -0000
@@ -0,0 +1,25 @@
+# timegm.m4 serial 1
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+AC_DEFUN([gl_FUNC_TIMEGM],
+[
+  AC_REPLACE_FUNCS(timegm)
+  if test $ac_cv_func_timegm = no; then
+    gl_PREREQ_TIMEGM
+  fi
+])
+
+# Prerequisites of lib/timegm.c.
+AC_DEFUN([gl_PREREQ_TIMEGM], [
+  AC_CHECK_DECLS(gmtime_r,,,[
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+])
+  AC_CHECK_FUNCS(gmtime_r)
+])
Index: modules/timegm
===================================================================
RCS file: modules/timegm
diff -N modules/timegm
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/timegm      1 Sep 2003 15:47:39 -0000
@@ -0,0 +1,21 @@
+Description:
+Convert calendar time to simple time, inverse of mktime.
+
+Files:
+lib/timegm.h
+lib/timegm.c
+m4/timegm.m4
+
+Depends-on:
+
+configure.ac:
+gl_FUNC_TIMEGM
+
+Makefile.am:
+lib_SOURCES += timegm.h
+
+Include:
+"timegm.h"
+
+Maintainer:
+Simon Josefsson





reply via email to

[Prev in Thread] Current Thread [Next in Thread]