-static bool
-parse_TIME (struct data_in *i)
-{
- int sign;
- double second;
- long hour, minute;
-
- if (!parse_leader (i)
- || !parse_sign (i, &sign)
- || !parse_spaces (i)
- || !parse_hour (i, &hour)
- || !parse_time_delimiter (i)
- || !parse_minute (i, &minute)
- || !parse_opt_second (i, &second))
- return false;
-
- i->v->f = (hour * 60. * 60. + minute * 60. + second) * sign;
- return true;
-}
-
-static bool
-parse_DTIME (struct data_in *i)
-{
- int sign;
- long day_count, hour;
- double second;
- long minute;
-
- if (!parse_leader (i)
- || !parse_sign (i, &sign)
- || !parse_spaces (i)
- || !parse_day_count (i, &day_count)
- || !parse_time_delimiter (i)
- || !parse_hour (i, &hour)
- || !parse_time_delimiter (i)
- || !parse_minute (i, &minute)
- || !parse_opt_second (i, &second))
- return false;
-
- i->v->f = (day_count * 60. * 60. * 24.
- + hour * 60. * 60.
- + minute * 60.
- + second) * sign;
- return true;
-}
-
-static bool
-parse_DATETIME (struct data_in *i)
-{
- long day, month, year;
- long hour24;
- double second;
- long minute;
-
- if (!parse_leader (i)
- || !parse_day (i, &day)
- || !parse_date_delimiter (i)
- || !parse_month (i, &month)
- || !parse_date_delimiter (i)
- || !parse_year (i, &year)
- || !parse_time_delimiter (i)
- || !parse_hour24 (i, &hour24)
- || !parse_time_delimiter (i)
- || !parse_minute (i, &minute)
- || !parse_opt_second (i, &second)
- || !ymd_to_date (i, year, month, day, &i->v->f))
- return false;
-
- i->v->f += hour24 * 60. * 60. + minute * 60. + second;
- return true;
-}
-
-static bool
-parse_WKDAY (struct data_in *i)
-{
- long weekday;
-
- if (!parse_leader (i)
- || !parse_weekday (i, &weekday)
- || !parse_trailer (i))
- return false;
-
- i->v->f = weekday;
- return true;
-}
+ switch (ch)
+ {
+ case 'd':
+ error = count < 3 ? parse_day (i, &day) : parse_yday (i, &yday);
+ break;
+ case 'm':
+ error = parse_month (i, &month);
+ break;
+ case 'y':
+ {
+ size_t max_digits;
+ if (!c_isalpha (*template))
+ max_digits = SIZE_MAX;
+ else
+ {
+ if (ss_length (i->input) >= template_width + 2)
+ max_digits = 4;
+ else
+ max_digits = 2;
+ }
+ error = parse_year (i, &year, max_digits);
+ }
+ break;
+ case 'q':
+ error = parse_quarter (i, &month);
+ break;
+ case 'w':
+ error = parse_week (i, &yday);
+ break;
+ case 'D':
+ error = parse_time_units (i, 60. * 60. * 24., &time_sign, &time);
+ break;
+ case 'H':
+ error = parse_time_units (i, 60. * 60., &time_sign, &time);
+ break;
+ case 'M':
+ error = parse_minute_second (i, &time);
+ break;
+ case '-':
+ case '/':
+ case '.':
+ case 'X':
+ error = parse_date_delimiter (i);
+ break;
+ case ':':
+ error = parse_time_delimiter (i);
+ case ' ':
+ parse_spaces (i);
+ error = NULL;
+ break;
+ default:
+ assert (count == 1);
+ if (!ss_match_char (&i->input, c_toupper (ch))
+ && !ss_match_char (&i->input, c_tolower (ch)))
+ error = xasprintf (_("`%c' expected in date field."), ch);
+ else
+ error = NULL;
+ break;
+ }
+ if (error != NULL)
+ return error;
+ }
+ error = parse_trailer (i);
+ if (error != NULL)
+ return error;