Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / dos / strtodate.c
blob9fe06fc92e7d47aaeb9e2ded211926ce9f4c2577
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Converts a string into a date
6 Lang: english
7 */
8 #include <string.h>
9 #include "dos_intern.h"
11 #ifdef TEST
12 # include <proto/dos.h>
13 # include <stdio.h>
14 # undef AROS_LH1
15 # undef StrToDate
16 # undef AROS_LHA
17 # define AROS_LH1(ret,name,arg,type,base,offset,libname) \
18 ret name (arg)
19 # define AROS_LHA(type,name,reg) type name
21 const ULONG Dos_DayTable[]=
23 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
26 const char *const Dos_MonthTable[]=
28 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
29 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
32 const char *const Dos_WeekTable[]=
34 "Sunday", "Monday", "Tuesday", "Wednesday",
35 "Thursday", "Friday", "Saturday"
38 const char *const Dos_SubstDateTable[]=
40 "Tomorrow", "Today", "Yesterday"
42 #else
43 # include "date.h"
44 #endif
46 /*****************************************************************************
48 NAME */
49 #include <dos/datetime.h>
50 #include <proto/dos.h>
52 AROS_LH1(BOOL, StrToDate,
54 /* SYNOPSIS */
55 AROS_LHA(struct DateTime *, datetime, D1),
57 /* LOCATION */
58 struct DosLibrary *, DOSBase, 125, Dos)
60 /* FUNCTION
61 Converts a human readable ASCII string into an AmigaDOS
62 DateStamp.
64 INPUTS
65 DateTime - a pointer to an initialized DateTime structure.
66 The structure should be initialized as follows:
68 dat_Stamp: The converted date will be written here
70 dat_Format: How to convert the datestamp into
71 dat_StrDate. Can be any of the following:
73 FORMAT_DOS: AmigaDOS format (dd-mmm-yy). This
74 is the default if you specify something other
75 than any entry in this list.
77 FORMAT_INT: International format (yy-mmm-dd).
79 FORMAT_USA: American format (mm-dd-yy).
81 FORMAT_CDN: Canadian format (dd-mm-yy).
83 FORMAT_DEF: default format for locale.
86 dat_Flags: Modifies dat_Format. The only flag
87 used by this function is DTF_FUTURE. If set, then
88 a string like "Monday" refers to the next monday.
89 Otherwise it refers to the last monday.
91 dat_StrDay: Ignored.
93 dat_StrDate: Pointer to valid string representing the
94 date. This can be a "DTF_SUBST" style string such
95 as "Today" "Tomorrow" "Monday", or it may be a
96 string as specified by the dat_Format byte. This
97 will be converted to the ds_Days portion of the
98 DateStamp. If this pointer is NULL,
99 DateStamp->ds_Days will not be affected.
101 dat_StrTime: Pointer to a buffer which contains the
102 time in the ASCII format hh:mm:ss. This will be
103 converted to the ds_Minutes and ds_Ticks portions
104 of the DateStamp. If this pointer is NULL,
105 ds_Minutes and ds_Ticks will be unchanged.
108 RESULT
109 A zero return indicates that a conversion could not be performed. A
110 non-zero return indicates that the DateTime.dat_Stamp variable
111 contains the converted values.
113 NOTES
115 EXAMPLE
117 BUGS
119 SEE ALSO
120 DateStamp(), DateToStr()
122 INTERNALS
124 *****************************************************************************/
126 AROS_LIBFUNC_INIT
127 struct DateStamp curr;
128 LONG days, min, tick, len, t, year, month;
129 BOOL leap;
130 UBYTE * ptr, * format;
132 if ((ptr = datetime->dat_StrDate))
134 DateStamp (&curr);
136 for (t=0; t<3; t++)
138 if (!strncasecmp (Dos_SubstDateTable[t], ptr, strlen (Dos_SubstDateTable[t])))
139 break;
142 if (t != 3)
143 days = curr.ds_Days + 1 - t;
144 else
146 for (t=0; t<7; t++)
148 if (!strncasecmp (Dos_WeekTable[t], ptr, strlen (Dos_WeekTable[t])))
149 break;
152 if (t != 7)
154 #if 1
155 LONG diffdays;
157 days = curr.ds_Days;
159 diffdays = t - (days % 7);
161 if (datetime->dat_Flags & DTF_FUTURE)
163 if (diffdays > 0)
165 days += diffdays;
167 else
169 days += 7 + diffdays;
172 else
174 if (diffdays < 0)
176 days += diffdays;
178 else
180 days += diffdays - 7;
183 #else
184 days = curr.ds_Days;
186 if ((days % 7) == 0)
187 days -= 7;
188 else
189 days -= (days % 7);
191 days += t;
193 if (datetime->dat_Flags & DTF_FUTURE)
194 days += 7;
195 #endif
197 else
199 switch (datetime->dat_Format)
201 case FORMAT_INT: format = "y-m-d"; break;
202 case FORMAT_USA: format = "M-d-y"; break;
203 case FORMAT_CDN: format = "d-M-y"; break;
204 case FORMAT_DEF: format = "d.M.y"; break;
205 default: format = "d-m-y"; break;
208 while (*format)
210 switch (*format)
212 case 'y':
213 t = StrToLong (ptr, &year);
215 if (t == -1)
216 return DOSFALSE;
218 if (year < 100)
219 year += 1900;
221 ptr += t;
223 break;
225 case 'M':
226 t = StrToLong (ptr, &month);
228 if (t == -1)
229 return DOSFALSE;
231 ptr += t;
233 break;
235 case 'd':
236 t = StrToLong (ptr, &days);
238 if (t == -1)
239 return DOSFALSE;
241 ptr += t;
243 break;
245 case 'm':
246 for (t=0; t<12; t++)
248 if (!strncasecmp (Dos_MonthTable[t], ptr,
249 strlen (Dos_MonthTable[t])))
250 break;
253 if (t == 12)
254 return DOSFALSE;
256 month = t+1;
258 ptr += strlen (Dos_MonthTable[t]);
260 break;
262 default:
263 if (*ptr != *format)
264 return DOSFALSE;
266 ptr ++;
268 break;
270 } /* switch */
272 format ++;
273 } /* while */
275 /* kprintf ("Year=%ld, Month=%ld, Days=%ld\n",
276 year, month, days); */
278 /* Days go from 1..x */
279 days --;
281 /* First year must be 1978 */
282 if (year < 1978)
283 return DOSFALSE;
285 /* Is this year a leap year ? */
286 leap = (((year % 400) == 0) ||
287 (((year % 4) == 0) && !((year % 100) == 0)));
289 /* Add the days for all years (without leap years) */
290 days += (year - 1978) * 365;
292 #if 1
293 /* stegerg: we do *not* want a day to be added for *this*
294 year, if it is a leap year. Only the previous years
295 are the ones we want to be taken into account. */
297 year--;
298 #endif
300 /* Add leap years */
301 days += ((year / 4) - (year / 100) + (year / 400)
302 - (494 - 19 + 4));
304 //kprintf("strtodate: days1 = %d\n", days);
305 /* Add days of months */
306 days += Dos_DayTable[month-1];
307 //kprintf("strtodate: days2 = %d\n", days);
310 In Dos_DayTable, February has 29 days. Correct this in
311 non-leap years and if the day has not yet been reached.
314 #if 1
315 /* stegerg: if this year is *no* leap year, then Dos_DayTable
316 is wrong by one day when accessing
317 Dos_DayTable[March..Dec] */
319 if (!leap && (month >= 3)) days--;
320 #else
321 if (month >= 2 || (leap && month < 2))
322 days --;
323 #endif
325 //kprintf("strtodate: days3 = %d\n", days);
327 } /* Normal date */
329 } /* Not "Tomorrow", "Today" or "Yesterday" */
331 datetime->dat_Stamp.ds_Days = days;
333 } /* Convert date ? */
335 if ((ptr = datetime->dat_StrTime))
337 len = StrToLong (ptr, &t);
339 if ((len == -1) || (t < 0) || (t > 23))
340 return DOSFALSE;
342 min = t * 60;
344 ptr += len;
346 if (*ptr++ != ':')
347 return DOSFALSE;
349 len = StrToLong (ptr, &t);
351 if ((len == -1) || (t < 0) || (t > 59))
352 return DOSFALSE;
354 min += t;
356 ptr += len;
358 if (*ptr != '\0')
360 if (*ptr++ != ':')
361 return DOSFALSE;
363 len = StrToLong (ptr, &t);
365 if ((len == -1) || (t < 0) || (t > 59))
366 return DOSFALSE;
368 tick = t * TICKS_PER_SECOND;
370 else
371 tick = 0;
373 datetime->dat_Stamp.ds_Minute = min;
374 datetime->dat_Stamp.ds_Tick = tick;
378 return DOSTRUE;
379 AROS_LIBFUNC_EXIT
380 } /* StrToDate */
382 #ifdef TEST
383 # include <stdio.h>
385 int main (int argc, char ** argv)
387 struct DateTime dt;
388 char * date;
389 char * time;
390 char daybuf[LEN_DATSTRING];
391 char datebuf[LEN_DATSTRING];
392 char timebuf[LEN_DATSTRING];
394 if (argc >= 2)
395 date = argv[1];
396 else
397 date = NULL;
399 if (argc >= 3)
400 time = argv[2];
401 else
402 time = NULL;
404 dt.dat_StrDate = date;
405 dt.dat_StrTime = time;
406 dt.dat_Flags = 0;
407 dt.dat_Format = FORMAT_CDN;
409 if (!StrToDate (&dt))
411 printf ("Cannot convert date/time\n");
412 return 10;
414 else
416 printf ("Result: Days=%ld, Minute=%ld, Ticks=%ld\n"
417 , dt.dat_Stamp.ds_Days
418 , dt.dat_Stamp.ds_Minute
419 , dt.dat_Stamp.ds_Tick
422 dt.dat_StrDay = daybuf;
423 dt.dat_StrDate = datebuf;
424 dt.dat_StrTime = timebuf;
426 DateToStr (&dt);
428 printf ("Gives: %s, %s %s\n", daybuf, datebuf, timebuf);
430 dt.dat_Flags = DTF_SUBST;
432 DateToStr (&dt);
434 printf ("(With DTF_SUBST): %s, %s %s\n", daybuf, datebuf, timebuf);
438 return 0;
439 } /* main */
441 #endif /* TEST */