Files
vlibc/src/time/ctime.c
T

136 lines
2.9 KiB
C

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
/*
* 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) */