stdlibc/time: +calculation of weekday and yearday
[meinos.git] / apps / lib / stdlibc / time.c
blob2dfeb8d3c63984fe7a018ec12b8da40b1b9ed044
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <time.h>
21 #include <cmos.h>
22 #include <syscall.h>
23 #include <stdio.h>
25 static time_t start_time = 0;
26 static clock_t start_ticks;
28 static int is_leapyear(unsigned int year) {
29 if (year%400==0) return 1;
30 else if (year%100==0) return 0;
31 else if (year%4==0) return 1;
32 else return 0;
35 static void getyday(struct tm *tm) {
36 unsigned int mdays[12] = {
37 31,
38 31+28,
39 31+28+31,
40 31+28+31+30,
41 31+28+31+30+31,
42 31+28+31+30+31+30,
43 31+28+31+30+31+30+31,
44 31+28+31+30+31+30+31+31,
45 31+28+31+30+31+30+31+31+30,
46 31+28+31+30+31+30+31+31+30+31,
47 31+28+31+30+31+30+31+31+30+31+30,
48 31+28+31+30+31+30+31+31+30+31+30+31
51 tm->tm_yday = (tm->tm_mon>0?mdays[tm->tm_mon-1]:0)+tm->tm_mday;
52 if (is_leapyear(tm->tm_year+1900)) tm->tm_yday++;
55 static void getwday(struct tm *tm) {
56 unsigned int doomsdays[] = {1,6,4,2};
57 unsigned int year = tm->tm_year+1900;
58 unsigned int dday_idx = (year/100)%4;
59 unsigned int step1 = (year%100)/12;
60 unsigned int step2 = (year%100)%12;
61 unsigned int step3 = step2/4;
62 unsigned int dday_year = (doomsdays[dday_idx]+((step1+step2+step3)%7))%7;
63 unsigned int january0 = dday_year+(7-((59+is_leapyear(year)?1:0)%7));
64 tm->tm_wday = ((january0+(tm->tm_yday%7))%7)-1;
67 char *asctime(const struct tm *timeptr) {
68 char *wday_name[] = {"Sun","Mon","Tue","Wed","Thu", "Fri","Sat"};
69 char *mon_name[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
70 static char result[26];
71 sprintf(result,"%s %s %u %02u:%02u:%02u %u\n",wday_name[timeptr->tm_wday],mon_name[timeptr->tm_mon],timeptr->tm_mday,timeptr->tm_hour,timeptr->tm_min, timeptr->tm_sec,1900+timeptr->tm_year);
72 return result;
75 time_t time(time_t *tloc) {
76 if (start_time==0) {
77 struct tm tm = {
78 .tm_sec = cmos_getsecond(),
79 .tm_min = cmos_getminute(),
80 .tm_hour = cmos_gethour(),
81 .tm_mday = cmos_getday(),
82 .tm_mon = cmos_getmonth()-1,
83 .tm_year = cmos_getyear()-1900
85 getyday(&tm);
86 getwday(&tm);
88 start_time = mktime(&tm);
89 start_ticks = clock();
92 time_t time = start_time+(clock()-start_ticks)/CLOCKS_PER_SEC;
94 if (tloc!=NULL) *tloc = time;
95 return time;
98 time_t mktime(struct tm *tm) {
99 return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 + tm->tm_yday*86400 +
100 (tm->tm_year-70)*31536000 + ((tm->tm_year-69)/4)*86400 -
101 ((tm->tm_year-1)/100)*86400 + ((tm->tm_year+299)/400)*86400;
104 static clock_t start_clock = -1;
105 clock_t clock() {
106 if (start_clock==-1) start_clock = syscall_call(SYSCALL_TIME_GETTICKS,0);
107 return syscall_call(SYSCALL_TIME_GETTICKS,0)-start_clock;