2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 #include <exec/types.h>
10 #include <aros/asmcall.h>
11 #include "locale_intern.h"
13 static const UWORD monthdays
[12] =
14 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
15 static const UBYTE monthday
[12] =
16 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
18 BOOL
_getnum(LONG numchars
,
21 CONST_STRPTR
* fmtTemplatePtr
,
23 const struct Locale
*locale
,
24 const struct Hook
*getCharFunc
, struct LocaleBase
*LocaleBase
);
25 #define get2num(x) _getnum(2, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
26 #define get4num(x) _getnum(4, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
28 /*****************************************************************************
31 #include <proto/locale.h>
33 AROS_LH4(BOOL
, ParseDate
,
36 AROS_LHA(const struct Locale
*, locale
, A0
),
37 AROS_LHA(struct DateStamp
*, date
, A1
),
38 AROS_LHA(CONST_STRPTR
, fmtTemplate
, A2
),
39 AROS_LHA(const struct Hook
*, getCharFunc
, A3
),
42 struct LocaleBase
*, LocaleBase
, 27, Locale
)
45 This function will convert a stream of characters into an AmigaDOS
46 DateStamp structure. It will obtain its characters from the
47 getCharFunc callback hook, and the given formatting template will
48 be used to direct the parse.
51 locale - the locale to use for the formatting or NULL for
52 the system default locale.
53 date - where to put the converted date. If this is NULL,
54 then this function can be used to verify a date
56 fmtTemplate - the date template used to direct the parse of the
57 data. The following FormatDate() formatting
59 %a %A %b %B %d %e %h %H %I %m %M %p %S %y %Y
61 See FormatDate() autodoc for more information.
62 getCharFunc - A callback Hook which is used to read the data
63 from a stream. The hook is called with:
65 A0 - address of the Hook structure
69 BTW: The AmigaOS autodocs which state that A1
70 gets locale pointer and A2 NULL are wrong!!
72 The read character should be returned in D0. Note
73 that this is a 32 bit character not an 8 bit
74 character. Return a NULL character if you reach the
78 TRUE - If the parse could be performed.
79 FALSE - If the format of the data did not match the formatting
83 This has a few differences from the implementation in locale.library
85 - %p does not have to be at the end of the line.
86 - %d and %e are not effectively the same: leading spaces are
87 allowed before %e, but not before %d.
92 %p, %b, %A and probably others accept substrings and superstrings of
100 *****************************************************************************/
105 LONG day
= 0, month
= 0, hour
= 0, min
= 0, sec
= 0;
107 BOOL leap
, am
= FALSE
, pm
= FALSE
, checkEOF
= TRUE
;
108 struct Locale
*def_locale
= NULL
;
111 if ((fmtTemplate
== NULL
)
112 || (getCharFunc
== NULL
)
113 || (*fmtTemplate
== '\0'))
118 locale
= OpenLocale(NULL
);
121 def_locale
= (struct Locale
*)locale
;
125 AROS_UFC3(ULONG, getCharFunc->h_Entry, \
126 AROS_UFCA(const struct Hook *, getCharFunc, A0), \
127 AROS_UFCA(const struct Locale *, locale, A2), \
128 AROS_UFCA(ULONG, 0, A1))
132 /* Check for EOF if we leave the loop */
135 if (*fmtTemplate
== '%')
140 switch (*fmtTemplate
++)
142 /* abbreviated weekday name */
148 CONST_STRPTR dayStr
[7];
152 for (i
= 0; i
< 7; i
++)
155 dayStr
[i
] = GetLocaleStr(locale
, i
+ strOffs
+ 1);
159 while ((c
!= '\0') && (c
!= *fmtTemplate
))
161 for (i
= 0; i
< 7; i
++)
163 a
= ConvToUpper(locale
, *(dayStr
[i
])++);
164 c
= ConvToUpper(locale
, c
);
173 /* End of stream in wrong place, or invalid */
174 if (((c
== '\0') && *fmtTemplate
)
175 || (c
!= *fmtTemplate
))
178 /* If we didn't get a valid day, fail */
180 while ((i
< 7) && !dayOk
[i
++])
182 if ((i
== 7) && !dayOk
[6])
189 break; /* case 'A': */
191 /* abbreviated month name */
193 /* abbreviated month name */
198 CONST_STRPTR monthStr
[24];
202 for (i
= 0; i
< 24; i
++)
206 GetLocaleStr(locale
, i
+ strOffs
+ MON_1
);
210 while ((c
!= '\0') && (c
!= *fmtTemplate
))
212 for (i
= 0; i
< 24; i
++)
214 a
= ConvToUpper(locale
, *monthStr
[i
]);
217 c
= ConvToUpper(locale
, c
);
225 for (i
= 0; i
< 24; i
++)
227 if (monthOk
[i
] && *monthStr
[i
] == '\0')
231 /* If we didn't get a valid month, fail */
235 /* End of stream in wrong place, or invalid */
236 if (((c
== '\0') && *fmtTemplate
)
237 || (c
!= *fmtTemplate
))
257 /* Day no., leading spaces. */
261 while (IsSpace(locale
, c
))
270 /* hour 24-hr style */
280 /* hour 12-hr style */
285 if ((hour
> 12) || (hour
== 0))
292 if (!get2num(&month
))
294 if ((month
> 12) || (month
== 0))
308 /* AM or PM string */
311 CONST_STRPTR amStr
, pmStr
;
312 BOOL amOk
= TRUE
, pmOk
= TRUE
;
314 amStr
= GetLocaleStr(locale
, AM_STR
);
315 pmStr
= GetLocaleStr(locale
, PM_STR
);
318 while ((c
!= '\0') && (c
!= *fmtTemplate
))
320 a
= ConvToUpper(locale
, *amStr
++);
321 b
= ConvToUpper(locale
, *pmStr
++);
322 c
= ConvToUpper(locale
, c
);
335 /* End of stream in wrong place, or invalid */
336 if (c
!= *fmtTemplate
)
339 /* Check whether we got AM or PM */
349 /* the number of seconds */
358 /* the year using two or four digits */
364 if (year
>= 100 && year
< 1978)
372 /* the year using four digits */
375 if (IsDigit(locale
, c
) == FALSE
)
377 year
= (c
- '0') * 1000;
380 if (IsDigit(locale
, c
) == FALSE
)
382 year
+= (c
- '0') * 100;
385 if (IsDigit(locale
, c
) == FALSE
)
387 year
+= (c
- '0') * 10;
390 if (IsDigit(locale
, c
) == FALSE
)
402 } /* if (char == '%') */
406 if (c
!= *fmtTemplate
++)
409 } /* while (*fmtTemplate) */
411 /* Reached end of fmtTemplate, end of input stream? */
413 if ((GetChar() != 0))
416 /* Is this year a leap year ? */
417 leap
= (((year
% 400) == 0) ||
418 (((year
% 4) == 0) && !((year
% 100) == 0)));
421 if (month
!= 0 && day
>=
422 (monthday
[month
- 1] + ((leap
&& (month
== 2)) ? 1 : 0)))
429 /* Add the days for all years (without leap years) */
430 day
+= (year
- 1978) * 365;
435 day
+= ((year
/ 4) - (year
/ 100) + (year
/ 400) - (494 - 19 + 4));
437 /* Add days of months */
438 day
+= monthdays
[month
- 1];
441 in monthdays, February has 28 days. Correct this in
442 leap years if month is >= March.
445 if (leap
&& (month
>= 3))
450 date
->ds_Minute
= hour
* 60 + min
;
451 if ((hour
== 12) && am
)
452 date
->ds_Minute
-= 720;
453 if ((hour
< 12) && pm
)
454 date
->ds_Minute
+= 720;
455 date
->ds_Tick
= sec
* TICKS_PER_SECOND
;
460 CloseLocale(def_locale
);
468 BOOL
_getnum(LONG numchars
,
471 CONST_STRPTR
* fmtTemplatePtr
,
473 const struct Locale
* locale
,
474 const struct Hook
* getCharFunc
, struct LocaleBase
* LocaleBase
)
481 if (IsDigit(locale
, c
) == FALSE
)
486 while (--numchars
>= 1)
489 if (IsDigit(locale
, c
))
490 val
= val
* 10 + c
- '0';
494 if (c
!= **fmtTemplatePtr
)
497 *checkEOFPtr
= FALSE
;