1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
4 // Public Domain C Library - http://pdclib.sourceforge.net
5 // This code is Public Domain. Use, modify, and redistribute at will.
6 // ----------------------------------------------------------------------------
8 char * asctime( const struct tm * tptr ) { /* TODO */ };
9 clock_t clock( void ) { /* TODO */ };
10 char * ctime( const time_t * tod ) { /* TODO */ };
11 double difftime( time_t t1, time_t t0 ) { /* TODO */ };
12 struct tm * gmtime( const time_t * tod ) { /* TODO */ };
13 struct tm * localtime( const time_t * tod ) { /* TODO */ };
14 time_t mktime( struct tm * tptr ) { /* TODO */ };
15 size_t strftime( char * restrict s, size_t n, const char * restrict format,
16 const struct tm * restrict tptr ) { /* TODO */ };
17 time_t time( time_t * tod ) { /* TODO */ };
19 /* PDPC code - unreviewed, verbatim
20 /* scalar date routines -- public domain by Ray Gardner
21 ** These will work over the range 1-01-01 thru 14699-12-31
22 ** The functions written by Ray are isleap, months_to_days,
23 ** years_to_days, ymd_to_scalar, scalar_to_ymd.
24 ** modified slightly by Paul Edwards
27 static int isleap(unsigned yr)
29 return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0);
32 static unsigned months_to_days(unsigned month)
34 return (month * 3057 - 3007) / 100;
37 static long years_to_days (unsigned yr)
39 return yr * 365L + yr / 4 - yr / 100 + yr / 400;
42 static long ymd_to_scalar(unsigned yr, unsigned mo, unsigned day)
46 scalar = day + months_to_days(mo);
47 if ( mo > 2 ) /* adjust if past February */
48 scalar -= isleap(yr) ? 1 : 2;
50 scalar += years_to_days(yr);
54 static void scalar_to_ymd(long scalar,
59 unsigned n; /* compute inverse of years_to_days() */
61 n = (unsigned)((scalar * 400L) / 146097L);
62 while (years_to_days(n) < scalar)
66 for ( n = (unsigned)((scalar * 400L) / 146097L); years_to_days(n) < scalar; )
67 n++; /* 146097 == years_to_days(400) */
69 n = (unsigned)(scalar - years_to_days(n-1));
70 if ( n > 59 ) { /* adjust if past February */
75 *pmo = (n * 100 + 3007) / 3057; /* inverse of months_to_days() */
76 *pday = n - months_to_days(*pmo);
80 time_t time(time_t *timer)
87 #if (defined(__MSDOS__) || defined(__MVS__))
103 rc = DosGetDateTime(&dt);
118 tt = ymd_to_scalar(dt.year, dt.month, dt.day)
119 - ymd_to_scalar(1970, 1, 1);
120 tt = tt * 24 + dt.hours;
121 tt = tt * 60 + dt.minutes;
122 tt = tt * 60 + dt.seconds;
134 return ((clock_t)-1);
137 double difftime(time_t time1, time_t time0)
139 return ((double)(time1 - time0));
142 time_t mktime(struct tm *timeptr)
146 if ((timeptr->tm_year < 70) || (timeptr->tm_year > 120))
152 tt = ymd_to_scalar(timeptr->tm_year + 1900,
155 - ymd_to_scalar(1970, 1, 1);
156 tt = tt * 24 + timeptr->tm_hour;
157 tt = tt * 60 + timeptr->tm_min;
158 tt = tt * 60 + timeptr->tm_sec;
163 char *asctime(const struct tm *timeptr)
165 static const char wday_name[7][3] = {
166 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
168 static const char mon_name[12][3] = {
169 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
170 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
172 static char result[26];
174 sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
175 wday_name[timeptr->tm_wday],
176 mon_name[timeptr->tm_mon],
177 timeptr->tm_mday, timeptr->tm_hour,
178 timeptr->tm_min, timeptr->tm_sec,
179 1900 + timeptr->tm_year);
183 char *ctime(const time_t *timer)
185 return (asctime(localtime(timer)));
188 struct tm *gmtime(const time_t *timer)
190 return (localtime(timer));
193 /* dow - written by Paul Edwards, 1993-01-31 */
194 /* Released to the Public Domain */
195 /* This routine will work over the range 1-01-01 to 32767-12-31.
196 It assumes the current calendar system has always been in
197 place in that time. If you pass 0 or negative years, then
198 it produces results on the assumption that there is a year
199 0. It should always produce a value in the range of 0..6
200 if a valid month and day have been passed, no matter what
201 the year is. However, it has not been tested for negative
202 years, because the results are meaningless anyway. It is
203 mainly to stop people playing silly buggers and causing
204 the macro to crash on negative years. */
206 /* Modified 1994-08-26 by Paul Edwards to make it return
207 0..6 for Sunday..Saturday instead of Monday..Sunday */
208 /* change the "(d) + 1" to "(d) + 0" to get it back to Monday
209 to Sunday if you want */
212 ((((((m)+9)%12+1)<<4)%27 + (d) + 1 + \
213 ((y)%400+400) + ((y)%400+400)/4 - ((y)%400+400)/100 + \
215 (((((y)%4)==0) && (((y)%100)!=0)) || (((y)%400)==0)) \
218 static struct tm tms;
220 struct tm *localtime(const time_t *timer)
226 days = *timer / (60L*60*24);
227 secs = *timer % (60L*60*24);
228 scalar_to_ymd(days + ymd_to_scalar(1970, 1, 1), &yr, &mo, &da);
229 tms.tm_year = yr - 1900;
232 tms.tm_yday = (int)(ymd_to_scalar(tms.tm_year + 1900, 1, 1)
233 - ymd_to_scalar(tms.tm_year + 1900, mo, da));
234 tms.tm_wday = dow(tms.tm_year + 1900, mo, da);
236 tms.tm_sec = (int)(secs % 60);
238 tms.tm_min = (int)(secs % 60);
240 tms.tm_hour = (int)secs;
247 * implements the iso c function strftime()
249 * written 1989-09-06 by jim nutt
250 * released into the public domain by jim nutt
252 * modified 1989-10-21 by Rob Duff
254 * modified 1994-08-26 by Paul Edwards
257 static char *aday[] = {
258 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
261 static char *day[] = {
262 "Sunday", "Monday", "Tuesday", "Wednesday",
263 "Thursday", "Friday", "Saturday"
266 static char *amonth[] = {
267 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
268 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
271 static char *month[] = {
272 "January", "February", "March", "April", "May", "June",
273 "July", "August", "September", "October", "November", "December"
276 static char *__tzname[2] = { "" "" };
279 static void strfmt(char *str, const char *fmt, ...);
283 * size_t strftime(char *str,
286 * const struct tm *t)
288 * this functions acts much like a sprintf for time/date output.
289 * given a pointer to an output buffer, a format string and a
290 * time, it copies the time to the output buffer formatted in
291 * accordance with the format string. the parameters are used
294 * str is a pointer to the output buffer, there should
295 * be at least maxs characters available at the address
298 * maxs is the maximum number of characters to be copied
299 * into the output buffer, included the '\0' terminator
301 * fmt is the format string. a percent sign (%) is used
302 * to indicate that the following character is a special
303 * format character. the following are valid format
306 * %A full weekday name (Monday)
307 * %a abbreviated weekday name (Mon)
308 * %B full month name (January)
309 * %b abbreviated month name (Jan)
310 * %c standard date and time representation
311 * %d day-of-month (01-31)
312 * %H hour (24 hour clock) (00-23)
313 * %I hour (12 hour clock) (01-12)
314 * %j day-of-year (001-366)
317 * %p local equivalent of AM or PM
319 * %U week-of-year, first day sunday (00-53)
320 * %W week-of-year, first day monday (00-53)
321 * %w weekday (0-6, sunday is 0)
322 * %X standard time representation
323 * %x standard date representation
324 * %Y year with century
325 * %y year without century (00-99)
329 * the standard date string is equivalent to:
333 * the standard time string is equivalent to:
337 * the standard date and time string is equivalent to:
339 * %a %b %d %H:%M:%S %Y
341 * strftime returns the number of characters placed in the
342 * buffer, not including the terminating \0, or zero if more
343 * than maxs characters were produced.
347 size_t strftime(char *s, size_t maxs, const char *f, const struct tm *t)
366 r = aday[t->tm_wday];
374 r = amonth[t->tm_mon];
378 r = month[t->tm_mon];
382 strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
383 aday[t->tm_wday], amonth[t->tm_mon],
384 t->tm_mday,t->tm_hour, t->tm_min,
385 t->tm_sec, t->tm_year+1900);
389 strfmt(r,"%2",t->tm_mday);
393 strfmt(r,"%2",t->tm_hour);
397 strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
401 strfmt(r,"%3",t->tm_yday+1);
405 strfmt(r,"%2",t->tm_mon+1);
409 strfmt(r,"%2",t->tm_min);
413 r = (t->tm_hour>11)?"PM":"AM";
417 strfmt(r,"%2",t->tm_sec);
422 if (t->tm_yday%7 > t->tm_wday)
429 if (t->tm_yday%7 > (t->tm_wday+6)%7)
435 strfmt(r,"%1",t->tm_wday);
439 strfmt(r, "%3s %3s %2 %4", aday[t->tm_wday],
440 amonth[t->tm_mon], t->tm_mday, t->tm_year+1900);
444 strfmt(r, "%2:%2:%2", t->tm_hour,
445 t->tm_min, t->tm_sec);
449 strfmt(r,"%2",t->tm_year%100);
453 strfmt(r,"%4",t->tm_year+1900);
457 r = (t->tm_isdst) ? __tzname[1] : __tzname[0];
461 buf[0] = '%'; /* reconstruct the format */
465 f--; /* back up if at end of string */
488 return (size_t)(p - s);
491 static int pow[5] = { 1, 10, 100, 1000, 10000 };
494 * static void strfmt(char *str, char *fmt);
496 * simple sprintf for strftime
498 * each format descriptor is of the form %n
499 * where n goes from zero to four
506 static void strfmt(char *str, const char *fmt, ...)
518 if (ilen == 0) /* zero means string arg */
520 sval = va_arg(vp, char*);
524 else /* always leading zeros */
526 ival = va_arg(vp, int);
530 *str++ = (char)('0' + ival / pow[ilen]);
534 else *str++ = fmt[-1];