POSIX does not require strptime() to derive tm_mon/tm_mday from %j, and musl does not, so ordinal ISO 8601 dates (e.g. "2001-34") were mis-parsed on musl. Bug: https://bugs.gentoo.org/922481 --- a/src/unix.c +++ b/src/unix.c @@ -22,8 +22,23 @@ return IE_SUCCESS; offset = strptime((char*)string, "%Y-%j", time); - if (offset && *offset == '\0') + if (offset && *offset == '\0') { + /* POSIX does not require strptime() to derive tm_mon and tm_mday + * from %j, and musl does not (it only sets tm_yday). */ + static const int days_before_month[12] = + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + const int year = time->tm_year + 1900; + const int leap = + ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); + int mon = 11; + while ((mon > 0) && + (time->tm_yday < days_before_month[mon] + ((mon >= 2) ? leap : 0))) + mon--; + time->tm_mon = mon; + time->tm_mday = time->tm_yday - days_before_month[mon] + - ((mon >= 2) ? leap : 0) + 1; return IE_SUCCESS; + } return IE_NOTSUP; }