mailing list of musl libc
 help / color / mirror / code / Atom feed
* [PATCH] fix struct tm.tm_gmtoff to be posive east of UTC
@ 2015-08-13 15:28 Natanael Copa
  2015-08-14  0:48 ` Rich Felker
  0 siblings, 1 reply; 2+ messages in thread
From: Natanael Copa @ 2015-08-13 15:28 UTC (permalink / raw)
  To: musl; +Cc: Natanael Copa

Posix says that tzset() should set the  "extern long timezone" (defined
in time.h) "shall be set to the difference, in seconds, between
Coordinated Universal Time (UTC) and local standard time." This means
that locations east of UTC will have negative value timezone value.

However the value in the glibc additional struct tm field "long
tm_gmtoff" is positive on locations east of UTC, just like the offset in
the zoneinfo database.

From http://man7.org/linux/man-pages/man3/ctime.3.html

  long tm_gmtoff;           /* Seconds east of UTC */

This fixes coreutils' 'date -R' and 'ruby -e "puts Time.now"' to display
correct timezone offset.
---
 src/time/__tz.c        | 12 ++++++------
 src/time/localtime_r.c |  2 +-
 src/time/mktime.c      |  6 +++---
 src/time/strftime.c    |  4 ++--
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/time/__tz.c b/src/time/__tz.c
index 102c8bc..8b84b9b 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -354,9 +354,9 @@ void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo
 		size_t alt, i = scan_trans(t, local, &alt);
 		if (i != -1) {
 			*isdst = types[6*i+4];
-			*offset = -(int32_t)zi_read32(types+6*i);
+			*offset = (int32_t)zi_read32(types+6*i);
 			*zonename = (const char *)abbrevs + types[6*i+5];
-			if (oppoff) *oppoff = -(int32_t)zi_read32(types+6*alt);
+			if (oppoff) *oppoff = (int32_t)zi_read32(types+6*alt);
 			UNLOCK(lock);
 			return;
 		}
@@ -390,15 +390,15 @@ void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo
 	}
 std:
 	*isdst = 0;
-	*offset = __timezone;
-	if (oppoff) *oppoff = dst_off;
+	*offset = -__timezone;
+	if (oppoff) *oppoff = -dst_off;
 	*zonename = __tzname[0];
 	UNLOCK(lock);
 	return;
 dst:
 	*isdst = 1;
-	*offset = dst_off;
-	if (oppoff) *oppoff = __timezone;
+	*offset = -dst_off;
+	if (oppoff) *oppoff = -__timezone;
 	*zonename = __tzname[1];
 	UNLOCK(lock);
 }
diff --git a/src/time/localtime_r.c b/src/time/localtime_r.c
index 1d43d9f..2e62c29 100644
--- a/src/time/localtime_r.c
+++ b/src/time/localtime_r.c
@@ -11,7 +11,7 @@ struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm)
 		return 0;
 	}
 	__secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone);
-	if (__secs_to_tm((long long)*t - tm->__tm_gmtoff, tm) < 0) {
+	if (__secs_to_tm((long long)*t + tm->__tm_gmtoff, tm) < 0) {
 		errno = EOVERFLOW;
 		return 0;
 	}
diff --git a/src/time/mktime.c b/src/time/mktime.c
index 0ab4780..bad3f07 100644
--- a/src/time/mktime.c
+++ b/src/time/mktime.c
@@ -10,14 +10,14 @@ time_t mktime(struct tm *tm)
 	__secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
 
 	if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
-		t += opp - new.__tm_gmtoff;
+		t -= opp - new.__tm_gmtoff;
 
-	t += new.__tm_gmtoff;
+	t -= new.__tm_gmtoff;
 	if ((time_t)t != t) goto error;
 
 	__secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
 
-	if (__secs_to_tm(t - new.__tm_gmtoff, &new) < 0) goto error;
+	if (__secs_to_tm(t + new.__tm_gmtoff, &new) < 0) goto error;
 
 	*tm = new;
 	return t;
diff --git a/src/time/strftime.c b/src/time/strftime.c
index 794fbe1..e945bb7 100644
--- a/src/time/strftime.c
+++ b/src/time/strftime.c
@@ -126,7 +126,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
 		fmt = "%H:%M";
 		goto recu_strftime;
 	case 's':
-		val = __tm_to_secs(tm) + tm->__tm_gmtoff;
+		val = __tm_to_secs(tm) - tm->__tm_gmtoff;
 		width = 1;
 		goto number;
 	case 'S':
@@ -178,7 +178,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
 			return "";
 		}
 		*l = snprintf(*s, sizeof *s, "%+.2d%.2d",
-			(-tm->__tm_gmtoff)/3600,
+			(tm->__tm_gmtoff)/3600,
 			abs(tm->__tm_gmtoff%3600)/60);
 		return *s;
 	case 'Z':
-- 
2.5.0



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] fix struct tm.tm_gmtoff to be posive east of UTC
  2015-08-13 15:28 [PATCH] fix struct tm.tm_gmtoff to be posive east of UTC Natanael Copa
@ 2015-08-14  0:48 ` Rich Felker
  0 siblings, 0 replies; 2+ messages in thread
From: Rich Felker @ 2015-08-14  0:48 UTC (permalink / raw)
  To: musl

On Thu, Aug 13, 2015 at 05:28:39PM +0200, Natanael Copa wrote:
>  src/time/__tz.c        | 12 ++++++------
>  src/time/localtime_r.c |  2 +-
>  src/time/mktime.c      |  6 +++---
>  src/time/strftime.c    |  4 ++--
>  4 files changed, 12 insertions(+), 12 deletions(-)

Committed. Thanks!

Rich


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-08-14  0:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-13 15:28 [PATCH] fix struct tm.tm_gmtoff to be posive east of UTC Natanael Copa
2015-08-14  0:48 ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).