183 lines
4.5 KiB
C++
183 lines
4.5 KiB
C++
#include <assert.h>
|
|
#include <luna.h>
|
|
#include <luna/syscall.h>
|
|
#include <stdio.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 time_t broken_down_to_unix(time_t year, time_t yday, time_t hour, time_t min, time_t sec)
|
|
{
|
|
return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 -
|
|
((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400;
|
|
}
|
|
|
|
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;
|
|
|
|
assert(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 + 1;
|
|
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"
|
|
{
|
|
clock_t clock()
|
|
{
|
|
struct timespec tp;
|
|
clock_gettime(CLOCK_PROCTIME, &tp);
|
|
return (tp.tv_sec * CLOCKS_PER_SEC) + (tp.tv_nsec / 1000);
|
|
}
|
|
|
|
time_t time(time_t* tloc)
|
|
{
|
|
struct timespec tp;
|
|
clock_gettime(CLOCK_REALTIME, &tp);
|
|
if (tloc) { *tloc = tp.tv_sec; }
|
|
return tp.tv_sec;
|
|
}
|
|
|
|
int clock_gettime(clockid_t clock_id, struct timespec* tp)
|
|
{
|
|
return (int)__lc_fast_syscall2(SYS_clock_gettime, clock_id, tp);
|
|
}
|
|
|
|
int gettimeofday(struct timeval* tp, __lc_unused void* tzp)
|
|
{
|
|
struct timespec tspec;
|
|
clock_gettime(CLOCK_REALTIME, &tspec);
|
|
tp->tv_sec = tspec.tv_sec;
|
|
tp->tv_usec = tspec.tv_nsec / 1000;
|
|
return 0;
|
|
}
|
|
|
|
struct tm* localtime(const time_t* time)
|
|
{
|
|
static struct tm result;
|
|
return localtime_r(time, &result);
|
|
}
|
|
|
|
struct tm* gmtime(const time_t* time)
|
|
{
|
|
static struct tm result;
|
|
return gmtime_r(time, &result);
|
|
}
|
|
|
|
struct tm* localtime_r(const time_t* time, struct tm* result)
|
|
{
|
|
return gmtime_r(time, result); // FIXME: Implement timezones.
|
|
}
|
|
|
|
struct tm* gmtime_r(const time_t* time, struct tm* result)
|
|
{
|
|
time_to_struct_tm(*time, result);
|
|
return result;
|
|
}
|
|
|
|
char* asctime_r(const struct tm* time, char buf[26])
|
|
{
|
|
strftime(buf, 26, "%a %b %d %H:%M:%S %Y\n", time);
|
|
return buf;
|
|
}
|
|
|
|
char* asctime(const struct tm* time)
|
|
{
|
|
static char buf[26];
|
|
return asctime_r(time, buf);
|
|
}
|
|
|
|
char* ctime_r(const time_t* time, char buf[26])
|
|
{
|
|
struct tm stm;
|
|
return asctime_r(localtime_r(time, &stm), buf);
|
|
}
|
|
|
|
char* ctime(const time_t* time)
|
|
{
|
|
return asctime(localtime(time));
|
|
}
|
|
|
|
time_t mktime(struct tm* time)
|
|
{
|
|
return broken_down_to_unix(time->tm_year, time->tm_yday, time->tm_hour, time->tm_min, time->tm_sec);
|
|
}
|
|
|
|
double difftime(time_t time2, time_t time1)
|
|
{
|
|
return (double)(time2 - time1);
|
|
}
|
|
} |