]> sjero.net Git - wget/blobdiff - src/cmpt.c
[svn] Check for timegm and use it where available.
[wget] / src / cmpt.c
index 8168f0d5877936642d14aef4bda1c0fc4b645593..19b56265ff7b9f283206f94575fea44d0966769a 100644 (file)
@@ -1222,3 +1222,71 @@ fnmatch (const char *pattern, const char *string, int flags)
 }
 
 #endif /* not SYSTEM_FNMATCH */
+\f
+#ifndef HAVE_TIMEGM
+/* timegm is a GNU extension typically unavailable on non-glibc-based
+   platforms. */
+
+/* Inverse of gmtime: 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.  This
+   implementation of timegm uses mktime to make the conversion
+   understanding that an offset will be introduced by the local time
+   assumption.
+
+   timegm 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
+
+   Contributed by Roger Beeman <beeman@cisco.com>, with the help of
+   Mark Baushke <mdb@cisco.com> and other experts at CISCO.  Further
+   improved by Roger with assistance from Edward J. Sabol based on
+   input by Jamie Zawinski.  */
+
+time_t
+timegm (struct tm *t)
+{
+  time_t tl, tb;
+  struct tm *tg;
+
+  tl = mktime (t);
+  if (tl == -1)
+    {
+      t->tm_hour--;
+      tl = mktime (t);
+      if (tl == -1)
+       return -1; /* can't deal with contents of T */
+      tl += 3600;
+    }
+  tg = gmtime (&tl);
+  tg->tm_isdst = 0;
+  tb = mktime (tg);
+  if (tb == -1)
+    {
+      tg->tm_hour--;
+      tb = mktime (tg);
+      if (tb == -1)
+       return -1; /* can't deal with output from gmtime */
+      tb += 3600;
+    }
+  return (tl - (tb - tl));
+}
+#endif /* HAVE_TIMEGM */