fxlibc/src/libc/time/mktime.c

59 lines
1.7 KiB
C

#include <time.h>
#include "timeutil.h"
/* TODO: mktime: DST not supported */
time_t mktime(struct tm *time)
{
/* Normalize time */
time->tm_min += (time->tm_sec / 60);
time->tm_hour += (time->tm_min / 60);
time->tm_mday += (time->tm_hour / 24);
time->tm_sec %= 60;
time->tm_min %= 60;
time->tm_hour %= 24;
/* Normalize date */
int days = daysin(time->tm_mon, time->tm_year + 1900);
while(time->tm_mday > days) {
time->tm_mday -= days;
if(++time->tm_mon == 12) {
time->tm_mon = 0;
time->tm_year++;
}
days = daysin(time->tm_mon, time->tm_year + 1900);
}
/* Determine day in year */
time->tm_yday = time->tm_mday - 1;
for(int i = 0; i < time->tm_mon; i++)
time->tm_yday += daysin(i, time->tm_year + 1900);
/* Determine day in week. The calendar has a period of 400 years and
1601-01-01 was a Monday. */
/* Years elapsed since last 400n+1 year (1601-2001-etc). */
int yr = (time->tm_year + 1900 - 1) % 400;
/* Leap years during this period */
int leaps = (yr / 4) - (yr >= 100) - (yr >= 200) - (yr >= 300);
/* Days elapsed since 01-01 on the last 400n+1 year */
days = 365 * yr + leaps + time->tm_yday;
/* Current day of week (1 is Monday on 01-01 of last 400n+1 year) */
time->tm_wday = (1 + days) % 7;
/* We don't determine DST at the targeted time */
time->tm_isdst = 0;
/* Number of periods elapsed since 1601-01-01 (may be negative) */
int periods = (time->tm_year + 1900 - 1601) / 400;
periods -= (time->tm_year + 1900 < 1601);
/* Days elapsed since 1970-01-01; the calendar period is 146097 days
and there are 134774 days between 1601-01-01 and 1970-01-01 */
days += 146097 * periods - 134774;
time_t t = days;
t = 24 * t + time->tm_hour;
t = 60 * t + time->tm_min;
t = 60 * t + time->tm_sec;
return t;
}