[PATCH] Add timegm POSIX call

"Andrew Russell via newlib" <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <CAEFwyTMui0EcsXp0oYmibWSneuCUJANnyrUO90w5WjYOOe_rxQ@mail.gmail.com>
From e182faa79c35984b667029ef7b6e4a8ce7329897 Mon Sep 17 00:00:00 2001
From: Andrew Russell <[email protected]>
Date: Fri, 10 Aug 2018 12:14:18 -0700
Subject: [PATCH 1/4] Start of mktime.c copy to timegm.c

I am proposing to add the timegm POSIX call to
Newlib. Part of this refactors some of the code in libc/time/local.h and
libc/time/mktime.c, per this discussion:

https://sourceware.org/ml/newlib/2018/msg00186.html

Thanks,
Andrew

---
 newlib/libc/time/{mktime.c => timegm.c} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename newlib/libc/time/{mktime.c => timegm.c} (100%)

diff --git a/newlib/libc/time/mktime.c b/newlib/libc/time/timegm.c
similarity index 100%
rename from newlib/libc/time/mktime.c
rename to newlib/libc/time/timegm.c
-- 
2.18.0.597.ga71716f1ad-goog


From e0a614c6d92ee5c14cebf8eaa69ade344998fab6 Mon Sep 17 00:00:00 2001
From: Andrew Russell <[email protected]>
Date: Fri, 10 Aug 2018 12:14:58 -0700
Subject: [PATCH 2/4] Middle of mktime.c copy to timegm.c

---
 newlib/libc/time/{mktime.c => mktime_backup.c} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename newlib/libc/time/{mktime.c => mktime_backup.c} (100%)

diff --git a/newlib/libc/time/mktime.c b/newlib/libc/time/mktime_backup.c
similarity index 100%
rename from newlib/libc/time/mktime.c
rename to newlib/libc/time/mktime_backup.c
-- 
2.18.0.597.ga71716f1ad-goog


From 078c008672c6e3edd98f04b7998397275f466734 Mon Sep 17 00:00:00 2001
From: Andrew Russell <[email protected]>
Date: Fri, 10 Aug 2018 12:16:23 -0700
Subject: [PATCH 3/4] Final commit to copy mktime.c to timegm.c

---
 newlib/libc/time/{mktime_backup.c => mktime.c} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename newlib/libc/time/{mktime_backup.c => mktime.c} (100%)

diff --git a/newlib/libc/time/mktime_backup.c b/newlib/libc/time/mktime.c
similarity index 100%
rename from newlib/libc/time/mktime_backup.c
rename to newlib/libc/time/mktime.c
-- 
2.18.0.597.ga71716f1ad-goog


From 2a8129248f33150c4ee0af17e34de37fcdaecb97 Mon Sep 17 00:00:00 2001
From: Andrew Russell <[email protected]>
Date: Fri, 10 Aug 2018 12:23:36 -0700
Subject: [PATCH 4/4] Refactor mktime and add the POSIX function timegm

---
 newlib/libc/include/time.h   |   1 +
 newlib/libc/saber            |   1 +
 newlib/libc/time/Makefile.am |   2 +
 newlib/libc/time/Makefile.in |  11 ++-
 newlib/libc/time/local.h     |   5 ++
 newlib/libc/time/mktime.c    | 163 ++++------------------------------
 newlib/libc/time/timegm.c    | 164 ++++++++++++-----------------------
 7 files changed, 90 insertions(+), 257 deletions(-)

diff --git a/newlib/libc/include/time.h b/newlib/libc/include/time.h
index a2efcc15e..8440ecb3c 100644
--- a/newlib/libc/include/time.h
+++ b/newlib/libc/include/time.h
@@ -56,6 +56,7 @@ struct tm
 clock_t    clock (void);
 double    difftime (time_t _time2, time_t _time1);
 time_t    mktime (struct tm *_timeptr);
+time_t    timegm (struct tm *_timeptr);
 time_t    time (time_t *_timer);
 #ifndef _REENT_ONLY
 char   *asctime (const struct tm *_tblock);
diff --git a/newlib/libc/saber b/newlib/libc/saber
index 4f16f976e..f57063f82 100644
--- a/newlib/libc/saber
+++ b/newlib/libc/saber
@@ -122,6 +122,7 @@ time/gmtime.c
 time/localtime.c
 time/mktime.c
 time/strftime.c
+time/timegm.c


 load stdio/fiprintf.c
diff --git a/newlib/libc/time/Makefile.am b/newlib/libc/time/Makefile.am
index be040baec..5c73c3a17 100644
--- a/newlib/libc/time/Makefile.am
+++ b/newlib/libc/time/Makefile.am
@@ -17,6 +17,7 @@ LIB_SOURCES = \
  lcltime.c \
  lcltime_r.c \
  mktime.c \
+ timegm.c \
  month_lengths.c \
  strftime.c  \
  strptime.c \
@@ -54,6 +55,7 @@ CHEWOUT_FILES = \
  gmtime.def \
  lcltime.def \
  mktime.def \
+ timegm.def \
  strftime.def \
  time.def \
  tzlock.def \
diff --git a/newlib/libc/time/Makefile.in b/newlib/libc/time/Makefile.in
index a32333234..2845f7438 100644
--- a/newlib/libc/time/Makefile.in
+++ b/newlib/libc/time/Makefile.in
@@ -80,6 +80,7 @@ am__objects_1 = lib_a-asctime.$(OBJEXT)
lib_a-asctime_r.$(OBJEXT) \
  lib_a-lcltime_r.$(OBJEXT) lib_a-mktime.$(OBJEXT) \
  lib_a-month_lengths.$(OBJEXT) lib_a-strftime.$(OBJEXT) \
  lib_a-strptime.$(OBJEXT) lib_a-time.$(OBJEXT) \
+ lib_a-timegm.$(OBJEXT) \
  lib_a-tzcalc_limits.$(OBJEXT) lib_a-tzlock.$(OBJEXT) \
  lib_a-tzset.$(OBJEXT) lib_a-tzset_r.$(OBJEXT) \
  lib_a-tzvars.$(OBJEXT) lib_a-wcsftime.$(OBJEXT)
@@ -90,7 +91,8 @@ libtime_la_LIBADD =
 am__objects_2 = asctime.lo asctime_r.lo clock.lo ctime.lo ctime_r.lo \
  difftime.lo gettzinfo.lo gmtime.lo gmtime_r.lo lcltime.lo \
  lcltime_r.lo mktime.lo month_lengths.lo strftime.lo \
- strptime.lo time.lo tzcalc_limits.lo tzlock.lo tzset.lo \
+ strptime.lo time.lo timegm.lo \
+ tzcalc_limits.lo tzlock.lo tzset.lo \
  tzset_r.lo tzvars.lo wcsftime.lo
 @USE_LIBTOOL_TRUE@am_libtime_la_OBJECTS = $(am__objects_2)
 libtime_la_OBJECTS = $(am_libtime_la_OBJECTS)
@@ -282,6 +284,7 @@ LIB_SOURCES = \
  strftime.c  \
  strptime.c \
  time.c \
+ timegm.c        \
  tzcalc_limits.c \
  tzlock.c \
  tzset.c \
@@ -463,6 +466,12 @@ lib_a-mktime.o: mktime.c
 lib_a-mktime.obj: mktime.c
  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mktime.obj `if test
-f 'mktime.c'; then $(CYGPATH_W) 'mktime.c'; else $(CYGPATH_W)
'$(srcdir)/mktime.c'; fi`

+lib_a-timegm.o: timegm.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-timegm.o `test -f
'timegm.c' || echo '$(srcdir)/'`timegm.c
+
+lib_a-timegm.obj: timegm.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-timegm.obj `if test
-f 'timegm.c'; then $(CYGPATH_W) 'timegm.c'; else $(CYGPATH_W)
'$(srcdir)/timegm.c'; fi`
+
 lib_a-month_lengths.o: month_lengths.c
  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-month_lengths.o
`test -f 'month_lengths.c' || echo '$(srcdir)/'`month_lengths.c

diff --git a/newlib/libc/time/local.h b/newlib/libc/time/local.h
index dce51cda2..543b9fd25 100644
--- a/newlib/libc/time/local.h
+++ b/newlib/libc/time/local.h
@@ -38,3 +38,8 @@ void _tzset_unlocked (void);
 void __tz_lock (void);
 void __tz_unlock (void);

+time_t __timegm_internal (struct tm *tim_p);
+void __set_tm_wday (long days, struct tm *tim_p);
+void __validate_tm_structure (struct tm *tim_p);
+
+int __days_in_year (int year);
diff --git a/newlib/libc/time/mktime.c b/newlib/libc/time/mktime.c
index 02032599a..ab47f8614 100644
--- a/newlib/libc/time/mktime.c
+++ b/newlib/libc/time/mktime.c
@@ -11,6 +11,8 @@
  * represented, returns the value (time_t) -1.
  *
  * Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland.
+ *                      Refactor code from mktime.c to shared internal
+ *                      functions. - 17 July 2018 Andrew Russell.
  */

 /*
@@ -39,157 +41,22 @@ result is the time, converted to a <<time_t>> value.
 PORTABILITY
 ANSI C requires <<mktime>>.

-<<mktime>> requires no supporting OS subroutines.
+<<timegm>> requires no supporting OS subroutines.
 */

 #include <stdlib.h>
 #include <time.h>
 #include "local.h"

-#define _SEC_IN_MINUTE 60L
-#define _SEC_IN_HOUR 3600L
-#define _SEC_IN_DAY 86400L
-
-static const int DAYS_IN_MONTH[12] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
-
-static const int _DAYS_BEFORE_MONTH[12] =
-{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
-
-#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 ||
(((y)+1900) % 400) == 0))
-#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
-
-static void
-validate_structure (struct tm *tim_p)
-{
-  div_t res;
-  int days_in_feb = 28;
-
-  /* calculate time & date to account for out of range values */
-  if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
-    {
-      res = div (tim_p->tm_sec, 60);
-      tim_p->tm_min += res.quot;
-      if ((tim_p->tm_sec = res.rem) < 0)
- {
-   tim_p->tm_sec += 60;
-   --tim_p->tm_min;
- }
-    }
-
-  if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
-    {
-      res = div (tim_p->tm_min, 60);
-      tim_p->tm_hour += res.quot;
-      if ((tim_p->tm_min = res.rem) < 0)
- {
-   tim_p->tm_min += 60;
-   --tim_p->tm_hour;
-        }
-    }
-
-  if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
-    {
-      res = div (tim_p->tm_hour, 24);
-      tim_p->tm_mday += res.quot;
-      if ((tim_p->tm_hour = res.rem) < 0)
- {
-   tim_p->tm_hour += 24;
-   --tim_p->tm_mday;
-        }
-    }
-
-  if (tim_p->tm_mon < 0 || tim_p->tm_mon > 11)
-    {
-      res = div (tim_p->tm_mon, 12);
-      tim_p->tm_year += res.quot;
-      if ((tim_p->tm_mon = res.rem) < 0)
-        {
-   tim_p->tm_mon += 12;
-   --tim_p->tm_year;
-        }
-    }
-
-  if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
-    days_in_feb = 29;
-
-  if (tim_p->tm_mday <= 0)
-    {
-      while (tim_p->tm_mday <= 0)
- {
-   if (--tim_p->tm_mon == -1)
-     {
-       tim_p->tm_year--;
-       tim_p->tm_mon = 11;
-       days_in_feb =
- ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
- 29 : 28);
-     }
-   tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
- }
-    }
-  else
-    {
-      while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
- {
-   tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
-   if (++tim_p->tm_mon == 12)
-     {
-       tim_p->tm_year++;
-       tim_p->tm_mon = 0;
-       days_in_feb =
- ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
- 29 : 28);
-     }
- }
-    }
-}
-
-time_t
+time_t
 mktime (struct tm *tim_p)
 {
-  time_t tim = 0;
-  long days = 0;
-  int year, isdst=0;
+  time_t tim = __timegm_internal(tim_p);
+  long days = tim / SECSPERDAY;
+  int year = tim_p->tm_year;
+  int isdst=0;
   __tzinfo_type *tz = __gettzinfo ();

-  /* validate structure */
-  validate_structure (tim_p);
-
-  /* compute hours, minutes, seconds */
-  tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
-    (tim_p->tm_hour * _SEC_IN_HOUR);
-
-  /* compute days in year */
-  days += tim_p->tm_mday - 1;
-  days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
-  if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
-    days++;
-
-  /* compute day of the year */
-  tim_p->tm_yday = days;
-
-  if (tim_p->tm_year > 10000 || tim_p->tm_year < -10000)
-      return (time_t) -1;
-
-  /* compute days in other years */
-  if ((year = tim_p->tm_year) > 70)
-    {
-      for (year = 70; year < tim_p->tm_year; year++)
- days += _DAYS_IN_YEAR (year);
-    }
-  else if (year < 70)
-    {
-      for (year = 69; year > tim_p->tm_year; year--)
- days -= _DAYS_IN_YEAR (year);
-      days -= _DAYS_IN_YEAR (year);
-    }
-
-  /* compute total seconds */
-  tim += (time_t)days * _SEC_IN_DAY;
-
   TZ_LOCK;

   _tzset_unlocked ();
@@ -204,7 +71,7 @@ mktime (struct tm *tim_p)

       if (y == tz->__tzyear || __tzcalc_limits (y))
  {
-   /* calculate start of dst in dst local time and
+   /* calculate start of dst in dst local time and
       start of std in both std local time and dst local time */
           time_t startdst_dst = tz->__tzrule[0].change
      - (time_t) tz->__tzrule[1].offset;
@@ -237,7 +104,7 @@ mktime (struct tm *tim_p)
    tim_p->tm_sec += diff;
    tim += diff;  /* we also need to correct our current time calculation */
    int mday = tim_p->tm_mday;
-   validate_structure (tim_p);
+   __validate_tm_structure(tim_p);
    mday = tim_p->tm_mday - mday;
    /* roll over occurred */
    if (mday) {
@@ -251,9 +118,9 @@ mktime (struct tm *tim_p)
      /* handle yday */
      if ((tim_p->tm_yday += mday) < 0) {
    --year;
-   tim_p->tm_yday = _DAYS_IN_YEAR(year) - 1;
+   tim_p->tm_yday = __days_in_year(year) - 1;
      } else {
-   mday = _DAYS_IN_YEAR(year);
+   mday = __days_in_year(year);
    if (tim_p->tm_yday > (mday - 1))
  tim_p->tm_yday -= mday;
      }
@@ -275,8 +142,8 @@ mktime (struct tm *tim_p)
   tim_p->tm_isdst = isdst;

   /* compute day of the week */
-  if ((tim_p->tm_wday = (days + 4) % 7) < 0)
-    tim_p->tm_wday += 7;
-
+  __set_tm_wday(days, tim_p);
+
   return tim;
 }
+
diff --git a/newlib/libc/time/timegm.c b/newlib/libc/time/timegm.c
index 02032599a..3299ce228 100644
--- a/newlib/libc/time/timegm.c
+++ b/newlib/libc/time/timegm.c
@@ -1,8 +1,8 @@
 /*
- * mktime.c
+ * timegm.c
  * Original Author: G. Haley
  *
- * Converts the broken-down time, expressed as local time, in the structure
+ * Converts the broken-down time, expressed as UTC time, in the structure
  * pointed to by tim_p into a calendar time value. The original values of the
  * tm_wday and tm_yday fields of the structure are ignored, and the original
  * values of the other fields have no restrictions. On successful completion
@@ -11,25 +11,27 @@
  * represented, returns the value (time_t) -1.
  *
  * Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland.
+ *                  Refactored mktime.c to support both mktime and timegm
+ *                       - 23 July 2018 Andrew Russell.
  */

 /*
 FUNCTION
-<<mktime>>---convert time to arithmetic representation
+<<timegm>>---convert time to arithmetic representation

 INDEX
- mktime
+ timegm

 SYNOPSIS
  #include <time.h>
- time_t mktime(struct tm *<[timp]>);
+ time_t timegm(struct tm *<[timp]>);

 DESCRIPTION
-<<mktime>> assumes the time at <[timp]> is a local time, and converts
+<<timegm>> assumes the time at <[timp]> is UTC time, and converts
 its representation from the traditional representation defined by
 <<struct tm>> into a representation suitable for arithmetic.

-<<localtime>> is the inverse of <<mktime>>.
+<<timegm>> is the inverse of <<gmtime>>.

 RETURNS
 If the contents of the structure at <[timp]> do not form a valid
@@ -37,9 +39,9 @@ calendar time representation, the result is <<-1>>.
Otherwise, the
 result is the time, converted to a <<time_t>> value.

 PORTABILITY
-ANSI C requires <<mktime>>.
+<<timegm>> is a nonstandard GNU extension to POSIX also present on BSD.

-<<mktime>> requires no supporting OS subroutines.
+<<timegm>> requires no supporting OS subroutines.
 */

 #include <stdlib.h>
@@ -58,11 +60,8 @@ static const int DAYS_IN_MONTH[12] =
 static const int _DAYS_BEFORE_MONTH[12] =
 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

-#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 ||
(((y)+1900) % 400) == 0))
-#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
-
-static void
-validate_structure (struct tm *tim_p)
+static void
+__validate_tm_structure (struct tm *tim_p)
 {
   div_t res;
   int days_in_feb = 28;
@@ -112,7 +111,7 @@ validate_structure (struct tm *tim_p)
         }
     }

-  if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
+  if (__days_in_year(tim_p->tm_year) == 366)
     days_in_feb = 29;

   if (tim_p->tm_mday <= 0)
@@ -124,7 +123,7 @@ validate_structure (struct tm *tim_p)
        tim_p->tm_year--;
        tim_p->tm_mon = 11;
        days_in_feb =
- ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
+ ((__days_in_year(tim_p->tm_year) == 366) ?
  29 : 28);
      }
    tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
@@ -140,15 +139,36 @@ validate_structure (struct tm *tim_p)
        tim_p->tm_year++;
        tim_p->tm_mon = 0;
        days_in_feb =
- ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
+ ((__days_in_year(tim_p->tm_year) == 366) ?
  29 : 28);
      }
  }
     }
 }

-time_t
-mktime (struct tm *tim_p)
+void
+__set_tm_wday (long days, struct tm *tim_p)
+{
+  if ((tim_p->tm_wday = (days + 4) % 7) < 0)
+    tim_p->tm_wday += 7;
+}
+
+/* returns either 0 or 1 */
+static
+int
+__is_leap_year (int year)
+{
+  return (year % 4) == 0 && ((year % 100) != 0 || (((year / 100) & 3)
== (-(YEAR_BASE / 100)  & 3)));
+}
+
+int
+__days_in_year (int year)
+{
+  return __is_leap_year(year) ? 366 : 365;
+}
+
+time_t
+__timegm_internal (struct tm *tim_p)
 {
   time_t tim = 0;
   long days = 0;
@@ -156,7 +176,7 @@ mktime (struct tm *tim_p)
   __tzinfo_type *tz = __gettzinfo ();

   /* validate structure */
-  validate_structure (tim_p);
+  __validate_tm_structure (tim_p);

   /* compute hours, minutes, seconds */
   tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
@@ -165,7 +185,7 @@ mktime (struct tm *tim_p)
   /* compute days in year */
   days += tim_p->tm_mday - 1;
   days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
-  if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
+  if (tim_p->tm_mon > 1 && __days_in_year(tim_p->tm_year) == 366)
     days++;

   /* compute day of the year */
@@ -178,105 +198,33 @@ mktime (struct tm *tim_p)
   if ((year = tim_p->tm_year) > 70)
     {
       for (year = 70; year < tim_p->tm_year; year++)
- days += _DAYS_IN_YEAR (year);
+ days += __days_in_year(year);
     }
   else if (year < 70)
     {
       for (year = 69; year > tim_p->tm_year; year--)
- days -= _DAYS_IN_YEAR (year);
-      days -= _DAYS_IN_YEAR (year);
+ days -= __days_in_year(year);
+      days -= __days_in_year(year);
     }

   /* compute total seconds */
   tim += (time_t)days * _SEC_IN_DAY;

-  TZ_LOCK;
-
-  _tzset_unlocked ();
-
-  if (_daylight)
-    {
-      int tm_isdst;
-      int y = tim_p->tm_year + YEAR_BASE;
-      /* Convert user positive into 1 */
-      tm_isdst = tim_p->tm_isdst > 0  ?  1 : tim_p->tm_isdst;
-      isdst = tm_isdst;
-
-      if (y == tz->__tzyear || __tzcalc_limits (y))
- {
-   /* calculate start of dst in dst local time and
-      start of std in both std local time and dst local time */
-          time_t startdst_dst = tz->__tzrule[0].change
-     - (time_t) tz->__tzrule[1].offset;
-   time_t startstd_dst = tz->__tzrule[1].change
-     - (time_t) tz->__tzrule[1].offset;
-   time_t startstd_std = tz->__tzrule[1].change
-     - (time_t) tz->__tzrule[0].offset;
-   /* if the time is in the overlap between dst and std local times */
-   if (tim >= startstd_std && tim < startstd_dst)
-     ; /* we let user decide or leave as -1 */
-          else
-     {
-       isdst = (tz->__tznorth
-        ? (tim >= startdst_dst && tim < startstd_std)
-        : (tim >= startdst_dst || tim < startstd_std));
-       /* if user committed and was wrong, perform correction, but not
-        * if the user has given a negative value (which
-        * asks mktime() to determine if DST is in effect or not) */
-       if (tm_isdst >= 0  &&  (isdst ^ tm_isdst) == 1)
- {
-   /* we either subtract or add the difference between
-      time zone offsets, depending on which way the user got it
-      wrong. The diff is typically one hour, or 3600 seconds,
-      and should fit in a 16-bit int, even though offset
-      is a long to accomodate 12 hours. */
-   int diff = (int) (tz->__tzrule[0].offset
-     - tz->__tzrule[1].offset);
-   if (!isdst)
-     diff = -diff;
-   tim_p->tm_sec += diff;
-   tim += diff;  /* we also need to correct our current time calculation */
-   int mday = tim_p->tm_mday;
-   validate_structure (tim_p);
-   mday = tim_p->tm_mday - mday;
-   /* roll over occurred */
-   if (mday) {
-     /* compensate for month roll overs */
-     if (mday > 1)
-   mday = -1;
-     else if (mday < -1)
-   mday = 1;
-     /* update days for wday calculation */
-     days += mday;
-     /* handle yday */
-     if ((tim_p->tm_yday += mday) < 0) {
-   --year;
-   tim_p->tm_yday = _DAYS_IN_YEAR(year) - 1;
-     } else {
-   mday = _DAYS_IN_YEAR(year);
-   if (tim_p->tm_yday > (mday - 1))
- tim_p->tm_yday -= mday;
-     }
-   }
- }
-     }
- }
-    }
-
-  /* add appropriate offset to put time in gmt format */
-  if (isdst == 1)
-    tim += (time_t) tz->__tzrule[1].offset;
-  else /* otherwise assume std time */
-    tim += (time_t) tz->__tzrule[0].offset;
+  return tim;
+}

-  TZ_UNLOCK;
+time_t
+timegm (struct tm *tim_p)
+{
+  time_t tim = __timegm_internal(tim_p);
+  long days = tim / SECSPERDAY;

-  /* reset isdst flag to what we have calculated */
-  tim_p->tm_isdst = isdst;
+  /* set isdst flag to 0 since we are in UTC */
+  tim_p->tm_isdst = 0;

   /* compute day of the week */
-  if ((tim_p->tm_wday = (days + 4) % 7) < 0)
-    tim_p->tm_wday += 7;
-
+  __set_tm_wday(days, tim_p);
+
   return tim;
 }
+
-- 
2.18.0.597.ga71716f1ad-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.