Andrew Russell via newlib
2018-08-14 01:17:06 UTC
From e182faa79c35984b667029ef7b6e4a8ce7329897 Mon Sep 17 00:00:00 2001
From: Andrew Russell <***@google.com>
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 <***@google.com>
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 <***@google.com>
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 <***@google.com>
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
@***@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;
}
+
From: Andrew Russell <***@google.com>
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 <***@google.com>
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 <***@google.com>
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 <***@google.com>
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
@***@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
2.18.0.597.ga71716f1ad-goog