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