#ifdef HAVE_CONFIG_H #include #endif #include /* * asctime/ctime: the fixed-format "Www Mmm dd hh:mm:ss yyyy\n" rendering * (26 bytes including the terminating NUL). Both functions are thin layers * over a single buffer writer: asctime renders a broken-down time directly, * ctime renders localtime(t). Per POSIX the conversion fails (NULL) when * the calendar year lies outside [1000, 9999], which is also what keeps the * fixed 26-byte layout exact. */ static const char *const wd_abbr[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char *const mon_abbr[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; /* * Render tm into buf (26 bytes: 24 + '\n' + '\0'). Returns buf, or NULL * when the year is outside the representable range (the buffer is then * left untouched, matching the POSIX contract). */ static char * asctime_write(const struct tm *tm, char *buf) { int year = tm->tm_year + 1900; int wd = tm->tm_wday; int mo = tm->tm_mon; int mday = tm->tm_mday; const char *s; char *p = buf; if (year < 1000 || year > 9999) { return NULL; } if (wd < 0) { wd = 7 - (-wd) % 7; if (wd == 7) { wd = 0; } } else { wd %= 7; } if (mo < 0) { mo = 12 - (-mo) % 12; if (mo == 12) { mo = 0; } } else { mo %= 12; } s = wd_abbr[wd]; while (*s != '\0') { *p++ = *s++; } *p++ = ' '; s = mon_abbr[mo]; while (*s != '\0') { *p++ = *s++; } *p++ = ' '; if (mday < 10) { *p++ = ' '; } *p++ = (char)('0' + (mday / 10) % 10); *p++ = (char)('0' + mday % 10); *p++ = ' '; *p++ = (char)('0' + (tm->tm_hour / 10) % 10); *p++ = (char)('0' + tm->tm_hour % 10); *p++ = ':'; *p++ = (char)('0' + (tm->tm_min / 10) % 10); *p++ = (char)('0' + tm->tm_min % 10); *p++ = ':'; *p++ = (char)('0' + (tm->tm_sec / 10) % 10); *p++ = (char)('0' + tm->tm_sec % 10); *p++ = ' '; *p++ = (char)('0' + (year / 1000) % 10); *p++ = (char)('0' + (year / 100) % 10); *p++ = (char)('0' + (year / 10) % 10); *p++ = (char)('0' + year % 10); *p++ = '\n'; *p = '\0'; return buf; } char * asctime(const struct tm *tm) // NOLINT(concurrency-mt-unsafe) { static char asctime_buf[26]; return asctime_write(tm, asctime_buf); } char * ctime(const time_t *timer) { return asctime(localtime(timer)); } #if VLIBC_LEVEL_GE(2) char * asctime_r(const struct tm *tm, char *buf) { return asctime_write(tm, buf); } char * ctime_r(const time_t *timer, char *buf) { struct tm tmv; if (localtime_r(timer, &tmv) == NULL) { return NULL; } return asctime_write(&tmv, buf); } #endif /* VLIBC_LEVEL_GE(2) */