From c7f0da4134d4e7f2efd295e7fb738c65c469fbd1 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 6 Feb 2018 12:31:06 -0500 Subject: [PATCH] adjust strftime + modifier to match apparent intent of POSIX MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit it's unclear from the specification whether the word "consumes" in "consumes more than four bytes to represent a year" refers just to significant places or includes leading zeros due to field width padding. however the examples in the rationale indicate that the latter was the intent. in particular, the year 270 is shown being formatted by %+5Y as +0270 rather than 00270. previously '+' prefixing was implemented just by comparing the year against 10000. instead, count the number of significant digits and padding bytes to be added, and use the total to determine whether to apply the '+' prefix. based on testing by Dennis Wölfing. --- src/time/strftime.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/time/strftime.c b/src/time/strftime.c index 16b3bb21..708875ee 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -251,15 +251,21 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st t = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad); if (!t) break; if (width) { + /* Trim off any sign and leading zeros, then + * count remaining digits to determine behavior + * for the + flag. */ if (*t=='+' || *t=='-') t++, k--; for (; *t=='0' && t[1]-'0'<10U; t++, k--); - width--; - if (plus && tm->tm_year >= 10000-1900) - s[l++] = '+'; - else if (tm->tm_year < -1900) + if (width < k) width = k; + size_t d; + for (d=0; t[d]-'0'<10U; d++); + if (tm->tm_year < -1900) { s[l++] = '-'; - else - width++; + width--; + } else if (plus && d+(width-k) >= (*p=='C'?3:5)) { + s[l++] = '+'; + width--; + } for (; width > k && l < n; width--) s[l++] = '0'; } -- 2.25.1