Detabbed
[AROS.git] / rom / dos / strtodate.c
blob5025f92e610831ddcdaceda93a079eb98e109c62
1 /*
2 Copyright © 1995-2010, 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 (!Strnicmp (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 (!Strnicmp (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 default: format = "d-M-y"; break;
207 while (*format)
209 switch (*format)
211 case 'y':
212 t = StrToLong (ptr, &year);
214 if (t == -1)
215 return DOSFALSE;
217 if (year < 100)
218 year += 1900;
220 ptr += t;
222 break;
224 case 'M':
225 t = StrToLong (ptr, &month);
227 if (t == -1)
228 return DOSFALSE;
230 ptr += t;
232 break;
234 case 'd':
235 t = StrToLong (ptr, &days);
237 if (t == -1)
238 return DOSFALSE;
240 ptr += t;
242 break;
244 case 'm':
245 for (t=0; t<12; t++)
247 if (!Strnicmp (Dos_MonthTable[t], ptr,
248 strlen (Dos_MonthTable[t])))
249 break;
252 if (t == 12)
253 return DOSFALSE;
255 month = t+1;
257 ptr += strlen (Dos_MonthTable[t]);
259 break;
261 default:
262 if (*ptr != *format)
263 return DOSFALSE;
265 ptr ++;
267 break;
269 } /* switch */
271 format ++;
272 } /* while */
274 /* kprintf ("Year=%ld, Month=%ld, Days=%ld\n",
275 year, month, days); */
277 /* Days go from 1..x */
278 days --;
280 /* First year must be 1978 */
281 if (year < 1978)
282 return DOSFALSE;
284 /* Is this year a leap year ? */
285 leap = (((year % 400) == 0) ||
286 (((year % 4) == 0) && !((year % 100) == 0)));
288 /* Add the days for all years (without leap years) */
289 days += (year - 1978) * 365;
291 #if 1
292 /* stegerg: we do *not* want a day to be added for *this*
293 year, if it is a leap year. Only the previous years
294 are the ones we want to be taken into account. */
296 year--;
297 #endif
299 /* Add leap years */
300 days += ((year / 4) - (year / 100) + (year / 400)
301 - (494 - 19 + 4));
303 //kprintf("strtodate: days1 = %d\n", days);
304 /* Add days of months */
305 days += Dos_DayTable[month-1];
306 //kprintf("strtodate: days2 = %d\n", days);
309 In Dos_DayTable, February has 29 days. Correct this in
310 non-leap years and if the day has not yet been reached.
313 #if 1
314 /* stegerg: if this year is *no* leap year, then Dos_DayTable
315 is wrong by one day when accessing
316 Dos_DayTable[March..Dec] */
318 if (!leap && (month >= 3)) days--;
319 #else
320 if (month >= 2 || (leap && month < 2))
321 days --;
322 #endif
324 //kprintf("strtodate: days3 = %d\n", days);
326 } /* Normal date */
328 } /* Not "Tomorrow", "Today" or "Yesterday" */
330 datetime->dat_Stamp.ds_Days = days;
332 } /* Convert date ? */
334 if ((ptr = datetime->dat_StrTime))
336 len = StrToLong (ptr, &t);
338 if ((len == -1) || (t < 0) || (t > 23))
339 return DOSFALSE;
341 min = t * 60;
343 ptr += len;
345 if (*ptr++ != ':')
346 return DOSFALSE;
348 len = StrToLong (ptr, &t);
350 if ((len == -1) || (t < 0) || (t > 59))
351 return DOSFALSE;
353 min += t;
355 ptr += len;
357 if (*ptr != '\0')
359 if (*ptr++ != ':')
360 return DOSFALSE;
362 len = StrToLong (ptr, &t);
364 if ((len == -1) || (t < 0) || (t > 59))
365 return DOSFALSE;
367 tick = t * TICKS_PER_SECOND;
369 else
370 tick = 0;
372 datetime->dat_Stamp.ds_Minute = min;
373 datetime->dat_Stamp.ds_Tick = tick;
377 return DOSTRUE;
378 AROS_LIBFUNC_EXIT
379 } /* StrToDate */
381 #ifdef TEST
382 # include <stdio.h>
384 int main (int argc, char ** argv)
386 struct DateTime dt;
387 char * date;
388 char * time;
389 char daybuf[LEN_DATSTRING];
390 char datebuf[LEN_DATSTRING];
391 char timebuf[LEN_DATSTRING];
393 if (argc >= 2)
394 date = argv[1];
395 else
396 date = NULL;
398 if (argc >= 3)
399 time = argv[2];
400 else
401 time = NULL;
403 dt.dat_StrDate = date;
404 dt.dat_StrTime = time;
405 dt.dat_Flags = 0;
406 dt.dat_Format = FORMAT_CDN;
408 if (!StrToDate (&dt))
410 printf ("Cannot convert date/time\n");
411 return 10;
413 else
415 printf ("Result: Days=%ld, Minute=%ld, Ticks=%ld\n"
416 , dt.dat_Stamp.ds_Days
417 , dt.dat_Stamp.ds_Minute
418 , dt.dat_Stamp.ds_Tick
421 dt.dat_StrDay = daybuf;
422 dt.dat_StrDate = datebuf;
423 dt.dat_StrTime = timebuf;
425 DateToStr (&dt);
427 printf ("Gives: %s, %s %s\n", daybuf, datebuf, timebuf);
429 dt.dat_Flags = DTF_SUBST;
431 DateToStr (&dt);
433 printf ("(With DTF_SUBST): %s, %s %s\n", daybuf, datebuf, timebuf);
437 return 0;
438 } /* main */
440 #endif /* TEST */