Minor cleanups
[lightOS.git] / trunk / lib / libc / time.c
blob14ddd28cf7ac50adf3d4a3257860c8d1daef7d5f
1 /*
2 lightOS libc
3 Copyright (C) 2007-2009 Jörg Pfähler
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <time.h>
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <libOS/LIBC_glue.h>
27 * NOTE: Helper functions
30 size_t _LIBC_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
32 static bool _LIBC_is_leap_year(size_t year)
34 if ((year % 400) == 0)return true;
35 if ((year % 100) == 0)return false;
36 if ((year % 4) == 0)return true;
37 return false;
40 size_t _LIBC_calc_day_of_year(size_t year, size_t month)
42 size_t yday = 0;
43 for (size_t i = 0;i < month;i++)
44 yday += _LIBC_month[i];
45 if (_LIBC_is_leap_year(year) == true && month > 1)++yday;
46 return yday;
49 static void _LIBC_calc_month(size_t *days,
50 size_t *month)
52 *month = 1;
53 while (*days >= _LIBC_month[*month - 1])
55 *days -= _LIBC_month[*month - 1];
56 ++*month;
61 * libc functions
64 clock_t clock(void)
66 // TODO
67 return (clock_t) -1;
70 double difftime(time_t time1, time_t time0)
72 return (double)(time1 - time0);
75 time_t mktime(struct tm *timeptr)
77 // NOTE: See http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap04.html#tag_04_14
78 return timeptr->tm_sec + timeptr->tm_min * 60 + timeptr->tm_hour * 3600 + timeptr->tm_yday * 86400 +
79 (timeptr->tm_year - 70) * 31536000 + ((timeptr->tm_year - 69) / 4) * 86400 -
80 ((timeptr->tm_year - 1) / 100) * 86400 + ((timeptr->tm_year + 299) / 400) * 86400;
83 time_t time(time_t *tloc)
85 struct tm time;
86 _LIBOS_get_time(&time);
87 time_t result = mktime(&time);
88 if (tloc != NULL)
89 *tloc = result;
90 return result;
93 char *asctime(const struct tm *timeptr)
95 static const char wday_name[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
96 static const char mon_name[12][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
97 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
98 static char result[26];
99 sprintf(result,
100 "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
101 wday_name[timeptr->tm_wday],
102 mon_name[timeptr->tm_mon],
103 timeptr->tm_mday, timeptr->tm_hour,
104 timeptr->tm_min, timeptr->tm_sec,
105 timeptr->tm_year);
106 return result;
109 char *ctime(const time_t *timer)
111 return asctime(localtime(timer));
114 struct tm *gmtime(const time_t *timer)
116 // TODO?
117 static struct tm result;
119 if (timer == NULL)
120 return NULL;
122 size_t t = *timer;
123 result.tm_sec = t % 60;
124 t /= 60;
125 result.tm_min = t % 60;
126 t /= 60;
127 result.tm_hour = t % 24;
128 t /= 24;
130 result.tm_year = 1970;
131 while (1)
133 bool leapYear = _LIBC_is_leap_year(result.tm_year);
134 if (leapYear == true && t >= 366)
136 result.tm_year++;
137 t -= 366;
139 else if (leapYear == false && t >= 365)
141 result.tm_year++;
142 t -= 365;
144 else
145 break;
148 result.tm_yday = t;
150 size_t mon;
151 _LIBC_calc_month(&t, &mon);
152 result.tm_mon = mon;
153 result.tm_mday = t;
155 // TODO int tm_wday;
156 // TODO int tm_isdst;
157 _LIBOS_WARNING("libc", "incomplete implementation");
158 return &result;
161 struct tm *localtime(const time_t *timer)
163 // TODO: probably not quite right, should consult the locale?
164 _LIBOS_WARNING("libc", "incomplete implementation");
165 return gmtime(timer);
168 size_t strftime(char * restrict s,
169 size_t maxsize,
170 const char * restrict format,
171 const struct tm * restrict timeptr)
173 size_t size = 0;
174 while (*format != '\0')
176 if (*format != '%')
178 if (size == maxsize)
179 return 0;
180 *s++ = *format++;
181 ++size;
182 continue;
185 ++format;
186 bool e_mod = false, o_mod = false;
187 if (*format == 'E')
189 e_mod = true;
190 ++format;
192 else if (*format == 'O')
194 o_mod = true;
195 ++format;
198 // TODO: Use the E and O modifiers
199 if (e_mod != 0 || o_mod != 0)
200 _LIBOS_WARNING("libc", "O and E modifiers not implemented");
202 switch (*format)
204 case 'H':
205 size += 2;
206 if (size > maxsize)
207 return 0;
208 *s++ = timeptr->tm_hour / 10 + '0';
209 *s++ = timeptr->tm_hour % 10 + '0';
210 break;
212 case 'M':
213 size += 2;
214 if (size > maxsize)
215 return 0;
216 *s++ = timeptr->tm_min / 10 + '0';
217 *s++ = timeptr->tm_min % 10 + '0';
218 break;
220 case 'S':
221 size += 2;
222 if (size > maxsize)
223 return 0;
224 *s++ = timeptr->tm_sec / 10 + '0';
225 *s++ = timeptr->tm_sec % 10 + '0';
226 break;
228 case 'y':
229 size += 2;
230 if (size > maxsize)
231 return 0;
232 *s++ = (timeptr->tm_year / 10) % 10 + '0';
233 *s++ = timeptr->tm_year % 10 + '0';
234 break;
235 case 'Y':
236 size += 4;
237 if (size > maxsize)
238 return 0;
239 *s++ = timeptr->tm_year / 1000 + '0';
240 *s++ = (timeptr->tm_year / 100) % 10 + '0';
241 *s++ = (timeptr->tm_year / 10) % 10 + '0';
242 *s++ = timeptr->tm_year % 10 + '0';
243 break;
245 case 'C':
246 size += 2;
247 if (size > maxsize)
248 return 0;
249 *s++ = timeptr->tm_year / 1000 + '0';
250 *s++ = (timeptr->tm_year / 100) % 10 + '0';
251 break;
253 case 'm':
254 size += 2;
255 if (size > maxsize)
256 return 0;
257 *s++ = timeptr->tm_mon / 10 + '0';
258 *s++ = timeptr->tm_mon % 10 + '0';
259 break;
261 case 'd':
262 size += 2;
263 if (size > maxsize)
264 return 0;
265 *s++ = timeptr->tm_mday / 10 + '0';
266 *s++ = timeptr->tm_mday % 10 + '0';
267 break;
269 default:
270 _LIBOS_WARNING("libc", "unimplemented conversion specifier");
271 abort();
273 ++format;
275 ++size;
276 if (size > maxsize)
277 return 0;
278 *s = '\0';
279 return size;