41 #include "qofdate-p.h"
45 AS_STRING_FUNC (QofDateError , ENUM_ERR_LIST)
47 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
48 # define match_string(cs1, s2) \
49 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
52 #define get_number(from, to, n) \
58 if (*rp < '0' || *rp > '9') \
60 *error = ERR_OUT_OF_RANGE; \
61 PERR (" error=%s", QofDateErrorasString (*error)); \
68 while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
69 if (val < from || val > to) \
71 *error = ERR_INVALID_DELIMITER; \
72 PERR (" error=%s", QofDateErrorasString (*error)); \
78 # define get_alt_number(from, to, n) \
79 get_number(from, to, n)
81 #define recursive(new_fmt) \
82 (*(new_fmt) != '\0' && (rp = strptime_internal (rp, (new_fmt), qd, error)) != NULL)
84 static gchar
const weekday_name[][10] = {
85 "Sunday",
"Monday",
"Tuesday",
"Wednesday",
86 "Thursday",
"Friday",
"Saturday"
88 static gchar
const ab_weekday_name[][4] = {
89 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
91 static gchar
const month_name[][10] = {
92 "January",
"February",
"March",
"April",
"May",
"June",
93 "July",
"August",
"September",
"October",
"November",
"December"
95 static gchar
const ab_month_name[][4] = {
96 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
97 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
100 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
101 # define HERE_D_FMT "%m/%d/%y"
102 # define HERE_AM_STR "AM"
103 # define HERE_PM_STR "PM"
104 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
105 # define HERE_T_FMT "%H:%M:%S"
110 static const gushort yeardays[2][13] = {
111 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
112 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
117 set_day_of_the_week (
QofDate * qd)
121 days = days_between (1970, qd->
qd_year);
128 qd->
qd_wday = ((days % 7) + 7) % 7;
132 strptime_internal (
const gchar * rp,
const gchar * fmt,
133 QofDate * qd, QofDateError * error)
135 const gchar *rp_backup;
136 gint64 val, century, want_century;
137 gint want_era, have_wday, want_xday, have_yday;
138 gint have_mon, have_mday, have_uweek, have_wweek;
139 gint week_no, have_I, is_pm, cnt, decided, era_cnt;
140 struct era_entry *era;
150 *error = ERR_NO_ERROR;
152 have_wday = want_xday = have_yday = have_mon = 0;
153 have_mday = have_uweek = have_wweek = 0;
161 while (isspace (*rp))
171 match_char (*fmt++, *rp++);
186 match_char (
'%', *rp++);
191 for (cnt = 0; cnt < 7; ++cnt)
193 if (match_string (weekday_name[cnt], rp)
194 || match_string (ab_weekday_name[cnt], rp))
200 *error = ERR_WEEKDAY_NAME;
201 PERR (
" error=%s", QofDateErrorasString (*error));
211 for (cnt = 0; cnt < 12; ++cnt)
213 if (match_string (month_name[cnt], rp)
214 || match_string (ab_month_name[cnt], rp))
223 *error = ERR_MONTH_NAME;
224 PERR (
" error=%s", QofDateErrorasString (*error));
232 if (!recursive (HERE_D_T_FMT))
234 *error = ERR_LOCALE_DATE_TIME;
235 PERR (
" error=%s", QofDateErrorasString (*error));
242 get_number (0, 99, 2);
249 get_number (1, 31, 2);
255 if (!recursive (
"%Y-%m-%d"))
263 if (!recursive (HERE_D_FMT))
265 *error = ERR_STANDARD_DAY;
266 PERR (
" error=%s", QofDateErrorasString (*error));
274 get_number (0, 23, 2);
282 get_number (1, 12, 2);
288 get_number (1, 366, 3);
294 get_number (1, 12, 2);
301 get_number (0, 59, 2);
309 while (n < 9 && *rp >=
'0' && *rp <=
'9')
311 val = val * 10 + *rp++ -
'0';
320 while (isspace (*rp))
325 if (!match_string (HERE_AM_STR, rp))
327 if (match_string (HERE_PM_STR, rp))
331 *error = ERR_LOCALE_AMPM;
332 PERR (
" error=%s", QofDateErrorasString (*error));
338 if (!recursive (HERE_T_FMT_AMPM))
340 *error = ERR_TIME_AMPM;
341 PERR (
" error=%s", QofDateErrorasString (*error));
346 if (!recursive (
"%H:%M"))
348 *error = ERR_RECURSIVE_R;
349 PERR (
" error=%s", QofDateErrorasString (*error));
360 if (*rp < '0' || *rp >
'9')
363 *error = ERR_SECS_NO_DIGITS;
364 PERR (
" error=%s", QofDateErrorasString (*error));
372 while (*rp >=
'0' && *rp <=
'9');
380 get_number (0, 61, 2);
386 if (!recursive (HERE_T_FMT))
388 *error = ERR_RECURSIVE_T;
389 PERR (
" error=%s", QofDateErrorasString (*error));
394 get_number (1, 7, 1);
399 get_number (0, 99, 2);
403 if (*rp < '0' || *rp >
'9')
405 *error = ERR_G_INCOMPLETE;
406 PERR (
" error=%s", QofDateErrorasString (*error));
413 while (*rp >=
'0' && *rp <=
'9');
416 get_number (0, 53, 2);
421 get_number (0, 53, 2);
426 get_number (0, 53, 2);
432 get_number (0, 6, 1);
438 get_number (0, 99, 2);
441 qd->
qd_year = val >= 69 ? val + 2000 : val + 1900;
448 get_number (0, 999999999, 9);
455 PINFO (
" Z format - todo?");
467 if (*rp !=
'+' && *rp !=
'-')
469 *error = ERR_INVALID_Z;
470 PERR (
" error=%s", QofDateErrorasString (*error));
475 while (n < 4 && *rp >=
'0' && *rp <=
'9')
477 val = val * 10 + *rp++ -
'0';
485 *error = ERR_YEAR_DIGITS;
486 PERR (
" error=%s", QofDateErrorasString (*error));
494 *error = ERR_MIN_TO_DECIMAL;
495 PERR (
" error=%s", QofDateErrorasString (*error));
498 val = (val / 100) * 100 + ((val % 100) * 50) / 30;
503 PERR (
" error=%s", QofDateErrorasString (*error));
514 if (*fmt !=
'c' && *fmt !=
'C' && *fmt !=
'y' && *fmt !=
'Y'
515 && *fmt !=
'x' && *fmt !=
'X')
518 *error = ERR_INVALID_FORMAT;
519 PERR (
" error=%s", QofDateErrorasString (*error));
530 get_alt_number (1, 31, 2);
538 get_alt_number (0, 23, 2);
545 get_alt_number (1, 12, 2);
551 get_alt_number (1, 12, 2);
558 get_alt_number (0, 59, 2);
563 get_alt_number (0, 61, 2);
567 get_alt_number (0, 53, 2);
572 get_alt_number (0, 53, 2);
577 get_alt_number (0, 53, 2);
583 get_alt_number (0, 6, 1);
589 get_alt_number (0, 99, 2);
590 qd->
qd_year = val >= 69 ? val : val + 100;
595 *error = ERR_UNKNOWN_ERR;
596 PERR (
" error=%s (first default)",
597 QofDateErrorasString (*error));
604 *error = ERR_UNKNOWN_ERR;
605 PERR (
" error=%s val=%s (second default)",
606 QofDateErrorasString (*error), rp);
622 qd->
qd_year = (century - 19) * 100;
629 *error = ERR_INVALID_ERA;
630 PERR (
" error=%s", QofDateErrorasString (*error));
639 if (want_century && century == -1 && qd->
qd_year < 69)
643 if (want_xday && !have_wday)
645 if (!(have_mon && have_mday) && have_yday)
650 while (yeardays[leap][t_mon] <=
657 yeardays[leap][t_mon - 1] + 1;
659 set_day_of_the_week (qd);
662 if (want_xday && !have_yday)
666 if ((have_uweek || have_wweek) && have_wday)
670 gint save_mon = qd->
qd_mon;
671 gint w_offset = have_uweek ? 0 : 1;
675 set_day_of_the_week (qd);
683 + (week_no - 1) * 7 + save_wday - w_offset);
685 if (!have_mday || !have_mon)