1 
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <time.h>
6 
7 #include <sys/time.h>
8 
9 #include <syscall.h>
10 
11 #define TZ_OFFSET_SECS 0
12 
13 static const char *dayOfWeek[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
14 static const char *months[12] = {
15     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
16     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
17 };
18 
19 time_t
time(time_t * t)20 time(time_t *t)
21 {
22     uint64_t nsec = OSTime();
23     time_t sec = nsec / 1000000000;
24 
25     if (t)
26 	*t = sec;
27 
28     return sec;
29 }
30 
31 int
gettimeofday(struct timeval * tv,struct timezone * tz)32 gettimeofday(struct timeval *tv, struct timezone *tz)
33 {
34     uint64_t nsec = OSTime();
35 
36     tv->tv_sec = nsec / 1000000000;
37     tv->tv_usec = (nsec % 1000000000) / 1000;
38 
39     return 0;
40 }
41 
42 int
settimeofday(const struct timeval * tv,const struct timezone * tz)43 settimeofday(const struct timeval *tv, const struct timezone *tz)
44 {
45     // set errno
46     return -1;
47 }
48 
49 char *
asctime_r(const struct tm * tm,char * buf)50 asctime_r(const struct tm *tm, char *buf)
51 {
52     // assert(tm->tm_wday < 7);
53     // assert(tm->tm_mon < 12);
54 
55     snprintf(buf, 26, "%s %s %2d %2d:%02d:%02d %4d\n",
56 		dayOfWeek[tm->tm_wday], months[tm->tm_mon],
57 		tm->tm_mday, tm->tm_hour, tm->tm_min,
58 		tm->tm_sec, tm->tm_year + 1900);
59 
60     return buf;
61 }
62 
63 char *
asctime(const struct tm * tm)64 asctime(const struct tm *tm)
65 {
66     static char buf[26];
67     return asctime_r(tm, buf);
68 }
69 
70 char *
ctime_r(const time_t * timep,char * buf)71 ctime_r(const time_t *timep, char *buf)
72 {
73     struct tm tm;
74     return asctime_r(localtime_r(timep, &tm), buf);
75 }
76 
77 char *
ctime(const time_t * timep)78 ctime(const time_t *timep)
79 {
80     return asctime(localtime(timep));
81 }
82 
83 static bool
Time_IsLeapYear(uint64_t year)84 Time_IsLeapYear(uint64_t year)
85 {
86     if ((year % 4) != 0)
87 	return false;
88     if ((year % 100) != 0)
89 	return true;
90     if ((year % 400) != 0)
91 	return false;
92     return true;
93 }
94 
95 static int
Time_DaysInMonth(uint64_t year,uint64_t month)96 Time_DaysInMonth(uint64_t year, uint64_t month)
97 {
98     static const uint64_t days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
99 
100     if ((month == 2) && Time_IsLeapYear(year))
101 	return 29;
102     else
103 	return days[month];
104 }
105 
106 
107 struct tm *
gmtime_r(const time_t * timep,struct tm * tm)108 gmtime_r(const time_t *timep, struct tm *tm)
109 {
110     uint64_t secs, mins, hours;
111     uint64_t days;
112     uint64_t y, m;
113 
114     // Compute seconds
115     secs = *timep % (60 * 60 * 24);
116     days = *timep / (60 * 60 * 24);
117     mins = secs / 60;
118     secs = secs % 60;
119 
120     // Compute minutes
121     hours = mins / 60;
122     mins = mins % 60;
123 
124     // Compute hours
125     hours = hours % 24;
126 
127     tm->tm_sec = secs;
128     tm->tm_min = mins;
129     tm->tm_hour = hours;
130 
131     tm->tm_wday = (days + 3) % 7;
132 
133     for (y = 1970; ; y++) {
134 	uint64_t daysOfYear;
135 	if (Time_IsLeapYear(y)) {
136 	    daysOfYear = 366;
137 	} else {
138 	    daysOfYear = 365;
139 	}
140 
141 	if (days < daysOfYear) {
142 	    tm->tm_yday = days;
143 	    tm->tm_year = y - 1900;
144 	    break;
145 	}
146 	days -= daysOfYear;
147     }
148 
149     for (m = 0; ; m++) {
150 	uint64_t daysOfMonth = Time_DaysInMonth(tm->tm_year + 1900, m);
151 
152 	if (days < daysOfMonth) {
153 	    tm->tm_mday = days;
154 	    tm->tm_mon = m;
155 	    break;
156 	}
157 	days -= daysOfMonth;
158     }
159 
160     return tm;
161 }
162 
163 struct tm *
gmtime(const time_t * timep)164 gmtime(const time_t *timep)
165 {
166     static struct tm tm;
167     return gmtime_r(timep, &tm);
168 }
169 
170 struct tm *
localtime_r(const time_t * timep,struct tm * result)171 localtime_r(const time_t *timep, struct tm *result)
172 {
173     time_t t = *timep - TZ_OFFSET_SECS;
174     return gmtime_r(&t, result);
175 }
176 
177 struct tm *
localtime(const time_t * timep)178 localtime(const time_t *timep)
179 {
180     static struct tm tm;
181     return localtime_r(timep, &tm);
182 }
183 
184 time_t
mktime(struct tm * tm)185 mktime(struct tm *tm)
186 {
187     uint64_t days = 0;
188     uint64_t secs = 0;
189     uint64_t y, m;
190 
191     // Convert to UNIX epoch
192     for (y = 70; y < tm->tm_year; y++) {
193 	if (Time_IsLeapYear(y))
194 	    days += 366;
195 	else
196 	    days += 365;
197     }
198 
199     uint64_t yday = 0;
200     for (m = 0; m < tm->tm_mon; m++) {
201 	yday += Time_DaysInMonth(tm->tm_year + 1900, m);
202     }
203     yday += tm->tm_mday;
204     days += yday;
205 
206     secs = 24 * days + tm->tm_hour;
207     secs = secs * 60 + tm->tm_min;
208     secs = secs * 60 + tm->tm_sec;
209 
210     secs += TZ_OFFSET_SECS;
211 
212     return secs;
213 }
214 
215