611ae9b0de3b566f07ceb01eca67ddac29674d6d
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / time.c
1 /*
2  * Acess2 C Library
3  * - By John Hodge (thePowersGang)
4  *
5  * time.c
6  * - POSIX/stdc time functions
7  */
8 #include <time.h>
9 #include <acess/sys.h>
10 #include <string.h>
11 #include "timeconv.h"
12 #include <errno.h>
13 #include <stdio.h>      // sprintf
14
15 #define UNIX_TO_2K      ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
16
17 clock_t clock(void)
18 {
19         return _SysTimestamp();
20 }
21
22 time_t mktime(struct tm *timeptr)
23 {
24         time_t ret = seconds_since_y2k(
25                 timeptr->tm_year - 2000,
26                 timeptr->tm_mon,
27                 timeptr->tm_mday,
28                 timeptr->tm_hour,
29                 timeptr->tm_min,
30                 timeptr->tm_sec
31                 );
32         if( ret == 0 && errno ) {
33                 // Bad date
34         }
35         ret += UNIX_TO_2K;
36         
37         return ret;
38 }
39
40 time_t time(time_t *t)
41 {
42         time_t ret = _SysTimestamp() / 1000;
43         if(t)
44                 *t = ret;
45         return ret;
46 }
47
48 //! Convert the time structure into a string of form 'Sun Sep 16 01:03:52 1973\n\0'
49 char *asctime(const struct tm *timeptr)
50 {
51         static char staticbuf[sizeof("Sun Sep 16 01:03:52 1973\n")];
52         return asctime_r(timeptr, staticbuf);
53 }
54 char *asctime_r(const struct tm *timeptr, char *buf)
55 {
56         const char *WDAYS[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
57         const char *MONS[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
58         sprintf(buf,
59                 "%s %s %i %02i:%02i:%02i %4i\n",
60                 WDAYS[timeptr->tm_wday],
61                 MONS[timeptr->tm_mon],
62                 timeptr->tm_mday,
63                 timeptr->tm_hour,
64                 timeptr->tm_min,
65                 timeptr->tm_sec,
66                 timeptr->tm_year
67                 );
68         return buf;
69 }
70
71 //! asctime(localtime(timer))
72 char *ctime(const time_t *timer)
73 {
74         struct tm       time_buf;
75         localtime_r(timer, &time_buf);
76         return asctime(&time_buf);
77 }
78 extern char *ctime_r(const time_t *timer, char *buf)
79 {
80         struct tm       time_buf;
81         localtime_r(timer, &time_buf);
82         return asctime_r(&time_buf, buf);
83 }
84
85 //! Convert \a timter into UTC
86 struct tm *gmtime(const time_t *timer)
87 {
88         // Ignore UTC
89         return localtime(timer);
90 }
91 struct tm *gmtime_r(const time_t *timer, struct tm *result)
92 {
93         return localtime_r(timer, result);
94 }
95
96 static struct tm        static_tm;
97
98 struct tm *localtime(const time_t *timer)
99 {
100         return localtime_r(timer, &static_tm);
101
102 }
103 struct tm *localtime_r(const time_t *timer, struct tm *ret)
104 {
105         // Hours, Mins, Seconds
106         int64_t days = get_days_since_y2k(*timer, &ret->tm_hour, &ret->tm_min, &ret->tm_sec);
107         
108         // Week day
109         ret->tm_wday = (days + 6) % 7;  // Sun = 0, 1 Jan 2000 was Sat (6)
110         
111         // Year and Day of Year
112         bool    is_ly;
113         ret->tm_year = 2000 + get_years_since_y2k(days, &is_ly, &ret->tm_yday);
114
115         // Month and Day of Month
116         get_month_day(ret->tm_yday, is_ly, &ret->tm_mon, &ret->tm_mday);
117         ret->tm_mon --;
118         
119         ret->tm_isdst = 0;      // Fuck DST
120         
121         return ret;
122 }
123
124 static inline size_t MIN(size_t a, size_t b) { return a < b ? a : b; }
125 static size_t _puts(char * restrict s, size_t maxsize, size_t ofs, const char *str, size_t len)
126 {
127         if( s && ofs < maxsize ) {
128                 size_t  addlen = MIN(len, maxsize-1-ofs);
129                 memcpy(s+ofs, str, addlen);
130         }
131         return len;
132 }
133
134 size_t strftime(char*restrict s, size_t maxsize, const char*restrict format, const struct tm*restrict timeptr)
135 {
136         size_t  ofs = 0;
137
138         while( *format )
139         {
140                 const char *restrict start = format;
141                 while( *format && *format != '%' )
142                         format ++;
143                 if( format != start )
144                         ofs += _puts(s, maxsize, ofs, start, format-start);
145                 if( *format == 0 )
146                         break;
147                 format ++;
148                 
149                 // If EOS is hit on a '%', break early
150                 if( *format == 0 )
151                         break;
152                 switch(*format++)
153                 {
154                 // Literal '%', 
155                 case '%':
156                         ofs += _puts(s, maxsize, ofs, format-1, 1);
157                         break;
158                 // The day of the month as a decimal number (range 01 to 31).
159                 case 'd':
160                         {
161                         char tmp[2] = {'0','0'};
162                         tmp[0] += (timeptr->tm_mday / 10) % 10;
163                         tmp[1] += timeptr->tm_mday % 10;
164                         ofs += _puts(s, maxsize, ofs, tmp, 2);
165                         }
166                         break;
167                 // Two-digit 24 hour
168                 case 'H':
169                         {
170                         char tmp[2] = {'0','0'};
171                         tmp[0] += (timeptr->tm_hour / 10) % 10;
172                         tmp[1] +=  timeptr->tm_hour % 10;
173                         ofs += _puts(s, maxsize, ofs, tmp, 2);
174                         }
175                         break;
176                 // Two-digit minutes
177                 case 'M':
178                         {
179                         char tmp[2] = {'0','0'};
180                         tmp[0] += (timeptr->tm_min / 10) % 10;
181                         tmp[1] +=  timeptr->tm_min % 10;
182                         ofs += _puts(s, maxsize, ofs, tmp, 2);
183                         }
184                         break;
185                 default:
186                         _SysDebug("TODO: strftime('...%%%c...')", format[-1]);
187                         break;
188                 }
189         }
190         
191         return ofs;
192 }

UCC git Repository :: git.ucc.asn.au