libc: Add a wide range of time manipulation functions, including reentrant variants
This commit is contained in:
parent
2d2db300b0
commit
e676fb8299
13
apps/app.c
13
apps/app.c
@ -1,8 +1,5 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
|
||||
void bye()
|
||||
@ -15,13 +12,6 @@ int main()
|
||||
atexit(bye);
|
||||
printf("Welcome to %s!\n", "Luna");
|
||||
|
||||
time_t now = time(NULL);
|
||||
printf("Realtime clock: %ld s\n", now);
|
||||
|
||||
for (int i = 0; i < atoi("8"); i++) { console_write(".", 1); }
|
||||
|
||||
console_write("\n", 1);
|
||||
|
||||
char* address = (char*)malloc(1);
|
||||
printf("address: %p\n", address);
|
||||
printf("memory at address: %c\n", *address);
|
||||
@ -29,4 +19,7 @@ int main()
|
||||
printf("memory at address: %c\n", *address);
|
||||
|
||||
free(address);
|
||||
|
||||
time_t now = time(NULL);
|
||||
printf("date: %s", ctime(&now));
|
||||
}
|
||||
|
19
libc/include/bits/struct_tm.h
Normal file
19
libc/include/bits/struct_tm.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* bits/struct_tm.h: Broken-down time. */
|
||||
|
||||
#ifndef _BITS_STRUCT_TM_H
|
||||
#define _BITS_STRUCT_TM_H
|
||||
|
||||
struct tm
|
||||
{
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,3 +1,5 @@
|
||||
/* sys/mman.h: Memory allocation and deallocation. */
|
||||
|
||||
#ifndef _LUNA_MMAN_H
|
||||
#define _LUNA_MMAN_H
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define _TIME_H
|
||||
|
||||
#include <bits/clockid.h>
|
||||
#include <bits/struct_tm.h>
|
||||
#include <bits/timespec.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -17,6 +18,30 @@ extern "C"
|
||||
/* Get the current wall clock time. */
|
||||
time_t time(time_t* tp);
|
||||
|
||||
/* Get the broken-down time representation of UNIX time, in local time. */
|
||||
struct tm* localtime(const time_t* tp);
|
||||
|
||||
/* Get the broken-down time representation of UNIX time, in local time. */
|
||||
struct tm* localtime_r(const time_t* tp, struct tm* out);
|
||||
|
||||
/* Get the broken-down time representation of UNIX time, in UTC time. */
|
||||
struct tm* gmtime(const time_t* tp);
|
||||
|
||||
/* Get the broken-down time representation of UNIX time, in UTC time. */
|
||||
struct tm* gmtime_r(const time_t* tp, struct tm* out);
|
||||
|
||||
/* Build a string representation of broken-down time. */
|
||||
char* asctime(const struct tm* tm);
|
||||
|
||||
/* Build a string representation of broken-down time. */
|
||||
char* asctime_r(const struct tm* tm, char buf[26]);
|
||||
|
||||
/* Build a string representation of UNIX time. */
|
||||
char* ctime(const time_t* tp);
|
||||
|
||||
/* Build a string representation of UNIX time. */
|
||||
char* ctime_r(const time_t* tp, char buf[26]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,8 +1,93 @@
|
||||
#define _LUNA_SYSTEM_ERROR_EXTENSIONS
|
||||
#include <bits/errno-return.h>
|
||||
#include <luna/Check.h>
|
||||
#include <luna/Format.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SECONDS_PER_DAY 86400
|
||||
|
||||
static int isleap(int year)
|
||||
{
|
||||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
|
||||
static int make_yday(int year, int month)
|
||||
{
|
||||
static const short int upto[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
int yd;
|
||||
|
||||
yd = upto[month - 1];
|
||||
if (month > 2 && isleap(year)) yd++;
|
||||
return yd;
|
||||
}
|
||||
|
||||
static int day_of_week(int year, int mon, int day)
|
||||
{
|
||||
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
|
||||
year -= mon < 3;
|
||||
return (year + year / 4 - year / 100 + year / 400 + t[mon - 1] + day) % 7;
|
||||
}
|
||||
|
||||
static void time_to_struct_tm(time_t time, struct tm* result)
|
||||
{
|
||||
result->tm_isdst = 0; // No DST/timezone support for now.
|
||||
|
||||
int year = 1970;
|
||||
|
||||
while (time > 0)
|
||||
{
|
||||
time_t seconds_in_year = (isleap(year) ? 366 : 365) * SECONDS_PER_DAY;
|
||||
if (seconds_in_year <= time)
|
||||
{
|
||||
year++;
|
||||
time -= seconds_in_year;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int month_days[] = { 31, isleap(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
int month = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
time_t seconds_in_month = month_days[month] * SECONDS_PER_DAY;
|
||||
if (seconds_in_month <= time)
|
||||
{
|
||||
month++;
|
||||
time -= seconds_in_month;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int day = (int)(time / SECONDS_PER_DAY);
|
||||
time %= SECONDS_PER_DAY;
|
||||
|
||||
check(day < month_days[month]);
|
||||
|
||||
int hour = (int)(time / 3600);
|
||||
time %= 3600;
|
||||
|
||||
int min = (int)(time / 60);
|
||||
time %= 60;
|
||||
|
||||
result->tm_year = year - 1900;
|
||||
result->tm_mon = month;
|
||||
result->tm_yday = make_yday(year, month + 1) + day;
|
||||
result->tm_wday = day_of_week(year, month + 1, day + 1);
|
||||
result->tm_mday = day + 1;
|
||||
result->tm_hour = hour;
|
||||
result->tm_min = min;
|
||||
result->tm_sec = (int)time;
|
||||
}
|
||||
|
||||
const char* wday_names[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
const char* month_names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int clock_gettime(clockid_t id, struct timespec* ts)
|
||||
@ -20,4 +105,52 @@ extern "C"
|
||||
|
||||
return ts.tv_sec;
|
||||
}
|
||||
|
||||
struct tm* localtime_r(const time_t* tp, struct tm* out)
|
||||
{
|
||||
time_to_struct_tm(*tp, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct tm* gmtime_r(const time_t* tp, struct tm* out)
|
||||
{
|
||||
time_to_struct_tm(*tp, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct tm* localtime(const time_t* tp)
|
||||
{
|
||||
static struct tm out;
|
||||
return localtime_r(tp, &out);
|
||||
}
|
||||
|
||||
struct tm* gmtime(const time_t* tp)
|
||||
{
|
||||
static struct tm out;
|
||||
return gmtime_r(tp, &out);
|
||||
}
|
||||
|
||||
char* asctime_r(const struct tm* tm, char buf[26])
|
||||
{
|
||||
string_format(buf, 26, "%s %s %.2d %.2d:%.2d:%.2d %4d\n", wday_names[tm->tm_wday], month_names[tm->tm_mon],
|
||||
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char* asctime(const struct tm* tm)
|
||||
{
|
||||
static char buf[26];
|
||||
return asctime_r(tm, buf);
|
||||
}
|
||||
|
||||
char* ctime_r(const time_t* tp, char buf[26])
|
||||
{
|
||||
struct tm out;
|
||||
return asctime_r(localtime_r(tp, &out), buf);
|
||||
}
|
||||
|
||||
char* ctime(const time_t* tp)
|
||||
{
|
||||
return asctime(localtime(tp));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user