feat(time): time/clock/mktime/strftime/nanosleep
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
#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) */
|
||||
Reference in New Issue
Block a user