ref: 88412aa050adddde5cacf3a45e914bad9a5d3e22
parent: 37f710de39e9cf06240907053f3ab931f81d8e9a
author: rodri <rgl@antares-labs.eu>
date: Sun Aug 13 16:17:09 EDT 2023
tmdate: add ordinal day of month format specifier
--- a/sys/man/2/tmdate
+++ b/sys/man/2/tmdate
@@ -122,6 +122,9 @@
.B a, A
Lower and uppercase 'am' and 'pm' specifiers, respectively.
.TP
+.B o
+Ordinal day of month suffix specifier.
+.TP
.B [...]
Quoted text, copied directly to the output.
.TP
--- a/sys/src/libc/port/date.c
+++ b/sys/src/libc/port/date.c
@@ -454,6 +454,15 @@
default: goto badfmt;
}
break;
+ case 'o':
+ if(w != 1) goto badfmt;
+ switch(tm->mday){
+ case 1: case 21: case 31: n += fmtprint(f, "st"); break;
+ case 2: case 22: n += fmtprint(f, "nd"); break;
+ case 3: case 23: n += fmtprint(f, "rd"); break;
+ default: n += fmtprint(f, "th");
+ }
+ break;
case 'W':
switch(w){
case 1: n += fmtprint(f, "%*d", pad, tm->wday + 1); break;
@@ -696,6 +705,15 @@
case 2: tm->mday = getnum(&s, 2, &ok); break;
default: goto badfmt;
}
+ break;
+ case 'o':
+ if(strncmp(s, "th", 2) == 0
+ || strncmp(s, "rd", 2) == 0
+ || strncmp(s, "nd", 2) == 0
+ || strncmp(s, "st", 2) == 0)
+ s += 2;
+ else
+ goto badfmt;
break;
case 'W':
switch(w){
--- a/sys/src/libc/test/date.c
+++ b/sys/src/libc/test/date.c
@@ -278,6 +278,25 @@
print("bad am/pm parsed: %s != %s (%lld != %lld)\n", buf, buf1, tmnorm(&tm), tmnorm(&tt));
}
+ /* ordinal day suffix parsing and formatting */
+ for(i = 1; i < 32; i++){
+ snprint(buf, sizeof(buf), "2023 08 %d", i);
+ snprint(buf1, sizeof(buf1), "2023 08 %02d%s", i,
+ i == 1 || i == 21 || i == 31? "st": i == 2 || i == 22? "nd": i == 3 || i == 23? "rd": "th");
+ if(tmparse(&tm, "YYYY MM DD", buf, nil, nil) == nil)
+ fail("parse: %r\n");
+ if(tmparse(&tt, "YYYY MM DDo", buf1, nil, nil) == nil)
+ fail("parse: %r\n");
+ if(tmnorm(&tm) != tmnorm(&tt))
+ print("bad ordinal day suffix parsed: %s != %s (%lld != %lld)\n", buf, buf1, tmnorm(&tm), tmnorm(&tt));
+ if(tmparse(&tm, "YYYY MM DDo", buf, nil, nil) != nil)
+ print("ordinal day suffix parsed when absent\n");
+ if(snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "YYYY MM DDo")) == -1)
+ fail("format: %r");
+ if(strcmp(buf, buf1) != 0)
+ print("bad ordinal day suffix formatted: %s != %s\n", buf, buf1);
+ }
+
/* Time zone boundaries: entering DST */
if(tmtime(&tm, 1520733600, us_eastern) == nil)
fail("tmtime: tz boundary");