Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] ztrftime(): Fix truncation for %.



On 24 Dec 2018, at 06:45, Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
>Also, in (unpatched) master:
>
>% strftime '[%3.]' 123456789
>[000]
>% strftime '[%s][%3.]' 0 123456789
>[0][124]
>% 
>
>Shouldn't the former print [124]?

No, %. only uses the nanoseconds value given to ztrftime(), which is
implicitly 0 in the former case. It's not substituting an arbitrary series of
inputs in the style of printf, it only takes those two time arguments to
ztrftime().

On 24 Dec 2018, at 06:45, Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
>but nsec=11151 would print '1115'.  (The +8 should probably be +5 ---
>half the radix.)

Oh, wow. That's... extremely obvious in hind sight. Apparently i had changed
the +5 to +8 in the ztrftime() patch that originally added nanosecond support,
i guess mindlessly associating it with the 5 that used to be in the loop.
Embarrassing.

... How about this, then? This also fixes an issue where you can't use %. more
than once in the format string because it overwrites the original value.

dana


diff --git a/Src/utils.c b/Src/utils.c
index e43a3cdb4..70ac7ac8d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3334,19 +3334,22 @@ morefmt:
 #endif
 	    switch (*fmt++) {
 	    case '.':
-		if (ztrftimebuf(&bufsize, digs))
-		    return -1;
+	    {
 		if (digs > 9)
 		    digs = 9;
+		if (ztrftimebuf(&bufsize, digs))
+		    return -1;
+		long fnsec = nsec;
 		if (digs < 9) {
 		    int trunc;
 		    for (trunc = 8 - digs; trunc; trunc--)
-			nsec /= 10;
-		    nsec = (nsec + 8) / 10;
+			fnsec /= 10;
+		    fnsec = (nsec < 999999500 ? (fnsec + 5) : fnsec) / 10;
 		}
-		sprintf(buf, "%0*ld", digs, nsec);
+		sprintf(buf, "%0*ld", digs, fnsec);
 		buf += digs;
 		break;
+	    }
 	    case '\0':
 		/* Guard against premature end of string */
 		*buf++ = '%';
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 2041d9b40..3fee49e1d 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -114,3 +114,17 @@
 
   strftime -r '%Y' 2> /dev/null
 1:-r timestring not optional
+
+  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 999_999 ))
+  for 1 in %. %1. %3. %6. %9. %12.; do
+    print -rn - "$1 "
+    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
+  done
+0:%. truncation
+>2002-02-02 02:02:02.001
+>%. 2002-02-02 02:02:02.999
+>%1. 2002-02-02 02:02:02.9
+>%3. 2002-02-02 02:02:02.999
+>%6. 2002-02-02 02:02:02.999999
+>%9. 2002-02-02 02:02:02.999999999
+>%12. 2002-02-02 02:02:02.999999999



Messages sorted by: Reverse Date, Date, Thread, Author