Ruby  1.9.3p547(2014-05-14revision45962)
date_parse.c
Go to the documentation of this file.
1 /*
2  date_parse.c: Coded by Tadayoshi Funaba 2011,2012
3 */
4 
5 #include "ruby.h"
6 #include "ruby/encoding.h"
7 #include "ruby/re.h"
8 #include <ctype.h>
9 
10 #define sizeof_array(o) (sizeof o / sizeof o[0])
11 
12 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
13 #define f_add(x,y) rb_funcall(x, '+', 1, y)
14 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
15 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
16 #define f_div(x,y) rb_funcall(x, '/', 1, y)
17 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
18 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
19 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
20 
21 #define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
22 #define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
23 #define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
24 #define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
25 
26 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
27 
28 #define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
29 #define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
30 #define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
31 #define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
32 #define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
33 #define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
34 #define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
35 #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
36 #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
37 
38 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
39 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
40 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
41 
42 #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
43 #define str2num(s) rb_str_to_inum(s, 10, 0)
44 
45 static const char *abbr_days[] = {
46  "sun", "mon", "tue", "wed",
47  "thu", "fri", "sat"
48 };
49 
50 static const char *abbr_months[] = {
51  "jan", "feb", "mar", "apr", "may", "jun",
52  "jul", "aug", "sep", "oct", "nov", "dec"
53 };
54 
55 #define issign(c) ((c) == '-' || (c) == '+')
56 #define asp_string() rb_str_new(" ", 1)
57 
58 static void
59 s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
60 {
61  VALUE c = Qnil;
62 
63  if (TYPE(m) != T_STRING)
64  m = f_to_s(m);
65 
66  if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
67  VALUE oy = y;
68  VALUE om = m;
69  VALUE od = d;
70 
71  y = od;
72  m = oy;
73  d = om;
74  }
75 
76  if (NIL_P(y)) {
77  if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
78  y = d;
79  d = Qnil;
80  }
81  if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') {
82  y = d;
83  d = Qnil;
84  }
85  }
86 
87  if (!NIL_P(y)) {
88  const char *s, *bp, *ep;
89  size_t l;
90 
91  s = RSTRING_PTR(y);
92  while (!issign(*s) && !isdigit(*s))
93  s++;
94  bp = s;
95  if (issign(*s))
96  s++;
97  l = strspn(s, "0123456789");
98  ep = s + l;
99  if (*ep) {
100  y = d;
101  d = rb_str_new(bp, ep - bp);
102  }
103  }
104 
105  if (!NIL_P(m)) {
106  const char *s;
107 
108  s = RSTRING_PTR(m);
109  if (*s == '\'' || RSTRING_LEN(m) > 2) {
110  /* us -> be */
111  VALUE oy = y;
112  VALUE om = m;
113  VALUE od = d;
114 
115  y = om;
116  m = od;
117  d = oy;
118  }
119  }
120 
121  if (!NIL_P(d)) {
122  const char *s;
123 
124  s = RSTRING_PTR(d);
125  if (*s == '\'' || RSTRING_LEN(d) > 2) {
126  VALUE oy = y;
127  VALUE od = d;
128 
129  y = od;
130  d = oy;
131  }
132  }
133 
134  if (!NIL_P(y)) {
135  const char *s, *bp, *ep;
136  int sign = 0;
137  size_t l;
138  VALUE iy;
139 
140  s = RSTRING_PTR(y);
141  while (!issign(*s) && !isdigit(*s))
142  s++;
143  bp = s;
144  if (issign(*s)) {
145  s++;
146  sign = 1;
147  }
148  if (sign)
149  c = Qfalse;
150  l = strspn(s, "0123456789");
151  ep = s + l;
152  if (l > 2)
153  c = Qfalse;
154  {
155  char *buf;
156 
157  buf = ALLOCA_N(char, ep - bp + 1);
158  memcpy(buf, bp, ep - bp);
159  buf[ep - bp] = '\0';
160  iy = cstr2num(buf);
161  }
162  if (bc)
163  iy = f_add(f_negate(iy), INT2FIX(1));
164  set_hash("year", iy);
165  }
166 
167  if (!NIL_P(m)) {
168  const char *s, *bp, *ep;
169  size_t l;
170  VALUE im;
171 
172  s = RSTRING_PTR(m);
173  while (!isdigit(*s))
174  s++;
175  bp = s;
176  l = strspn(s, "0123456789");
177  ep = s + l;
178  {
179  char *buf;
180 
181  buf = ALLOCA_N(char, ep - bp + 1);
182  memcpy(buf, bp, ep - bp);
183  buf[ep - bp] = '\0';
184  im = cstr2num(buf);
185  }
186  set_hash("mon", im);
187  }
188 
189  if (!NIL_P(d)) {
190  const char *s, *bp, *ep;
191  size_t l;
192  VALUE id;
193 
194  s = RSTRING_PTR(d);
195  while (!isdigit(*s))
196  s++;
197  bp = s;
198  l = strspn(s, "0123456789");
199  ep = s + l;
200  {
201  char *buf;
202 
203  buf = ALLOCA_N(char, ep - bp + 1);
204  memcpy(buf, bp, ep - bp);
205  buf[ep - bp] = '\0';
206  id = cstr2num(buf);
207  }
208  set_hash("mday", id);
209  }
210 
211  if (!NIL_P(c))
212  set_hash("_comp", c);
213 }
214 
215 #define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
216 #define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
217 #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
218 #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
219 
220 static VALUE
221 regcomp(const char *source, long len, int opt)
222 {
223  VALUE pat;
224 
225  pat = rb_reg_new(source, len, opt);
227  return pat;
228 }
229 
230 #define REGCOMP(pat,opt) \
231 { \
232  if (NIL_P(pat)) \
233  pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
234 }
235 
236 #define REGCOMP_0(pat) REGCOMP(pat, 0)
237 #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
238 
239 #define MATCH(s,p,c) \
240 { \
241  return match(s, p, hash, c); \
242 }
243 
244 static int
245 match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
246 {
247  VALUE m;
248 
249  m = f_match(pat, str);
250 
251  if (NIL_P(m))
252  return 0;
253 
254  (*cb)(m, hash);
255 
256  return 1;
257 }
258 
259 #define SUBS(s,p,c) \
260 { \
261  return subs(s, p, hash, c); \
262 }
263 
264 static int
265 subs(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
266 {
267  VALUE m;
268 
269  m = f_match(pat, str);
270 
271  if (NIL_P(m))
272  return 0;
273 
274  {
275  VALUE be, en;
276 
277  be = f_begin(m, INT2FIX(0));
278  en = f_end(m, INT2FIX(0));
279  f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), asp_string());
280  (*cb)(m, hash);
281  }
282 
283  return 1;
284 }
285 
286 struct zone {
287  const char *name;
288  int offset;
289 };
290 
291 static struct zone zones_source[] = {
292  {"ut", 0*3600}, {"gmt", 0*3600}, {"est", -5*3600}, {"edt", -4*3600},
293  {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600},
294  {"pst", -8*3600}, {"pdt", -7*3600},
295  {"a", 1*3600}, {"b", 2*3600}, {"c", 3*3600}, {"d", 4*3600},
296  {"e", 5*3600}, {"f", 6*3600}, {"g", 7*3600}, {"h", 8*3600},
297  {"i", 9*3600}, {"k", 10*3600}, {"l", 11*3600}, {"m", 12*3600},
298  {"n", -1*3600}, {"o", -2*3600}, {"p", -3*3600}, {"q", -4*3600},
299  {"r", -5*3600}, {"s", -6*3600}, {"t", -7*3600}, {"u", -8*3600},
300  {"v", -9*3600}, {"w", -10*3600}, {"x", -11*3600}, {"y", -12*3600},
301  {"z", 0*3600},
302 
303  {"utc", 0*3600}, {"wet", 0*3600},
304  {"at", -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)},
305  {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600},
306  {"nst", -(3*3600+1800)},
307  {"ast", -4*3600}, {"clt", -4*3600},
308  {"akdt",-8*3600}, {"ydt", -8*3600},
309  {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600},
310  {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600},
311  {"nt", -11*3600},
312  {"idlw",-12*3600},
313  {"bst", 1*3600}, {"cet", 1*3600}, {"fwt", 1*3600}, {"met", 1*3600},
314  {"mewt", 1*3600}, {"mez", 1*3600}, {"swt", 1*3600}, {"wat", 1*3600},
315  {"west", 1*3600},
316  {"cest", 2*3600}, {"eet", 2*3600}, {"fst", 2*3600}, {"mest", 2*3600},
317  {"mesz", 2*3600}, {"sast", 2*3600}, {"sst", 2*3600},
318  {"bt", 3*3600}, {"eat", 3*3600}, {"eest", 3*3600}, {"msk", 3*3600},
319  {"msd", 4*3600}, {"zp4", 4*3600},
320  {"zp5", 5*3600}, {"ist", (5*3600+1800)},
321  {"zp6", 6*3600},
322  {"wast", 7*3600},
323  {"cct", 8*3600}, {"sgt", 8*3600}, {"wadt", 8*3600},
324  {"jst", 9*3600}, {"kst", 9*3600},
325  {"east",10*3600}, {"gst", 10*3600},
326  {"eadt",11*3600},
327  {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600},
328  {"nzdt",13*3600},
329 
330  {"afghanistan", 16200}, {"alaskan", -32400},
331  {"arab", 10800}, {"arabian", 14400},
332  {"arabic", 10800}, {"atlantic", -14400},
333  {"aus central", 34200}, {"aus eastern", 36000},
334  {"azores", -3600}, {"canada central", -21600},
335  {"cape verde", -3600}, {"caucasus", 14400},
336  {"cen. australia", 34200}, {"central america", -21600},
337  {"central asia", 21600}, {"central europe", 3600},
338  {"central european", 3600}, {"central pacific", 39600},
339  {"central", -21600}, {"china", 28800},
340  {"dateline", -43200}, {"e. africa", 10800},
341  {"e. australia", 36000}, {"e. europe", 7200},
342  {"e. south america", -10800}, {"eastern", -18000},
343  {"egypt", 7200}, {"ekaterinburg", 18000},
344  {"fiji", 43200}, {"fle", 7200},
345  {"greenland", -10800}, {"greenwich", 0},
346  {"gtb", 7200}, {"hawaiian", -36000},
347  {"india", 19800}, {"iran", 12600},
348  {"jerusalem", 7200}, {"korea", 32400},
349  {"mexico", -21600}, {"mid-atlantic", -7200},
350  {"mountain", -25200}, {"myanmar", 23400},
351  {"n. central asia", 21600}, {"nepal", 20700},
352  {"new zealand", 43200}, {"newfoundland", -12600},
353  {"north asia east", 28800}, {"north asia", 25200},
354  {"pacific sa", -14400}, {"pacific", -28800},
355  {"romance", 3600}, {"russian", 10800},
356  {"sa eastern", -10800}, {"sa pacific", -18000},
357  {"sa western", -14400}, {"samoa", -39600},
358  {"se asia", 25200}, {"malay peninsula", 28800},
359  {"south africa", 7200}, {"sri lanka", 21600},
360  {"taipei", 28800}, {"tasmania", 36000},
361  {"tokyo", 32400}, {"tonga", 46800},
362  {"us eastern", -18000}, {"us mountain", -25200},
363  {"vladivostok", 36000}, {"w. australia", 28800},
364  {"w. central africa", 3600}, {"w. europe", 3600},
365  {"west asia", 18000}, {"west pacific", 36000},
366  {"yakutsk", 32400}
367 };
368 
369 VALUE
371 {
372  VALUE offset = Qnil;
373 
374  long l, i;
375  char *s, *dest, *d;
376  int sp = 1;
377 
378  l = RSTRING_LEN(str);
379  s = RSTRING_PTR(str);
380 
381  dest = d = ALLOCA_N(char, l + 1);
382 
383  for (i = 0; i < l; i++) {
384  if (isspace(s[i]) || s[i] == '\0') {
385  if (!sp)
386  *d++ = ' ';
387  sp = 1;
388  }
389  else {
390  if (isalpha(s[i]))
391  *d++ = tolower(s[i]);
392  else
393  *d++ = s[i];
394  sp = 0;
395  }
396  }
397  if (d > dest) {
398  if (*(d - 1) == ' ')
399  --d;
400  *d = '\0';
401  }
402  str = rb_str_new2(dest);
403  {
404 #define STD " standard time"
405 #define DST " daylight time"
406  char *ss, *ds;
407  long sl, dl;
408  int dst = 0;
409 
410  sl = RSTRING_LEN(str) - (sizeof STD - 1);
411  ss = RSTRING_PTR(str) + sl;
412  dl = RSTRING_LEN(str) - (sizeof DST - 1);
413  ds = RSTRING_PTR(str) + dl;
414 
415  if (sl >= 0 && strcmp(ss, STD) == 0) {
416  str = rb_str_new(RSTRING_PTR(str), sl);
417  }
418  else if (dl >= 0 && strcmp(ds, DST) == 0) {
419  str = rb_str_new(RSTRING_PTR(str), dl);
420  dst = 1;
421  }
422 #undef STD
423 #undef DST
424  else {
425 #define DST " dst"
426  char *ds;
427  long dl;
428 
429  dl = RSTRING_LEN(str) - (sizeof DST - 1);
430  ds = RSTRING_PTR(str) + dl;
431 
432  if (dl >= 0 && strcmp(ds, DST) == 0) {
433  str = rb_str_new(RSTRING_PTR(str), dl);
434  dst = 1;
435  }
436 #undef DST
437  }
438  {
439  static VALUE zones = Qnil;
440 
441  if (NIL_P(zones)) {
442  int i;
443 
444  zones = rb_hash_new();
446  for (i = 0; i < (int)sizeof_array(zones_source); i++) {
447  VALUE name = rb_str_new2(zones_source[i].name);
448  VALUE offset = INT2FIX(zones_source[i].offset);
449  rb_hash_aset(zones, name, offset);
450  }
451  }
452 
453  offset = f_aref(zones, str);
454  if (!NIL_P(offset)) {
455  if (dst)
456  offset = f_add(offset, INT2FIX(3600));
457  goto ok;
458  }
459  }
460  {
461  char *s, *p;
462  VALUE sign;
463  VALUE hour = Qnil, min = Qnil, sec = Qnil;
464  VALUE str_orig;
465 
466  s = RSTRING_PTR(str);
467  str_orig = str;
468 
469  if (strncmp(s, "gmt", 3) == 0 ||
470  strncmp(s, "utc", 3) == 0)
471  s += 3;
472  if (issign(*s)) {
473  sign = rb_str_new(s, 1);
474  s++;
475 
476  str = rb_str_new2(s);
477 
478  if (p = strchr(s, ':')) {
479  hour = rb_str_new(s, p - s);
480  s = ++p;
481  if (p = strchr(s, ':')) {
482  min = rb_str_new(s, p - s);
483  s = ++p;
484  if (p = strchr(s, ':')) {
485  sec = rb_str_new(s, p - s);
486  }
487  else
488  sec = rb_str_new2(s);
489  }
490  else
491  min = rb_str_new2(s);
492  RB_GC_GUARD(str_orig);
493  goto num;
494  }
495  if (strpbrk(RSTRING_PTR(str), ",.")) {
496  char *a, *b;
497 
498  a = ALLOCA_N(char, RSTRING_LEN(str) + 1);
499  strcpy(a, RSTRING_PTR(str));
500  b = strpbrk(a, ",.");
501  *b = '\0';
502  b++;
503 
504  hour = cstr2num(a);
505  min = f_mul(rb_rational_new2
506  (cstr2num(b),
507  f_expt(INT2FIX(10),
508  LONG2NUM((long)strlen(b)))),
509  INT2FIX(60));
510  goto num;
511  }
512  {
513  const char *cs = RSTRING_PTR(str);
514  long cl = RSTRING_LEN(str);
515 
516  if (cl % 2) {
517  if (cl >= 1)
518  hour = rb_str_new(&cs[0], 1);
519  if (cl >= 3)
520  min = rb_str_new(&cs[1], 2);
521  if (cl >= 5)
522  min = rb_str_new(&cs[3], 2);
523  }
524  else {
525  if (cl >= 2)
526  hour = rb_str_new(&cs[0], 2);
527  if (cl >= 4)
528  min = rb_str_new(&cs[2], 2);
529  if (cl >= 6)
530  sec = rb_str_new(&cs[4], 2);
531  }
532  goto num;
533  }
534  num:
535  if (NIL_P(hour))
536  offset = INT2FIX(0);
537  else {
538  if (TYPE(hour) == T_STRING)
539  hour = str2num(hour);
540  offset = f_mul(hour, INT2FIX(3600));
541  }
542  if (!NIL_P(min)) {
543  if (TYPE(min) == T_STRING)
544  min = str2num(min);
545  offset = f_add(offset, f_mul(min, INT2FIX(60)));
546  }
547  if (!NIL_P(sec))
548  offset = f_add(offset, str2num(sec));
549  if (!NIL_P(sign) &&
550  RSTRING_LEN(sign) == 1 &&
551  *RSTRING_PTR(sign) == '-')
552  offset = f_negate(offset);
553  }
554  }
555  }
556  RB_GC_GUARD(str);
557  ok:
558  return offset;
559 }
560 
561 static int
563 {
564  int i;
565 
566  for (i = 0; i < (int)sizeof_array(abbr_days); i++)
567  if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
568  break;
569  return i;
570 }
571 
572 static int
574 {
575  int i;
576 
577  for (i = 0; i < (int)sizeof_array(abbr_months); i++)
578  if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
579  break;
580  return i + 1;
581 }
582 
583 static int
585 {
586  VALUE s;
587 
588  s = rb_reg_nth_match(1, m);
589  set_hash("wday", INT2FIX(day_num(s)));
590  return 1;
591 }
592 
593 static int
595 {
596  static const char pat_source[] = "\\b(" ABBR_DAYS ")[^-\\d\\s]*";
597  static VALUE pat = Qnil;
598 
599  REGCOMP_I(pat);
600  SUBS(str, pat, parse_day_cb);
601 }
602 
603 static int
605 {
606  VALUE h, min, s, f, p;
607 
608  h = rb_reg_nth_match(1, m);
609  h = str2num(h);
610 
611  min = rb_reg_nth_match(2, m);
612  if (!NIL_P(min))
613  min = str2num(min);
614 
615  s = rb_reg_nth_match(3, m);
616  if (!NIL_P(s))
617  s = str2num(s);
618 
619  f = rb_reg_nth_match(4, m);
620 
621  if (!NIL_P(f))
622  f = rb_rational_new2(str2num(f),
623  f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
624 
625  p = rb_reg_nth_match(5, m);
626 
627  if (!NIL_P(p)) {
628  int ih = NUM2INT(h);
629  ih %= 12;
630  if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
631  ih += 12;
632  h = INT2FIX(ih);
633  }
634 
635  set_hash("hour", h);
636  if (!NIL_P(min))
637  set_hash("min", min);
638  if (!NIL_P(s))
639  set_hash("sec", s);
640  if (!NIL_P(f))
641  set_hash("sec_fraction", f);
642 
643  return 1;
644 }
645 
646 static int
648 {
649  static const char pat_source[] =
650  "\\A(\\d+)h?"
651  "(?:\\s*:?\\s*(\\d+)m?"
652  "(?:"
653  "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
654  ")?"
655  ")?"
656  "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
657  static VALUE pat = Qnil;
658  VALUE s1, s2;
659 
660  s1 = rb_reg_nth_match(1, m);
661  s2 = rb_reg_nth_match(2, m);
662 
663  if (!NIL_P(s2))
664  set_hash("zone", s2);
665 
666  REGCOMP_I(pat);
667 
668  {
669  VALUE m = f_match(pat, s1);
670 
671  if (NIL_P(m))
672  return 0;
673  parse_time2_cb(m, hash);
674  }
675 
676  return 1;
677 }
678 
679 static int
681 {
682  static const char pat_source[] =
683  "("
684  "(?:"
685  "\\d+\\s*:\\s*\\d+"
686  "(?:"
687  "\\s*:\\s*\\d+(?:[,.]\\d*)?"
688  ")?"
689  "|"
690  "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
691  ")"
692  "(?:"
693  "\\s*"
694  "[ap](?:m\\b|\\.m\\.)"
695  ")?"
696  "|"
697  "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
698  ")"
699  "(?:"
700  "\\s*"
701  "("
702  "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
703  "|"
704  "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
705  "|"
706  "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
707  ")"
708  ")?";
709  static VALUE pat = Qnil;
710 
711  REGCOMP_I(pat);
712  SUBS(str, pat, parse_time_cb);
713 }
714 
715 static int
717 {
718  VALUE y, mon, d, b;
719 
720  d = rb_reg_nth_match(1, m);
721  mon = rb_reg_nth_match(2, m);
722  b = rb_reg_nth_match(3, m);
723  y = rb_reg_nth_match(4, m);
724 
725  mon = INT2FIX(mon_num(mon));
726 
727  s3e(hash, y, mon, d, !NIL_P(b) &&
728  (*RSTRING_PTR(b) == 'B' ||
729  *RSTRING_PTR(b) == 'b'));
730  return 1;
731 }
732 
733 static int
734 parse_eu(VALUE str, VALUE hash)
735 {
736  static const char pat_source[] =
737  "'?(\\d+)[^-\\d\\s]*"
738  "\\s*"
739  "(" ABBR_MONTHS ")[^-\\d\\s']*"
740  "(?:"
741  "\\s*"
742  "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
743  "\\s*"
744  "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
745  ")?";
746  static VALUE pat = Qnil;
747 
748  REGCOMP_I(pat);
749  SUBS(str, pat, parse_eu_cb);
750 }
751 
752 static int
754 {
755  VALUE y, mon, d, b;
756 
757  mon = rb_reg_nth_match(1, m);
758  d = rb_reg_nth_match(2, m);
759  b = rb_reg_nth_match(3, m);
760  y = rb_reg_nth_match(4, m);
761 
762  mon = INT2FIX(mon_num(mon));
763 
764  s3e(hash, y, mon, d, !NIL_P(b) &&
765  (*RSTRING_PTR(b) == 'B' ||
766  *RSTRING_PTR(b) == 'b'));
767  return 1;
768 }
769 
770 static int
771 parse_us(VALUE str, VALUE hash)
772 {
773  static const char pat_source[] =
774  "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
775  "\\s*"
776  "('?\\d+)[^-\\d\\s']*"
777  "(?:"
778  "\\s*"
779  "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
780  "\\s*"
781  "('?-?\\d+)"
782  ")?";
783  static VALUE pat = Qnil;
784 
785  REGCOMP_I(pat);
786  SUBS(str, pat, parse_us_cb);
787 }
788 
789 static int
791 {
792  VALUE y, mon, d;
793 
794  y = rb_reg_nth_match(1, m);
795  mon = rb_reg_nth_match(2, m);
796  d = rb_reg_nth_match(3, m);
797 
798  s3e(hash, y, mon, d, 0);
799  return 1;
800 }
801 
802 static int
804 {
805  static const char pat_source[] = "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)";
806  static VALUE pat = Qnil;
807 
808  REGCOMP_0(pat);
809  SUBS(str, pat, parse_iso_cb);
810 }
811 
812 static int
814 {
815  VALUE y, w, d;
816 
817  y = rb_reg_nth_match(1, m);
818  w = rb_reg_nth_match(2, m);
819  d = rb_reg_nth_match(3, m);
820 
821  if (!NIL_P(y))
822  set_hash("cwyear", str2num(y));
823  set_hash("cweek", str2num(w));
824  if (!NIL_P(d))
825  set_hash("cwday", str2num(d));
826 
827  return 1;
828 }
829 
830 static int
832 {
833  static const char pat_source[] =
834  "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b";
835  static VALUE pat = Qnil;
836 
837  REGCOMP_I(pat);
838  SUBS(str, pat, parse_iso21_cb);
839 }
840 
841 static int
843 {
844  VALUE d;
845 
846  d = rb_reg_nth_match(1, m);
847  set_hash("cwday", str2num(d));
848  return 1;
849 }
850 
851 static int
853 {
854  static const char pat_source[] = "-w-(\\d)\\b";
855  static VALUE pat = Qnil;
856 
857  REGCOMP_I(pat);
858  SUBS(str, pat, parse_iso22_cb);
859 }
860 
861 static int
863 {
864  VALUE mon, d;
865 
866  mon = rb_reg_nth_match(1, m);
867  d = rb_reg_nth_match(2, m);
868 
869  if (!NIL_P(mon))
870  set_hash("mon", str2num(mon));
871  set_hash("mday", str2num(d));
872 
873  return 1;
874 }
875 
876 static int
878 {
879  static const char pat_source[] = "--(\\d{2})?-(\\d{2})\\b";
880  static VALUE pat = Qnil;
881 
882  REGCOMP_0(pat);
883  SUBS(str, pat, parse_iso23_cb);
884 }
885 
886 static int
888 {
889  VALUE mon, d;
890 
891  mon = rb_reg_nth_match(1, m);
892  d = rb_reg_nth_match(2, m);
893 
894  set_hash("mon", str2num(mon));
895  if (!NIL_P(d))
896  set_hash("mday", str2num(d));
897 
898  return 1;
899 }
900 
901 static int
903 {
904  static const char pat_source[] = "--(\\d{2})(\\d{2})?\\b";
905  static VALUE pat = Qnil;
906 
907  REGCOMP_0(pat);
908  SUBS(str, pat, parse_iso24_cb);
909 }
910 
911 static int
913 {
914  VALUE y, d;
915 
916  y = rb_reg_nth_match(1, m);
917  d = rb_reg_nth_match(2, m);
918 
919  set_hash("year", str2num(y));
920  set_hash("yday", str2num(d));
921 
922  return 1;
923 }
924 
925 static int
927 {
928  static const char pat0_source[] = "[,.](\\d{2}|\\d{4})-\\d{3}\\b";
929  static VALUE pat0 = Qnil;
930  static const char pat_source[] = "\\b(\\d{2}|\\d{4})-(\\d{3})\\b";
931  static VALUE pat = Qnil;
932 
933  REGCOMP_0(pat0);
934  REGCOMP_0(pat);
935 
936  if (!NIL_P(f_match(pat0, str)))
937  return 0;
938  SUBS(str, pat, parse_iso25_cb);
939 }
940 
941 static int
943 {
944  VALUE d;
945 
946  d = rb_reg_nth_match(1, m);
947  set_hash("yday", str2num(d));
948 
949  return 1;
950 }
951 static int
953 {
954  static const char pat0_source[] = "\\d-\\d{3}\\b";
955  static VALUE pat0 = Qnil;
956  static const char pat_source[] = "\\b-(\\d{3})\\b";
957  static VALUE pat = Qnil;
958 
959  REGCOMP_0(pat0);
960  REGCOMP_0(pat);
961 
962  if (!NIL_P(f_match(pat0, str)))
963  return 0;
964  SUBS(str, pat, parse_iso26_cb);
965 }
966 
967 static int
969 {
970  if (parse_iso21(str, hash))
971  goto ok;
972  if (parse_iso22(str, hash))
973  goto ok;
974  if (parse_iso23(str, hash))
975  goto ok;
976  if (parse_iso24(str, hash))
977  goto ok;
978  if (parse_iso25(str, hash))
979  goto ok;
980  if (parse_iso26(str, hash))
981  goto ok;
982  return 0;
983 
984  ok:
985  return 1;
986 }
987 
988 static int
989 gengo(int c)
990 {
991  int e;
992 
993  switch (c) {
994  case 'M': case 'm': e = 1867; break;
995  case 'T': case 't': e = 1911; break;
996  case 'S': case 's': e = 1925; break;
997  case 'H': case 'h': e = 1988; break;
998  default: e = 0; break;
999  }
1000  return e;
1001 }
1002 
1003 static int
1005 {
1006  VALUE e, y, mon, d;
1007  int ep;
1008 
1009  e = rb_reg_nth_match(1, m);
1010  y = rb_reg_nth_match(2, m);
1011  mon = rb_reg_nth_match(3, m);
1012  d = rb_reg_nth_match(4, m);
1013 
1014  ep = gengo(*RSTRING_PTR(e));
1015 
1016  set_hash("year", f_add(str2num(y), INT2FIX(ep)));
1017  set_hash("mon", str2num(mon));
1018  set_hash("mday", str2num(d));
1019 
1020  return 1;
1021 }
1022 
1023 static int
1025 {
1026  static const char pat_source[] = "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)";
1027  static VALUE pat = Qnil;
1028 
1029  REGCOMP_I(pat);
1030  SUBS(str, pat, parse_jis_cb);
1031 }
1032 
1033 static int
1035 {
1036  VALUE y, mon, d;
1037 
1038  d = rb_reg_nth_match(1, m);
1039  mon = rb_reg_nth_match(2, m);
1040  y = rb_reg_nth_match(3, m);
1041 
1042  mon = INT2FIX(mon_num(mon));
1043 
1044  s3e(hash, y, mon, d, 0);
1045  return 1;
1046 }
1047 
1048 static int
1050 {
1051  static const char pat_source[] =
1052  "('?-?\\d+)-(" ABBR_MONTHS ")[^-]*"
1053  "-('?-?\\d+)";
1054  static VALUE pat = Qnil;
1055 
1056  REGCOMP_I(pat);
1057  SUBS(str, pat, parse_vms11_cb);
1058 }
1059 
1060 static int
1062 {
1063  VALUE y, mon, d;
1064 
1065  mon = rb_reg_nth_match(1, m);
1066  d = rb_reg_nth_match(2, m);
1067  y = rb_reg_nth_match(3, m);
1068 
1069  mon = INT2FIX(mon_num(mon));
1070 
1071  s3e(hash, y, mon, d, 0);
1072  return 1;
1073 }
1074 
1075 static int
1077 {
1078  static const char pat_source[] =
1079  "\\b(" ABBR_MONTHS ")[^-]*"
1080  "-('?-?\\d+)(?:-('?-?\\d+))?";
1081  static VALUE pat = Qnil;
1082 
1083  REGCOMP_I(pat);
1084  SUBS(str, pat, parse_vms12_cb);
1085 }
1086 
1087 static int
1089 {
1090  if (parse_vms11(str, hash))
1091  goto ok;
1092  if (parse_vms12(str, hash))
1093  goto ok;
1094  return 0;
1095 
1096  ok:
1097  return 1;
1098 }
1099 
1100 static int
1102 {
1103  VALUE y, mon, d;
1104 
1105  y = rb_reg_nth_match(1, m);
1106  mon = rb_reg_nth_match(2, m);
1107  d = rb_reg_nth_match(3, m);
1108 
1109  s3e(hash, y, mon, d, 0);
1110  return 1;
1111 }
1112 
1113 static int
1115 {
1116  static const char pat_source[] =
1117  "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?";
1118  static VALUE pat = Qnil;
1119 
1120  REGCOMP_I(pat);
1121  SUBS(str, pat, parse_sla_cb);
1122 }
1123 
1124 static int
1126 {
1127  VALUE y, mon, d;
1128 
1129  y = rb_reg_nth_match(1, m);
1130  mon = rb_reg_nth_match(2, m);
1131  d = rb_reg_nth_match(3, m);
1132 
1133  s3e(hash, y, mon, d, 0);
1134  return 1;
1135 }
1136 
1137 static int
1139 {
1140  static const char pat_source[] =
1141  "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)";
1142  static VALUE pat = Qnil;
1143 
1144  REGCOMP_I(pat);
1145  SUBS(str, pat, parse_dot_cb);
1146 }
1147 
1148 static int
1150 {
1151  VALUE y;
1152 
1153  y = rb_reg_nth_match(1, m);
1154  set_hash("year", str2num(y));
1155  return 1;
1156 }
1157 
1158 static int
1160 {
1161  static const char pat_source[] = "'(\\d+)\\b";
1162  static VALUE pat = Qnil;
1163 
1164  REGCOMP_0(pat);
1165  SUBS(str, pat, parse_year_cb);
1166 }
1167 
1168 static int
1170 {
1171  VALUE mon;
1172 
1173  mon = rb_reg_nth_match(1, m);
1174  set_hash("mon", INT2FIX(mon_num(mon)));
1175  return 1;
1176 }
1177 
1178 static int
1180 {
1181  static const char pat_source[] = "\\b(" ABBR_MONTHS ")\\S*";
1182  static VALUE pat = Qnil;
1183 
1184  REGCOMP_I(pat);
1185  SUBS(str, pat, parse_mon_cb);
1186 }
1187 
1188 static int
1190 {
1191  VALUE d;
1192 
1193  d = rb_reg_nth_match(1, m);
1194  set_hash("mday", str2num(d));
1195  return 1;
1196 }
1197 
1198 static int
1200 {
1201  static const char pat_source[] = "(\\d+)(st|nd|rd|th)\\b";
1202  static VALUE pat = Qnil;
1203 
1204  REGCOMP_I(pat);
1205  SUBS(str, pat, parse_mday_cb);
1206 }
1207 
1208 static int
1209 n2i(const char *s, long f, long w)
1210 {
1211  long e, i;
1212  int v;
1213 
1214  e = f + w;
1215  v = 0;
1216  for (i = f; i < e; i++) {
1217  v *= 10;
1218  v += s[i] - '0';
1219  }
1220  return v;
1221 }
1222 
1223 static int
1225 {
1226  VALUE s1, s2, s3, s4, s5;
1227  const char *cs2, *cs3, *cs5;
1228  long l2, l3, l4, l5;
1229 
1230  s1 = rb_reg_nth_match(1, m);
1231  s2 = rb_reg_nth_match(2, m);
1232  s3 = rb_reg_nth_match(3, m);
1233  s4 = rb_reg_nth_match(4, m);
1234  s5 = rb_reg_nth_match(5, m);
1235 
1236  cs2 = RSTRING_PTR(s2);
1237  l2 = RSTRING_LEN(s2);
1238 
1239  switch (l2) {
1240  case 2:
1241  if (NIL_P(s3) && !NIL_P(s4))
1242  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1243  else
1244  set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
1245  break;
1246  case 4:
1247  if (NIL_P(s3) && !NIL_P(s4)) {
1248  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1249  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1250  }
1251  else {
1252  set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
1253  set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
1254  }
1255  break;
1256  case 6:
1257  if (NIL_P(s3) && !NIL_P(s4)) {
1258  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1259  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1260  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1261  }
1262  else {
1263  int y = n2i(cs2, 0, 2);
1264  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1265  y = -y;
1266  set_hash("year", INT2FIX(y));
1267  set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
1268  set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
1269  }
1270  break;
1271  case 8:
1272  case 10:
1273  case 12:
1274  case 14:
1275  if (NIL_P(s3) && !NIL_P(s4)) {
1276  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1277  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1278  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1279  set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
1280  if (l2 >= 10)
1281  set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
1282  if (l2 == 12) {
1283  int y = n2i(cs2, l2-12, 2);
1284  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1285  y = -y;
1286  set_hash("year", INT2FIX(y));
1287  }
1288  if (l2 == 14) {
1289  int y = n2i(cs2, l2-14, 4);
1290  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1291  y = -y;
1292  set_hash("year", INT2FIX(y));
1293  set_hash("_comp", Qfalse);
1294  }
1295  }
1296  else {
1297  int y = n2i(cs2, 0, 4);
1298  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1299  y = -y;
1300  set_hash("year", INT2FIX(y));
1301  set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
1302  set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
1303  if (l2 >= 10)
1304  set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
1305  if (l2 >= 12)
1306  set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
1307  if (l2 >= 14)
1308  set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
1309  set_hash("_comp", Qfalse);
1310  }
1311  break;
1312  case 3:
1313  if (NIL_P(s3) && !NIL_P(s4)) {
1314  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1315  set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
1316  }
1317  else
1318  set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
1319  break;
1320  case 5:
1321  if (NIL_P(s3) && !NIL_P(s4)) {
1322  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1323  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1324  set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
1325  }
1326  else {
1327  int y = n2i(cs2, 0, 2);
1328  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1329  y = -y;
1330  set_hash("year", INT2FIX(y));
1331  set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
1332  }
1333  break;
1334  case 7:
1335  if (NIL_P(s3) && !NIL_P(s4)) {
1336  set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1337  set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1338  set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1339  set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
1340  }
1341  else {
1342  int y = n2i(cs2, 0, 4);
1343  if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1344  y = -y;
1345  set_hash("year", INT2FIX(y));
1346  set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
1347  }
1348  break;
1349  }
1350  RB_GC_GUARD(s2);
1351  if (!NIL_P(s3)) {
1352  cs3 = RSTRING_PTR(s3);
1353  l3 = RSTRING_LEN(s3);
1354 
1355  if (!NIL_P(s4)) {
1356  switch (l3) {
1357  case 2:
1358  case 4:
1359  case 6:
1360  set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
1361  if (l3 >= 4)
1362  set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
1363  if (l3 >= 6)
1364  set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
1365  break;
1366  }
1367  }
1368  else {
1369  switch (l3) {
1370  case 2:
1371  case 4:
1372  case 6:
1373  set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
1374  if (l3 >= 4)
1375  set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
1376  if (l3 >= 6)
1377  set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
1378  break;
1379  }
1380  }
1381  RB_GC_GUARD(s3);
1382  }
1383  if (!NIL_P(s4)) {
1384  l4 = RSTRING_LEN(s4);
1385 
1386  set_hash("sec_fraction",
1388  f_expt(INT2FIX(10), LONG2NUM(l4))));
1389  }
1390  if (!NIL_P(s5)) {
1391  cs5 = RSTRING_PTR(s5);
1392  l5 = RSTRING_LEN(s5);
1393 
1394  set_hash("zone", s5);
1395 
1396  if (*cs5 == '[') {
1397  char *buf = ALLOCA_N(char, l5 + 1);
1398  char *s1, *s2, *s3;
1399  VALUE zone;
1400 
1401  memcpy(buf, cs5, l5);
1402  buf[l5 - 1] = '\0';
1403 
1404  s1 = buf + 1;
1405  s2 = strchr(buf, ':');
1406  if (s2) {
1407  *s2 = '\0';
1408  s2++;
1409  }
1410  if (s2)
1411  s3 = s2;
1412  else
1413  s3 = s1;
1414  zone = rb_str_new2(s3);
1415  set_hash("zone", zone);
1416  if (isdigit(*s1))
1417  *--s1 = '+';
1418  set_hash("offset", date_zone_to_diff(rb_str_new2(s1)));
1419  }
1420  RB_GC_GUARD(s5);
1421  }
1422 
1423  return 1;
1424 }
1425 
1426 static int
1428 {
1429  static const char pat_source[] =
1430  "([-+]?)(\\d{2,14})"
1431  "(?:"
1432  "\\s*"
1433  "t?"
1434  "\\s*"
1435  "(\\d{2,6})?(?:[,.](\\d*))?"
1436  ")?"
1437  "(?:"
1438  "\\s*"
1439  "("
1440  "z\\b"
1441  "|"
1442  "[-+]\\d{1,4}\\b"
1443  "|"
1444  "\\[[-+]?\\d[^\\]]*\\]"
1445  ")"
1446  ")?";
1447  static VALUE pat = Qnil;
1448 
1449  REGCOMP_I(pat);
1450  SUBS(str, pat, parse_ddd_cb);
1451 }
1452 
1453 static int
1455 {
1456  VALUE y;
1457 
1458  y = ref_hash("year");
1459  if (!NIL_P(y))
1460  set_hash("year", f_add(f_negate(y), INT2FIX(1)));
1461 
1462  return 1;
1463 }
1464 
1465 static int
1467 {
1468  static const char pat_source[] =
1469  "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
1470  static VALUE pat = Qnil;
1471 
1472  REGCOMP_I(pat);
1473  SUBS(str, pat, parse_bc_cb);
1474 }
1475 
1476 static int
1478 {
1479  VALUE s, n;
1480 
1481  s = rb_reg_nth_match(1, m);
1482 
1483  if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
1484  n = str2num(s);
1485  if (f_ge_p(n, INT2FIX(1)) &&
1486  f_le_p(n, INT2FIX(31)))
1487  set_hash("mday", n);
1488  }
1489  if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
1490  n = str2num(s);
1491  if (f_ge_p(n, INT2FIX(0)) &&
1492  f_le_p(n, INT2FIX(24)))
1493  set_hash("hour", n);
1494  }
1495 
1496  return 1;
1497 }
1498 
1499 static int
1501 {
1502  static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
1503  static VALUE pat = Qnil;
1504 
1505  REGCOMP_I(pat);
1506  SUBS(str, pat, parse_frag_cb);
1507 }
1508 
1509 #define HAVE_ALPHA (1<<0)
1510 #define HAVE_DIGIT (1<<1)
1511 #define HAVE_DASH (1<<2)
1512 #define HAVE_DOT (1<<3)
1513 #define HAVE_SLASH (1<<4)
1514 
1515 static unsigned
1517 {
1518  unsigned flags;
1519  long i;
1520 
1521  flags = 0;
1522  for (i = 0; i < RSTRING_LEN(s); i++) {
1523  if (isalpha(RSTRING_PTR(s)[i]))
1524  flags |= HAVE_ALPHA;
1525  if (isdigit(RSTRING_PTR(s)[i]))
1526  flags |= HAVE_DIGIT;
1527  if (RSTRING_PTR(s)[i] == '-')
1528  flags |= HAVE_DASH;
1529  if (RSTRING_PTR(s)[i] == '.')
1530  flags |= HAVE_DOT;
1531  if (RSTRING_PTR(s)[i] == '/')
1532  flags |= HAVE_SLASH;
1533  }
1534  return flags;
1535 }
1536 
1537 #define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
1538 
1539 VALUE
1541 {
1542  VALUE backref, hash;
1543 
1544  backref = rb_backref_get();
1545  rb_match_busy(backref);
1546 
1547  {
1548  static const char pat_source[] = "[^-+',./:@[:alnum:]\\[\\]]+";
1549  static VALUE pat = Qnil;
1550 
1551  REGCOMP_0(pat);
1552  str = rb_str_dup(str);
1553  f_gsub_bang(str, pat, asp_string());
1554  }
1555 
1556  hash = rb_hash_new();
1557  set_hash("_comp", comp);
1558 
1559  if (HAVE_ELEM_P(HAVE_ALPHA))
1560  parse_day(str, hash);
1561  if (HAVE_ELEM_P(HAVE_DIGIT))
1562  parse_time(str, hash);
1563 
1565  if (parse_eu(str, hash))
1566  goto ok;
1568  if (parse_us(str, hash))
1569  goto ok;
1571  if (parse_iso(str, hash))
1572  goto ok;
1574  if (parse_jis(str, hash))
1575  goto ok;
1577  if (parse_vms(str, hash))
1578  goto ok;
1580  if (parse_sla(str, hash))
1581  goto ok;
1583  if (parse_dot(str, hash))
1584  goto ok;
1585  if (HAVE_ELEM_P(HAVE_DIGIT))
1586  if (parse_iso2(str, hash))
1587  goto ok;
1588  if (HAVE_ELEM_P(HAVE_DIGIT))
1589  if (parse_year(str, hash))
1590  goto ok;
1591  if (HAVE_ELEM_P(HAVE_ALPHA))
1592  if (parse_mon(str, hash))
1593  goto ok;
1594  if (HAVE_ELEM_P(HAVE_DIGIT))
1595  if (parse_mday(str, hash))
1596  goto ok;
1597  if (HAVE_ELEM_P(HAVE_DIGIT))
1598  if (parse_ddd(str, hash))
1599  goto ok;
1600 
1601  ok:
1602  if (HAVE_ELEM_P(HAVE_ALPHA))
1603  parse_bc(str, hash);
1604  if (HAVE_ELEM_P(HAVE_DIGIT))
1605  parse_frag(str, hash);
1606 
1607  {
1608  if (RTEST(ref_hash("_comp"))) {
1609  VALUE y;
1610 
1611  y = ref_hash("cwyear");
1612  if (!NIL_P(y))
1613  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
1614  if (f_ge_p(y, INT2FIX(69)))
1615  set_hash("cwyear", f_add(y, INT2FIX(1900)));
1616  else
1617  set_hash("cwyear", f_add(y, INT2FIX(2000)));
1618  }
1619  y = ref_hash("year");
1620  if (!NIL_P(y))
1621  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
1622  if (f_ge_p(y, INT2FIX(69)))
1623  set_hash("year", f_add(y, INT2FIX(1900)));
1624  else
1625  set_hash("year", f_add(y, INT2FIX(2000)));
1626  }
1627  }
1628  }
1629 
1630  del_hash("_comp");
1631 
1632  {
1633  VALUE zone = ref_hash("zone");
1634  if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
1635  set_hash("offset", date_zone_to_diff(zone));
1636  }
1637 
1638  rb_backref_set(backref);
1639 
1640  return hash;
1641 }
1642 
1643 static VALUE
1645 {
1646  if (f_ge_p(y, INT2FIX(69)))
1647  return f_add(y, INT2FIX(1900));
1648  return f_add(y, INT2FIX(2000));
1649 }
1650 
1651 static VALUE
1653 {
1654  if (f_ge_p(y, INT2FIX(50)))
1655  return f_add(y, INT2FIX(1900));
1656  return f_add(y, INT2FIX(2000));
1657 }
1658 
1659 static VALUE
1661 {
1662  return rb_rational_new2(str2num(f),
1663  f_expt(INT2FIX(10),
1664  LONG2NUM(RSTRING_LEN(f))));
1665 }
1666 
1667 #define SNUM 14
1668 
1669 static int
1671 {
1672  VALUE s[SNUM + 1], y;
1673 
1674  {
1675  int i;
1676  s[0] = Qnil;
1677  for (i = 1; i <= SNUM; i++)
1678  s[i] = rb_reg_nth_match(i, m);
1679  }
1680 
1681  if (!NIL_P(s[3])) {
1682  set_hash("mday", str2num(s[3]));
1683  if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
1684  y = str2num(s[1]);
1685  if (RSTRING_LEN(s[1]) < 4)
1686  y = comp_year69(y);
1687  set_hash("year", y);
1688  }
1689  if (NIL_P(s[2])) {
1690  if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
1691  return 0;
1692  }
1693  else
1694  set_hash("mon", str2num(s[2]));
1695  }
1696  else if (!NIL_P(s[5])) {
1697  set_hash("yday", str2num(s[5]));
1698  if (!NIL_P(s[4])) {
1699  y = str2num(s[4]);
1700  if (RSTRING_LEN(s[4]) < 4)
1701  y = comp_year69(y);
1702  set_hash("year", y);
1703  }
1704  }
1705  else if (!NIL_P(s[8])) {
1706  set_hash("cweek", str2num(s[7]));
1707  set_hash("cwday", str2num(s[8]));
1708  if (!NIL_P(s[6])) {
1709  y = str2num(s[6]);
1710  if (RSTRING_LEN(s[6]) < 4)
1711  y = comp_year69(y);
1712  set_hash("cwyear", y);
1713  }
1714  }
1715  else if (!NIL_P(s[9])) {
1716  set_hash("cwday", str2num(s[9]));
1717  }
1718  if (!NIL_P(s[10])) {
1719  set_hash("hour", str2num(s[10]));
1720  set_hash("min", str2num(s[11]));
1721  if (!NIL_P(s[12]))
1722  set_hash("sec", str2num(s[12]));
1723  }
1724  if (!NIL_P(s[13])) {
1725  set_hash("sec_fraction", sec_fraction(s[13]));
1726  }
1727  if (!NIL_P(s[14])) {
1728  set_hash("zone", s[14]);
1729  set_hash("offset", date_zone_to_diff(s[14]));
1730  }
1731 
1732  return 1;
1733 }
1734 
1735 static int
1737 {
1738  static const char pat_source[] =
1739  "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|"
1740  "([-+]?\\d{2,})?-(\\d{3})|"
1741  "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
1742  "-w-(\\d))"
1743  "(?:t"
1744  "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
1745  "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
1746  static VALUE pat = Qnil;
1747 
1748  REGCOMP_I(pat);
1749  MATCH(str, pat, iso8601_ext_datetime_cb);
1750 }
1751 
1752 #undef SNUM
1753 #define SNUM 17
1754 
1755 static int
1757 {
1758  VALUE s[SNUM + 1], y;
1759 
1760  {
1761  int i;
1762  s[0] = Qnil;
1763  for (i = 1; i <= SNUM; i++)
1764  s[i] = rb_reg_nth_match(i, m);
1765  }
1766 
1767  if (!NIL_P(s[3])) {
1768  set_hash("mday", str2num(s[3]));
1769  if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
1770  y = str2num(s[1]);
1771  if (RSTRING_LEN(s[1]) < 4)
1772  y = comp_year69(y);
1773  set_hash("year", y);
1774  }
1775  if (*RSTRING_PTR(s[2]) == '-') {
1776  if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
1777  return 0;
1778  }
1779  else
1780  set_hash("mon", str2num(s[2]));
1781  }
1782  else if (!NIL_P(s[5])) {
1783  set_hash("yday", str2num(s[5]));
1784  y = str2num(s[4]);
1785  if (RSTRING_LEN(s[4]) < 4)
1786  y = comp_year69(y);
1787  set_hash("year", y);
1788  }
1789  else if (!NIL_P(s[6])) {
1790  set_hash("yday", str2num(s[6]));
1791  }
1792  else if (!NIL_P(s[9])) {
1793  set_hash("cweek", str2num(s[8]));
1794  set_hash("cwday", str2num(s[9]));
1795  y = str2num(s[7]);
1796  if (RSTRING_LEN(s[7]) < 4)
1797  y = comp_year69(y);
1798  set_hash("cwyear", y);
1799  }
1800  else if (!NIL_P(s[11])) {
1801  set_hash("cweek", str2num(s[10]));
1802  set_hash("cwday", str2num(s[11]));
1803  }
1804  else if (!NIL_P(s[12])) {
1805  set_hash("cwday", str2num(s[12]));
1806  }
1807  if (!NIL_P(s[13])) {
1808  set_hash("hour", str2num(s[13]));
1809  set_hash("min", str2num(s[14]));
1810  if (!NIL_P(s[15]))
1811  set_hash("sec", str2num(s[15]));
1812  }
1813  if (!NIL_P(s[16])) {
1814  set_hash("sec_fraction", sec_fraction(s[16]));
1815  }
1816  if (!NIL_P(s[17])) {
1817  set_hash("zone", s[17]);
1818  set_hash("offset", date_zone_to_diff(s[17]));
1819  }
1820 
1821  return 1;
1822 }
1823 
1824 static int
1826 {
1827  static const char pat_source[] =
1828  "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
1829  "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
1830  "-(\\d{3})|"
1831  "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
1832  "-w(\\d{2})(\\d)|"
1833  "-w-(\\d))"
1834  "(?:t?"
1835  "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
1836  "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
1837  static VALUE pat = Qnil;
1838 
1839  REGCOMP_I(pat);
1840  MATCH(str, pat, iso8601_bas_datetime_cb);
1841 }
1842 
1843 #undef SNUM
1844 #define SNUM 5
1845 
1846 static int
1848 {
1849  VALUE s[SNUM + 1];
1850 
1851  {
1852  int i;
1853  s[0] = Qnil;
1854  for (i = 1; i <= SNUM; i++)
1855  s[i] = rb_reg_nth_match(i, m);
1856  }
1857 
1858  set_hash("hour", str2num(s[1]));
1859  set_hash("min", str2num(s[2]));
1860  if (!NIL_P(s[3]))
1861  set_hash("sec", str2num(s[3]));
1862  if (!NIL_P(s[4]))
1863  set_hash("sec_fraction", sec_fraction(s[4]));
1864  if (!NIL_P(s[5])) {
1865  set_hash("zone", s[5]);
1866  set_hash("offset", date_zone_to_diff(s[5]));
1867  }
1868 
1869  return 1;
1870 }
1871 
1872 #define iso8601_bas_time_cb iso8601_ext_time_cb
1873 
1874 static int
1876 {
1877  static const char pat_source[] =
1878  "\\A\\s*(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
1879  "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
1880  static VALUE pat = Qnil;
1881 
1882  REGCOMP_I(pat);
1883  MATCH(str, pat, iso8601_ext_time_cb);
1884 }
1885 
1886 static int
1888 {
1889  static const char pat_source[] =
1890  "\\A\\s*(?:(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
1891  "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
1892  static VALUE pat = Qnil;
1893 
1894  REGCOMP_I(pat);
1895  MATCH(str, pat, iso8601_bas_time_cb);
1896 }
1897 
1898 VALUE
1900 {
1901  VALUE backref, hash;
1902 
1903  backref = rb_backref_get();
1904  rb_match_busy(backref);
1905 
1906  hash = rb_hash_new();
1907 
1908  if (iso8601_ext_datetime(str, hash))
1909  goto ok;
1910  if (iso8601_bas_datetime(str, hash))
1911  goto ok;
1912  if (iso8601_ext_time(str, hash))
1913  goto ok;
1914  if (iso8601_bas_time(str, hash))
1915  goto ok;
1916 
1917  ok:
1918  rb_backref_set(backref);
1919 
1920  return hash;
1921 }
1922 
1923 #undef SNUM
1924 #define SNUM 8
1925 
1926 static int
1928 {
1929  VALUE s[SNUM + 1];
1930 
1931  {
1932  int i;
1933  s[0] = Qnil;
1934  for (i = 1; i <= SNUM; i++)
1935  s[i] = rb_reg_nth_match(i, m);
1936  }
1937 
1938  set_hash("year", str2num(s[1]));
1939  set_hash("mon", str2num(s[2]));
1940  set_hash("mday", str2num(s[3]));
1941  set_hash("hour", str2num(s[4]));
1942  set_hash("min", str2num(s[5]));
1943  set_hash("sec", str2num(s[6]));
1944  set_hash("zone", s[8]);
1945  set_hash("offset", date_zone_to_diff(s[8]));
1946  if (!NIL_P(s[7]))
1947  set_hash("sec_fraction", sec_fraction(s[7]));
1948 
1949  return 1;
1950 }
1951 
1952 static int
1953 rfc3339(VALUE str, VALUE hash)
1954 {
1955  static const char pat_source[] =
1956  "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
1957  "(?:t|\\s)"
1958  "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
1959  "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
1960  static VALUE pat = Qnil;
1961 
1962  REGCOMP_I(pat);
1963  MATCH(str, pat, rfc3339_cb);
1964 }
1965 
1966 VALUE
1968 {
1969  VALUE backref, hash;
1970 
1971  backref = rb_backref_get();
1972  rb_match_busy(backref);
1973 
1974  hash = rb_hash_new();
1975  rfc3339(str, hash);
1976  rb_backref_set(backref);
1977  return hash;
1978 }
1979 
1980 #undef SNUM
1981 #define SNUM 8
1982 
1983 static int
1985 {
1986  VALUE s[SNUM + 1];
1987 
1988  {
1989  int i;
1990  s[0] = Qnil;
1991  for (i = 1; i <= SNUM; i++)
1992  s[i] = rb_reg_nth_match(i, m);
1993  }
1994 
1995  set_hash("year", str2num(s[1]));
1996  if (!NIL_P(s[2]))
1997  set_hash("mon", str2num(s[2]));
1998  if (!NIL_P(s[3]))
1999  set_hash("mday", str2num(s[3]));
2000  if (!NIL_P(s[4]))
2001  set_hash("hour", str2num(s[4]));
2002  if (!NIL_P(s[5]))
2003  set_hash("min", str2num(s[5]));
2004  if (!NIL_P(s[6]))
2005  set_hash("sec", str2num(s[6]));
2006  if (!NIL_P(s[7]))
2007  set_hash("sec_fraction", sec_fraction(s[7]));
2008  if (!NIL_P(s[8])) {
2009  set_hash("zone", s[8]);
2010  set_hash("offset", date_zone_to_diff(s[8]));
2011  }
2012 
2013  return 1;
2014 }
2015 
2016 static int
2018 {
2019  static const char pat_source[] =
2020  "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
2021  "(?:t"
2022  "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
2023  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2024  static VALUE pat = Qnil;
2025 
2026  REGCOMP_I(pat);
2027  MATCH(str, pat, xmlschema_datetime_cb);
2028 }
2029 
2030 #undef SNUM
2031 #define SNUM 5
2032 
2033 static int
2035 {
2036  VALUE s[SNUM + 1];
2037 
2038  {
2039  int i;
2040  s[0] = Qnil;
2041  for (i = 1; i <= SNUM; i++)
2042  s[i] = rb_reg_nth_match(i, m);
2043  }
2044 
2045  set_hash("hour", str2num(s[1]));
2046  set_hash("min", str2num(s[2]));
2047  if (!NIL_P(s[3]))
2048  set_hash("sec", str2num(s[3]));
2049  if (!NIL_P(s[4]))
2050  set_hash("sec_fraction", sec_fraction(s[4]));
2051  if (!NIL_P(s[5])) {
2052  set_hash("zone", s[5]);
2053  set_hash("offset", date_zone_to_diff(s[5]));
2054  }
2055 
2056  return 1;
2057 }
2058 
2059 static int
2061 {
2062  static const char pat_source[] =
2063  "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2064  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2065  static VALUE pat = Qnil;
2066 
2067  REGCOMP_I(pat);
2068  MATCH(str, pat, xmlschema_time_cb);
2069 }
2070 
2071 #undef SNUM
2072 #define SNUM 4
2073 
2074 static int
2076 {
2077  VALUE s[SNUM + 1];
2078 
2079  {
2080  int i;
2081  s[0] = Qnil;
2082  for (i = 1; i <= SNUM; i++)
2083  s[i] = rb_reg_nth_match(i, m);
2084  }
2085 
2086  if (!NIL_P(s[1]))
2087  set_hash("mon", str2num(s[1]));
2088  if (!NIL_P(s[2]))
2089  set_hash("mday", str2num(s[2]));
2090  if (!NIL_P(s[3]))
2091  set_hash("mday", str2num(s[3]));
2092  if (!NIL_P(s[4])) {
2093  set_hash("zone", s[4]);
2094  set_hash("offset", date_zone_to_diff(s[4]));
2095  }
2096 
2097  return 1;
2098 }
2099 
2100 static int
2102 {
2103  static const char pat_source[] =
2104  "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
2105  "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2106  static VALUE pat = Qnil;
2107 
2108  REGCOMP_I(pat);
2109  MATCH(str, pat, xmlschema_trunc_cb);
2110 }
2111 
2112 VALUE
2114 {
2115  VALUE backref, hash;
2116 
2117  backref = rb_backref_get();
2118  rb_match_busy(backref);
2119 
2120  hash = rb_hash_new();
2121 
2122  if (xmlschema_datetime(str, hash))
2123  goto ok;
2124  if (xmlschema_time(str, hash))
2125  goto ok;
2126  if (xmlschema_trunc(str, hash))
2127  goto ok;
2128 
2129  ok:
2130  rb_backref_set(backref);
2131 
2132  return hash;
2133 }
2134 
2135 #undef SNUM
2136 #define SNUM 8
2137 
2138 static int
2140 {
2141  VALUE s[SNUM + 1], y;
2142 
2143  {
2144  int i;
2145  s[0] = Qnil;
2146  for (i = 1; i <= SNUM; i++)
2147  s[i] = rb_reg_nth_match(i, m);
2148  }
2149 
2150  if (!NIL_P(s[1])) {
2151  set_hash("wday", INT2FIX(day_num(s[1])));
2152  }
2153  set_hash("mday", str2num(s[2]));
2154  set_hash("mon", INT2FIX(mon_num(s[3])));
2155  y = str2num(s[4]);
2156  if (RSTRING_LEN(s[4]) < 4)
2157  y = comp_year50(y);
2158  set_hash("year", y);
2159  set_hash("hour", str2num(s[5]));
2160  set_hash("min", str2num(s[6]));
2161  if (!NIL_P(s[7]))
2162  set_hash("sec", str2num(s[7]));
2163  set_hash("zone", s[8]);
2164  set_hash("offset", date_zone_to_diff(s[8]));
2165 
2166  return 1;
2167 }
2168 
2169 static int
2170 rfc2822(VALUE str, VALUE hash)
2171 {
2172  static const char pat_source[] =
2173  "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
2174  "(\\d{1,2})\\s+"
2175  "(" ABBR_MONTHS ")\\s+"
2176  "(-?\\d{2,})\\s+"
2177  "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
2178  "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
2179  static VALUE pat = Qnil;
2180 
2181  REGCOMP_I(pat);
2182  MATCH(str, pat, rfc2822_cb);
2183 }
2184 
2185 VALUE
2187 {
2188  VALUE backref, hash;
2189 
2190  backref = rb_backref_get();
2191  rb_match_busy(backref);
2192 
2193  hash = rb_hash_new();
2194  rfc2822(str, hash);
2195  rb_backref_set(backref);
2196  return hash;
2197 }
2198 
2199 #undef SNUM
2200 #define SNUM 8
2201 
2202 static int
2204 {
2205  VALUE s[SNUM + 1];
2206 
2207  {
2208  int i;
2209  s[0] = Qnil;
2210  for (i = 1; i <= SNUM; i++)
2211  s[i] = rb_reg_nth_match(i, m);
2212  }
2213 
2214  set_hash("wday", INT2FIX(day_num(s[1])));
2215  set_hash("mday", str2num(s[2]));
2216  set_hash("mon", INT2FIX(mon_num(s[3])));
2217  set_hash("year", str2num(s[4]));
2218  set_hash("hour", str2num(s[5]));
2219  set_hash("min", str2num(s[6]));
2220  set_hash("sec", str2num(s[7]));
2221  set_hash("zone", s[8]);
2222  set_hash("offset", INT2FIX(0));
2223 
2224  return 1;
2225 }
2226 
2227 static int
2229 {
2230  static const char pat_source[] =
2231  "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
2232  "(\\d{2})\\s+"
2233  "(" ABBR_MONTHS ")\\s+"
2234  "(-?\\d{4})\\s+"
2235  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2236  "(gmt)\\s*\\z";
2237  static VALUE pat = Qnil;
2238 
2239  REGCOMP_I(pat);
2240  MATCH(str, pat, httpdate_type1_cb);
2241 }
2242 
2243 #undef SNUM
2244 #define SNUM 8
2245 
2246 static int
2248 {
2249  VALUE s[SNUM + 1], y;
2250 
2251  {
2252  int i;
2253  s[0] = Qnil;
2254  for (i = 1; i <= SNUM; i++)
2255  s[i] = rb_reg_nth_match(i, m);
2256  }
2257 
2258  set_hash("wday", INT2FIX(day_num(s[1])));
2259  set_hash("mday", str2num(s[2]));
2260  set_hash("mon", INT2FIX(mon_num(s[3])));
2261  y = str2num(s[4]);
2262  if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
2263  y = comp_year69(y);
2264  set_hash("year", y);
2265  set_hash("hour", str2num(s[5]));
2266  set_hash("min", str2num(s[6]));
2267  set_hash("sec", str2num(s[7]));
2268  set_hash("zone", s[8]);
2269  set_hash("offset", INT2FIX(0));
2270 
2271  return 1;
2272 }
2273 
2274 static int
2276 {
2277  static const char pat_source[] =
2278  "\\A\\s*(" DAYS ")\\s*,\\s+"
2279  "(\\d{2})\\s*-\\s*"
2280  "(" ABBR_MONTHS ")\\s*-\\s*"
2281  "(\\d{2})\\s+"
2282  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2283  "(gmt)\\s*\\z";
2284  static VALUE pat = Qnil;
2285 
2286  REGCOMP_I(pat);
2287  MATCH(str, pat, httpdate_type2_cb);
2288 }
2289 
2290 #undef SNUM
2291 #define SNUM 7
2292 
2293 static int
2295 {
2296  VALUE s[SNUM + 1];
2297 
2298  {
2299  int i;
2300  s[0] = Qnil;
2301  for (i = 1; i <= SNUM; i++)
2302  s[i] = rb_reg_nth_match(i, m);
2303  }
2304 
2305  set_hash("wday", INT2FIX(day_num(s[1])));
2306  set_hash("mon", INT2FIX(mon_num(s[2])));
2307  set_hash("mday", str2num(s[3]));
2308  set_hash("hour", str2num(s[4]));
2309  set_hash("min", str2num(s[5]));
2310  set_hash("sec", str2num(s[6]));
2311  set_hash("year", str2num(s[7]));
2312 
2313  return 1;
2314 }
2315 
2316 static int
2318 {
2319  static const char pat_source[] =
2320  "\\A\\s*(" ABBR_DAYS ")\\s+"
2321  "(" ABBR_MONTHS ")\\s+"
2322  "(\\d{1,2})\\s+"
2323  "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2324  "(\\d{4})\\s*\\z";
2325  static VALUE pat = Qnil;
2326 
2327  REGCOMP_I(pat);
2328  MATCH(str, pat, httpdate_type3_cb);
2329 }
2330 
2331 VALUE
2333 {
2334  VALUE backref, hash;
2335 
2336  backref = rb_backref_get();
2337  rb_match_busy(backref);
2338 
2339  hash = rb_hash_new();
2340 
2341  if (httpdate_type1(str, hash))
2342  goto ok;
2343  if (httpdate_type2(str, hash))
2344  goto ok;
2345  if (httpdate_type3(str, hash))
2346  goto ok;
2347 
2348  ok:
2349  rb_backref_set(backref);
2350 
2351  return hash;
2352 }
2353 
2354 #undef SNUM
2355 #define SNUM 9
2356 
2357 static int
2359 {
2360  VALUE s[SNUM + 1];
2361  int ep;
2362 
2363  {
2364  int i;
2365  s[0] = Qnil;
2366  for (i = 1; i <= SNUM; i++)
2367  s[i] = rb_reg_nth_match(i, m);
2368  }
2369 
2370  ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1]));
2371  set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
2372  set_hash("mon", str2num(s[3]));
2373  set_hash("mday", str2num(s[4]));
2374  if (!NIL_P(s[5])) {
2375  set_hash("hour", str2num(s[5]));
2376  if (!NIL_P(s[6]))
2377  set_hash("min", str2num(s[6]));
2378  if (!NIL_P(s[7]))
2379  set_hash("sec", str2num(s[7]));
2380  }
2381  if (!NIL_P(s[8]))
2382  set_hash("sec_fraction", sec_fraction(s[8]));
2383  if (!NIL_P(s[9])) {
2384  set_hash("zone", s[9]);
2385  set_hash("offset", date_zone_to_diff(s[9]));
2386  }
2387 
2388  return 1;
2389 }
2390 
2391 static int
2393 {
2394  static const char pat_source[] =
2395  "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
2396  "(?:t"
2397  "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
2398  "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
2399  static VALUE pat = Qnil;
2400 
2401  REGCOMP_I(pat);
2402  MATCH(str, pat, jisx0301_cb);
2403 }
2404 
2405 VALUE
2407 {
2408  VALUE backref, hash;
2409 
2410  backref = rb_backref_get();
2411  rb_match_busy(backref);
2412 
2413  hash = rb_hash_new();
2414  if (jisx0301(str, hash))
2415  goto ok;
2416  hash = date__iso8601(str);
2417 
2418  ok:
2419  rb_backref_set(backref);
2420  return hash;
2421 }
2422 
2423 /*
2424 Local variables:
2425 c-file-style: "ruby"
2426 End:
2427 */
#define RSTRING_LEN(string)
Definition: generator.h:45
static long NUM2LONG(VALUE x)
Definition: ruby.h:510
static unsigned check_class(VALUE s)
Definition: date_parse.c:1516
#define f_begin(o, i)
Definition: date_parse.c:31
static int parse_time2_cb(VALUE m, VALUE hash)
Definition: date_parse.c:604
#define rb_rational_new2(x, y)
Definition: intern.h:154
#define ref_hash(k)
Definition: date_parse.c:39
#define f_aref(o, i)
Definition: date_parse.c:29
static int parse_sla_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1101
static int httpdate_type2(VALUE str, VALUE hash)
Definition: date_parse.c:2275
static int parse_bc_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1454
size_t strlen(const char *)
int i
Definition: win32ole.c:776
void rb_backref_set(VALUE)
Definition: vm.c:749
static int parse_iso22_cb(VALUE m, VALUE hash)
Definition: date_parse.c:842
#define NUM2INT(x)
Definition: ruby.h:536
static int parse_bc(VALUE str, VALUE hash)
Definition: date_parse.c:1466
static int xmlschema_trunc_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2075
#define f_expt(x, y)
Definition: date_parse.c:19
static int parse_us(VALUE str, VALUE hash)
Definition: date_parse.c:771
static int parse_iso24(VALUE str, VALUE hash)
Definition: date_parse.c:902
#define LONG2NUM(i)
Definition: cparse.c:72
#define f_to_s(x)
Definition: date_parse.c:26
static int parse_year_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1149
const int id
Definition: nkf.c:209
static int parse_day(VALUE str, VALUE hash)
Definition: date_parse.c:594
#define bp()
Definition: debug.h:27
#define sizeof_array(o)
Definition: date_parse.c:10
static int parse_year(VALUE str, VALUE hash)
Definition: date_parse.c:1159
#define asp_string()
Definition: date_parse.c:56
#define f_match(r, s)
Definition: date_parse.c:28
static const char * abbr_months[]
Definition: date_parse.c:50
static int gengo(int c)
Definition: date_parse.c:989
static void s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
Definition: date_parse.c:59
#define HAVE_DIGIT
Definition: date_parse.c:1510
#define set_hash(k, v)
Definition: date_parse.c:38
static int parse_day_cb(VALUE m, VALUE hash)
Definition: date_parse.c:584
#define RSTRING_PTR(string)
Definition: generator.h:42
VALUE rb_backref_get(void)
Definition: vm.c:743
static int iso8601_bas_datetime_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1756
#define f_end(o, i)
Definition: date_parse.c:32
static int xmlschema_trunc(VALUE str, VALUE hash)
Definition: date_parse.c:2101
#define HAVE_DASH
Definition: date_parse.c:1511
static int parse_iso21(VALUE str, VALUE hash)
Definition: date_parse.c:831
static int jisx0301_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2358
static VALUE regcomp(const char *source, long len, int opt)
Definition: date_parse.c:221
#define REGCOMP_I(pat)
Definition: date_parse.c:237
#define ABBR_DAYS
Definition: date_parse.c:217
#define strncasecmp
Definition: win32.h:209
static int parse_jis_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1004
static int jisx0301(VALUE str, VALUE hash)
Definition: date_parse.c:2392
static int min(int a, int b)
static int parse_iso25(VALUE str, VALUE hash)
Definition: date_parse.c:926
static int httpdate_type1_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2203
static int rfc3339(VALUE str, VALUE hash)
Definition: date_parse.c:1953
static int parse_time(VALUE str, VALUE hash)
Definition: date_parse.c:680
static int parse_iso22(VALUE str, VALUE hash)
Definition: date_parse.c:852
Win32OLEIDispatch * p
Definition: win32ole.c:778
static int parse_jis(VALUE str, VALUE hash)
Definition: date_parse.c:1024
static int parse_iso26_cb(VALUE m, VALUE hash)
Definition: date_parse.c:942
#define SUBS(s, p, c)
Definition: date_parse.c:259
VALUE date__xmlschema(VALUE str)
Definition: date_parse.c:2113
static int iso8601_bas_datetime(VALUE str, VALUE hash)
Definition: date_parse.c:1825
static int day_num(VALUE s)
Definition: date_parse.c:562
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1133
static int parse_sla(VALUE str, VALUE hash)
Definition: date_parse.c:1114
#define ABBR_MONTHS
Definition: date_parse.c:218
static int parse_vms12_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1061
#define DAYS
Definition: date_parse.c:215
static int iso8601_ext_datetime_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1670
VALUE date__parse(VALUE str, VALUE comp)
Definition: date_parse.c:1540
static VALUE comp_year50(VALUE y)
Definition: date_parse.c:1652
#define f_le_p(x, y)
Definition: date_parse.c:23
static int parse_ddd(VALUE str, VALUE hash)
Definition: date_parse.c:1427
static int rfc2822_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2139
#define NIL_P(v)
Definition: ruby.h:374
#define f_ge_p(x, y)
Definition: date_parse.c:24
static int parse_mday_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1189
#define f_negate(x)
Definition: date_parse.c:12
static int xmlschema_datetime_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1984
VALUE date_zone_to_diff(VALUE str)
Definition: date_parse.c:370
#define MATCH(s, p, c)
Definition: date_parse.c:239
int offset
Definition: date_parse.c:288
VALUE date__rfc2822(VALUE str)
Definition: date_parse.c:2186
VALUE date__jisx0301(VALUE str)
Definition: date_parse.c:2406
#define TYPE(x)
Definition: ruby.h:441
#define Qfalse
Definition: ruby.h:365
static int parse_time_cb(VALUE m, VALUE hash)
Definition: date_parse.c:647
static int parse_iso_cb(VALUE m, VALUE hash)
Definition: date_parse.c:790
#define ALLOCA_N(type, n)
Definition: ruby.h:1038
static int xmlschema_time(VALUE str, VALUE hash)
Definition: date_parse.c:2060
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:971
#define HAVE_ELEM_P(x)
Definition: date_parse.c:1537
#define HAVE_DOT
Definition: date_parse.c:1512
static int parse_vms(VALUE str, VALUE hash)
Definition: date_parse.c:1088
static int parse_iso24_cb(VALUE m, VALUE hash)
Definition: date_parse.c:887
VALUE rb_reg_new(const char *, long, int)
Definition: re.c:2510
static int mon_num(VALUE s)
Definition: date_parse.c:573
static int parse_frag(VALUE str, VALUE hash)
Definition: date_parse.c:1500
static VALUE sec_fraction(VALUE f)
Definition: date_parse.c:1660
#define RB_GC_GUARD(object)
Definition: generator.h:50
static int iso8601_bas_time(VALUE str, VALUE hash)
Definition: date_parse.c:1887
#define f_add(x, y)
Definition: date_parse.c:13
VALUE rb_hash_new(void)
Definition: hash.c:229
static int rfc2822(VALUE str, VALUE hash)
Definition: date_parse.c:2170
static int parse_iso25_cb(VALUE m, VALUE hash)
Definition: date_parse.c:912
#define HAVE_SLASH
Definition: date_parse.c:1513
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:3913
#define HAVE_ALPHA
Definition: date_parse.c:1509
#define Qnil
Definition: ruby.h:367
static int parse_dot(VALUE str, VALUE hash)
Definition: date_parse.c:1138
#define cstr2num(s)
Definition: date_parse.c:42
static int xmlschema_time_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2034
unsigned long VALUE
Definition: ruby.h:88
static int parse_dot_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1125
static int parse_iso(VALUE str, VALUE hash)
Definition: date_parse.c:803
char * strchr(char *, char)
static struct zone zones_source[]
Definition: date_parse.c:291
register unsigned int len
Definition: name2ctype.h:22210
void rb_match_busy(VALUE)
Definition: re.c:1177
static int parse_us_cb(VALUE m, VALUE hash)
Definition: date_parse.c:753
static int parse_eu_cb(VALUE m, VALUE hash)
Definition: date_parse.c:716
VALUE rb_str_dup(VALUE)
Definition: string.c:905
#define f_mul(x, y)
Definition: date_parse.c:15
static int parse_ddd_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1224
const char * name
Definition: date_parse.c:287
static int xmlschema_datetime(VALUE str, VALUE hash)
Definition: date_parse.c:2017
#define iso8601_bas_time_cb
Definition: date_parse.c:1872
static const char * abbr_days[]
Definition: date_parse.c:45
#define STD
static int parse_mday(VALUE str, VALUE hash)
Definition: date_parse.c:1199
#define INT2FIX(i)
Definition: ruby.h:225
#define SNUM
Definition: date_parse.c:2355
#define str2num(s)
Definition: date_parse.c:43
static VALUE comp_year69(VALUE y)
Definition: date_parse.c:1644
static int httpdate_type1(VALUE str, VALUE hash)
Definition: date_parse.c:2228
static int rfc3339_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1927
#define f_gsub_bang(s, r, x)
Definition: date_parse.c:36
VALUE date__httpdate(VALUE str)
Definition: date_parse.c:2332
static int iso8601_ext_time_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1847
static int parse_vms11_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1034
static int parse_frag_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1477
static int parse_iso21_cb(VALUE m, VALUE hash)
Definition: date_parse.c:813
#define DST
#define f_aset2(o, i, j, v)
Definition: date_parse.c:34
#define RTEST(v)
Definition: ruby.h:373
#define T_STRING
Definition: ruby.h:418
static int parse_mon_cb(VALUE m, VALUE hash)
Definition: date_parse.c:1169
v
Definition: win32ole.c:790
#define del_hash(k)
Definition: date_parse.c:40
static int n2i(const char *s, long f, long w)
Definition: date_parse.c:1209
static int subs(VALUE str, VALUE pat, VALUE hash, int(*cb)(VALUE, VALUE))
Definition: date_parse.c:265
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
static int parse_iso23_cb(VALUE m, VALUE hash)
Definition: date_parse.c:862
static int parse_vms11(VALUE str, VALUE hash)
Definition: date_parse.c:1049
VALUE date__rfc3339(VALUE str)
Definition: date_parse.c:1967
static int parse_iso2(VALUE str, VALUE hash)
Definition: date_parse.c:968
static int iso8601_ext_datetime(VALUE str, VALUE hash)
Definition: date_parse.c:1736
const char * name
Definition: nkf.c:208
static int parse_iso26(VALUE str, VALUE hash)
Definition: date_parse.c:952
#define REGCOMP_0(pat)
Definition: date_parse.c:236
#define issign(c)
Definition: date_parse.c:55
static int parse_vms12(VALUE str, VALUE hash)
Definition: date_parse.c:1076
static int parse_iso23(VALUE str, VALUE hash)
Definition: date_parse.c:877
static int httpdate_type3_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2294
static int httpdate_type2_cb(VALUE m, VALUE hash)
Definition: date_parse.c:2247
static int match(VALUE str, VALUE pat, VALUE hash, int(*cb)(VALUE, VALUE))
Definition: date_parse.c:245
VALUE rb_str_new2(const char *)
VALUE date__iso8601(VALUE str)
Definition: date_parse.c:1899
VALUE rb_reg_nth_match(int, VALUE)
Definition: re.c:1445
static int httpdate_type3(VALUE str, VALUE hash)
Definition: date_parse.c:2317
static int parse_mon(VALUE str, VALUE hash)
Definition: date_parse.c:1179
VALUE rb_str_new(const char *, long)
Definition: string.c:410
static int parse_eu(VALUE str, VALUE hash)
Definition: date_parse.c:734
static int iso8601_ext_time(VALUE str, VALUE hash)
Definition: date_parse.c:1875