[tz] [PROPOSED PATCH 1/4] Have zdump output gmtoff= even on platforms lacking TM_GMTOFF.
Paul Eggert
eggert at cs.ucla.edu
Mon Sep 22 05:53:34 UTC 2014
* zdump.c (adjusted_yday, gmtoff): New functions.
(show): Use new function gmtoff to output gmtoff= even on
platforms that do not define TM_GMTOFF.
* NEWS: Document this.
---
NEWS | 3 +++
zdump.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/NEWS b/NEWS
index 21e85a7..618ddb7 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,9 @@ Unreleased, experimental changes
Changes affecting code
+ zdump -V and -v now output gmtoff= values on all platforms,
+ not merely on platforms defining TM_GMTOFF.
+
The tz library's localtime and mktime functions now set tzname to a value
appropriate for the requested time stamp, and zdump now uses this
on platforms not defining TM_ZONE, fixing a 2014g regression.
diff --git a/zdump.c b/zdump.c
index 0aa94fc..92dd3c1 100644
--- a/zdump.c
+++ b/zdump.c
@@ -851,19 +851,54 @@ delta(struct tm * newp, struct tm *oldp)
return result;
}
+/* Return A->tm_yday, adjusted to compare it fairly to B->tm_yday.
+ Assume A and B differ by at most one year. */
+static int
+adjusted_yday(struct tm const *a, struct tm const *b)
+{
+ int yday = a->tm_yday;
+ if (b->tm_year < a->tm_year)
+ yday += 365 + isleap_sum(b->tm_year, TM_YEAR_BASE);
+ return yday;
+}
+
+/* If A is the broken-down local time and B the broken-down UTC for
+ the same instant, return A's UTC offset in seconds, where positive
+ offsets are east of Greenwich. On failure, return LONG_MIN. */
+static long
+gmtoff(struct tm const *a, struct tm const *b)
+{
+#ifdef TM_GMTOFF
+ return a->TM_GMTOFF;
+#else
+ if (! b)
+ return LONG_MIN;
+ else {
+ int ayday = adjusted_yday(a, b);
+ int byday = adjusted_yday(b, a);
+ int days = ayday - byday;
+ long hours = a->tm_hour - b->tm_hour + 24 * days;
+ long minutes = a->tm_min - b->tm_min + 60 * hours;
+ long seconds = a->tm_sec - b->tm_sec + 60 * minutes;
+ return seconds;
+ }
+#endif
+}
+
static void
show(timezone_t tz, char *zone, time_t t, bool v)
{
register struct tm * tmp;
- struct tm tm;
+ register struct tm * gmtmp;
+ struct tm tm, gmtm;
printf("%-*s ", longest, zone);
if (v) {
- tmp = my_gmtime_r(&t, &tm);
- if (tmp == NULL) {
+ gmtmp = my_gmtime_r(&t, &gmtm);
+ if (gmtmp == NULL) {
printf(tformat(), t);
} else {
- dumptime(tmp);
+ dumptime(gmtmp);
printf(" UT");
}
printf(" = ");
@@ -874,10 +909,10 @@ show(timezone_t tz, char *zone, time_t t, bool v)
if (*abbr(tmp) != '\0')
printf(" %s", abbr(tmp));
if (v) {
+ long off = gmtoff(tmp, gmtmp);
printf(" isdst=%d", tmp->tm_isdst);
-#ifdef TM_GMTOFF
- printf(" gmtoff=%ld", tmp->TM_GMTOFF);
-#endif /* defined TM_GMTOFF */
+ if (off != LONG_MIN)
+ printf(" gmtoff=%ld", off);
}
}
printf("\n");
--
1.9.3
More information about the tz
mailing list