[tz] [PROPOSED] zic now rounds to even

Paul Eggert eggert at cs.ucla.edu
Mon Feb 5 05:12:34 UTC 2018


* NEWS, zic.8: Mention this.
* zic.c (gethms): Round to even instead of discarding fractional
seconds.
---
 NEWS  |  5 +++--
 zic.8 |  4 +++-
 zic.c | 18 ++++++++++++++----
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index f00b29f..adc9814 100644
--- a/NEWS
+++ b/NEWS
@@ -45,8 +45,9 @@ Unreleased, experimental changes
 
     zic now accepts fractional seconds in expressions like 00:19:32.13
     (the UT offset of the Netherlands from 1835 to 1937).  Although
-    zic currently ignores these fractions, they may be useful to
-    applications requiring more precision in historical timestamps.
+    zic currently rounds these fractions to the nearest integer
+    (breaking ties to the even integer), the fractions may be useful
+    to applications requiring more precision in historical timestamps.
 
     The code is a bit more portable to MS-Windows.  (Thanks to Manuela
     Friedrich).
diff --git a/zic.8 b/zic.8
index f1fc8e2..28e4bd6 100644
--- a/zic.8
+++ b/zic.8
@@ -267,8 +267,10 @@ where hour 0 is midnight at the start of the day,
 and hour 24 is midnight at the end of the day.
 Although
 .I zic
-currently ignores any fractional seconds, the fractions may be useful
+currently rounds fractional seconds to the nearest integer
+(breaking ties to the even integer), the fractions may be useful
 to other applications requiring greater precision.
+The source format does not specify any maximum precision.
 Any of these forms may be followed by the letter
 .B w
 if the given time is local
diff --git a/zic.c b/zic.c
index 4965a10..6ad31f9 100644
--- a/zic.c
+++ b/zic.c
@@ -1197,7 +1197,8 @@ gethms(char const *string, char const *errstring, bool signable)
 {
 	zic_t	hh;
 	int sign, mm = 0, ss = 0;
-	char hhx, mmx, ssx, xs;
+	char hhx, mmx, ssx, xr = '0', xs;
+	int tenths = 0;
 	bool ok = true;
 
 	if (string == NULL || *string == '\0')
@@ -1209,10 +1210,18 @@ gethms(char const *string, char const *errstring, bool signable)
 		++string;
 	} else	sign = 1;
 	switch (sscanf(string,
-		       "%"SCNdZIC"%c%d%c%d%c%*1d%*[0123456789]%c",
-		       &hh, &hhx, &mm, &mmx, &ss, &ssx, &xs)) {
+		       "%"SCNdZIC"%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
+		       &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs)) {
 	  default: ok = false; break;
-	  case 6: ok &= ssx == '.'; /* fallthrough */
+	  case 8:
+	    ok = '0' <= xr && xr <= '9';
+	    /* fallthrough */
+	  case 7:
+	    ok &= ssx == '.';
+	    if (ok && noise)
+	      warning(_("fractional seconds rejected by"
+			" pre-2018 versions of zic"));
+	    /* fallthrough */
 	  case 5: ok &= mmx == ':'; /* fallthrough */
 	  case 3: ok &= hhx == ':'; /* fallthrough */
 	  case 1: break;
@@ -1231,6 +1240,7 @@ gethms(char const *string, char const *errstring, bool signable)
 		error(_("time overflow"));
 		return 0;
 	}
+	ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even.  */
 	if (noise && (hh > HOURSPERDAY ||
 		(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
-- 
2.7.4



More information about the tz mailing list