When rounding up the fractional portion of the printed value, increment
the seconds portion if necessary (instead of printing ':', i.e. '0'+10).

    TIMEFORMAT='%0R %1R %2R %6R'
    for _ in {1..5}; { time sleep 0.98; }

    0 0.: 0.98 0.984048
    0 0.: 0.99 0.992579
    0 0.: 0.:0 0.999416
    0 0.: 0.:0 0.998138
    1 1.0 1.00 1.001916

Also, I'm assuming it was not intentional that values with a precision
of 0 were being truncated while all other precisions were rounded (but
maybe it was?).
---
 execute_cmd.c | 56 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/execute_cmd.c b/execute_cmd.c
index 436f37ba..92b9f1fc 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1278,13 +1278,43 @@ static const int maxvals[] = { 1, 10, 100, 1000, 10000, 
100000, 10000000 };
 /* Expand one `%'-prefixed escape sequence from a time format string. */
 /* SEC_FRACTION is in usecs. We normalize and round that based on the
   precision. */
-int
+static int
 mkfmt (char *buf, int prec, int lng, time_t sec, long sec_fraction)
 {
   time_t min;
   char abuf[INT_STRLEN_BOUND(time_t) + 1];
   int ind, aind;
 
+  /* We want to add a decimal point and PREC places after it if PREC is
+     nonzero.  PREC is not greater than 6.  SEC_FRACTION is between 0
+     and 999999 (microseconds). */
+  if (0 <= prec && prec < 6)
+    {
+      /* We round here because we changed timeval_to_secs to return
+        microseconds and normalized clock_t_to_secs's fractional return
+        value to microseconds, deferring the work to be done to now.
+
+        Cut off digits in excess of PREC from SEC_FRACTION, round up if
+        necessary, handle potential overflow into SEC, then convert back
+        to microseconds. */
+      int frac, rest, maxval;
+
+      maxval = maxvals[6 - prec];
+      frac = sec_fraction / maxval;
+      rest = sec_fraction % maxval;
+
+      if (rest >= maxval/2)
+       frac++;
+
+      if (frac == maxvals[prec])
+       {
+         sec++;
+         sec_fraction = 0;
+       }
+      else
+       sec_fraction = frac * (1000000 / maxvals[prec]);
+    }
+
   ind = 0;
   abuf[sizeof(abuf) - 1] = '\0';
 
@@ -1312,32 +1342,8 @@ mkfmt (char *buf, int prec, int lng, time_t sec, long 
sec_fraction)
   while (abuf[aind])
     buf[ind++] = abuf[aind++];
 
-  /* We want to add a decimal point and PREC places after it if PREC is
-     nonzero.  PREC is not greater than 6.  SEC_FRACTION is between 0
-     and 999999 (microseconds). */
   if (prec != 0)
     {
-      /* We round here because we changed timeval_to_secs to return
-        microseconds and normalized clock_t_to_secs's fractional return
-        value to microseconds, deferring the work to be done to now.
-
-        sec_fraction is in microseconds. Take the value, cut off what we
-        don't want, round up if necessary, then convert back to
-        microseconds. */
-      if (prec != 6)
-       {
-         int frac, rest, maxval;
-
-         maxval = maxvals[6 - prec];
-         frac = sec_fraction / maxval;
-         rest = sec_fraction % maxval;
-
-         if (rest >= maxval/2)
-         frac++;
-
-         sec_fraction = frac * (1000000 / maxvals[prec]);
-       }
-  
       buf[ind++] = locale_decpoint ();
       for (aind = 1; aind <= prec; aind++)
        {
-- 
2.51.0


  • [PATCH] time: fi... Grisha Levit

Reply via email to