Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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 RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
11 RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
12
13 /* #define TIGHT_PARSER */
14
15 #define sizeof_array(o) (sizeof o / sizeof o[0])
16
17 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
18 #define f_add(x,y) rb_funcall(x, '+', 1, y)
19 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
20 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
21 #define f_div(x,y) rb_funcall(x, '/', 1, y)
22 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
23 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
24 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
25
26 #define f_lt_p(x,y) rb_funcall(x, '<', 1, y)
27 #define f_gt_p(x,y) rb_funcall(x, '>', 1, y)
28 #define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y)
29 #define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y)
30
31 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
32
33 #define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
34 #define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
35 #define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j)
36 #define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i)
37 #define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
38 #define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v)
39 #define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v)
40 #define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x)
41 #define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x)
42
43 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k"")), v)
44 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k"")))
45 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k"")))
46
47 #define cstr2num(s) rb_cstr_to_inum(s, 10, 0)
48 #define str2num(s) rb_str_to_inum(s, 10, 0)
49
50 static const char abbr_days[][4] = {
51 "sun", "mon", "tue", "wed",
52 "thu", "fri", "sat"
53 };
54
55 static const char abbr_months[][4] = {
56 "jan", "feb", "mar", "apr", "may", "jun",
57 "jul", "aug", "sep", "oct", "nov", "dec"
58 };
59
60 #define issign(c) ((c) == '-' || (c) == '+')
61 #define asp_string() rb_str_new(" ", 1)
62 #ifdef TIGHT_PARSER
63 #define asuba_string() rb_str_new("\001", 1)
64 #define asubb_string() rb_str_new("\002", 1)
65 #define asubw_string() rb_str_new("\027", 1)
66 #define asubt_string() rb_str_new("\024", 1)
67 #endif
68
69 static size_t
70 digit_span(const char *s, const char *e)
71 {
72 size_t i = 0;
73 while (s + i < e && isdigit(s[i])) i++;
74 return i;
75 }
76
77 static void
78 s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
79 {
80 VALUE vbuf = 0;
81 VALUE c = Qnil;
82
83 if (!RB_TYPE_P(m, T_STRING))
84 m = f_to_s(m);
85
86 if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) {
87 VALUE oy = y;
88 VALUE om = m;
89 VALUE od = d;
90
91 y = od;
92 m = oy;
93 d = om;
94 }
95
96 if (NIL_P(y)) {
97 if (!NIL_P(d) && RSTRING_LEN(d) > 2) {
98 y = d;
99 d = Qnil;
100 }
101 if (!NIL_P(d) && RSTRING_LEN(d) > 0 && *RSTRING_PTR(d) == '\'') {
102 y = d;
103 d = Qnil;
104 }
105 }
106
107 if (!NIL_P(y)) {
108 const char *s, *bp, *ep;
109 size_t l;
110
111 s = RSTRING_PTR(y);
112 ep = RSTRING_END(y);
113 while (s < ep && !issign(*s) && !isdigit(*s))
114 s++;
115 if (s >= ep) goto no_date;
116 bp = s;
117 if (issign((unsigned char)*s))
118 s++;
119 l = digit_span(s, ep);
120 ep = s + l;
121 if (*ep) {
122 y = d;
123 d = rb_str_new(bp, ep - bp);
124 }
125 no_date:;
126 }
127
128 if (!NIL_P(m)) {
129 const char *s;
130
131 s = RSTRING_PTR(m);
132 if (*s == '\'' || RSTRING_LEN(m) > 2) {
133 /* us -> be */
134 VALUE oy = y;
135 VALUE om = m;
136 VALUE od = d;
137
138 y = om;
139 m = od;
140 d = oy;
141 }
142 }
143
144 if (!NIL_P(d)) {
145 const char *s;
146
147 s = RSTRING_PTR(d);
148 if (*s == '\'' || RSTRING_LEN(d) > 2) {
149 VALUE oy = y;
150 VALUE od = d;
151
152 y = od;
153 d = oy;
154 }
155 }
156
157 if (!NIL_P(y)) {
158 const char *s, *bp, *ep;
159 int sign = 0;
160 size_t l;
161 VALUE iy;
162
163 s = RSTRING_PTR(y);
164 ep = RSTRING_END(y);
165 while (s < ep && !issign(*s) && !isdigit(*s))
166 s++;
167 if (s >= ep) goto no_year;
168 bp = s;
169 if (issign(*s)) {
170 s++;
171 sign = 1;
172 }
173 if (sign)
174 c = Qfalse;
175 l = digit_span(s, ep);
176 ep = s + l;
177 if (l > 2)
178 c = Qfalse;
179 {
180 char *buf;
181
182 buf = ALLOCV_N(char, vbuf, ep - bp + 1);
183 memcpy(buf, bp, ep - bp);
184 buf[ep - bp] = '\0';
185 iy = cstr2num(buf);
186 ALLOCV_END(vbuf);
187 }
188 set_hash("year", iy);
189 no_year:;
190 }
191
192 if (bc)
193 set_hash("_bc", Qtrue);
194
195 if (!NIL_P(m)) {
196 const char *s, *bp, *ep;
197 size_t l;
198 VALUE im;
199
200 s = RSTRING_PTR(m);
201 ep = RSTRING_END(m);
202 while (s < ep && !isdigit(*s))
203 s++;
204 if (s >= ep) goto no_month;
205 bp = s;
206 l = digit_span(s, ep);
207 ep = s + l;
208 {
209 char *buf;
210
211 buf = ALLOCV_N(char, vbuf, ep - bp + 1);
212 memcpy(buf, bp, ep - bp);
213 buf[ep - bp] = '\0';
214 im = cstr2num(buf);
215 ALLOCV_END(vbuf);
216 }
217 set_hash("mon", im);
218 no_month:;
219 }
220
221 if (!NIL_P(d)) {
222 const char *s, *bp, *ep;
223 size_t l;
224 VALUE id;
225
226 s = RSTRING_PTR(d);
227 ep = RSTRING_END(d);
228 while (s < ep && !isdigit(*s))
229 s++;
230 if (s >= ep) goto no_mday;
231 bp = s;
232 l = digit_span(s, ep);
233 ep = s + l;
234 {
235 char *buf;
236
237 buf = ALLOCV_N(char, vbuf, ep - bp + 1);
238 memcpy(buf, bp, ep - bp);
239 buf[ep - bp] = '\0';
240 id = cstr2num(buf);
241 ALLOCV_END(vbuf);
242 }
243 set_hash("mday", id);
244 no_mday:;
245 }
246
247 if (!NIL_P(c))
248 set_hash("_comp", c);
249 }
250
251 #define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday"
252 #define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december"
253 #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
254 #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
255
256 #ifdef TIGHT_PARSER
257 #define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
258 #define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
259 #define DOTLESS_VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")"
260 #define BOS "\\A\\s*"
261 #define FPA "\\001"
262 #define FPB "\\002"
263 #define FPW "\\027"
264 #define FPT "\\024"
265 #define FPW_COM "\\s*(?:" FPW "\\s*,?)?\\s*"
266 #define FPT_COM "\\s*(?:" FPT "\\s*,?)?\\s*"
267 #define COM_FPW "\\s*(?:,?\\s*" FPW ")?\\s*"
268 #define COM_FPT "\\s*(?:,?\\s*(?:@|\\b[aA][tT]\\b)?\\s*" FPT ")?\\s*"
269 #define TEE_FPT "\\s*(?:[tT]?" FPT ")?"
270 #define EOS "\\s*\\z"
271 #endif
272
273 static VALUE
274 regcomp(const char *source, long len, int opt)
275 {
276 VALUE pat;
277
278 pat = rb_reg_new(source, len, opt);
279 rb_gc_register_mark_object(pat);
280 return pat;
281 }
282
283 #define REGCOMP(pat,opt) \
284 do { \
285 if (NIL_P(pat)) \
286 pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \
287 } while (0)
288
289 #define REGCOMP_0(pat) REGCOMP(pat, 0)
290 #define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE)
291
292 #define MATCH(s,p,c) \
293 do { \
294 return match(s, p, hash, c); \
295 } while (0)
296
297 static int
298 match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
299 {
300 VALUE m;
301
302 m = f_match(pat, str);
303
304 if (NIL_P(m))
305 return 0;
306
307 (*cb)(m, hash);
308
309 return 1;
310 }
311
312 static int
313 subx(VALUE str, VALUE rep, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE))
314 {
315 VALUE m;
316
317 m = f_match(pat, str);
318
319 if (NIL_P(m))
320 return 0;
321
322 {
323 VALUE be, en;
324
325 be = f_begin(m, INT2FIX(0));
326 en = f_end(m, INT2FIX(0));
327 f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), rep);
328 (*cb)(m, hash);
329 }
330
331 return 1;
332 }
333
334 #define SUBS(s,p,c) \
335 do { \
336 return subx(s, asp_string(), p, hash, c); \
337 } while (0)
338
339 #ifdef TIGHT_PARSER
340 #define SUBA(s,p,c) \
341 do { \
342 return subx(s, asuba_string(), p, hash, c); \
343 } while (0)
344
345 #define SUBB(s,p,c) \
346 do { \
347 return subx(s, asubb_string(), p, hash, c); \
348 } while (0)
349
350 #define SUBW(s,p,c) \
351 do { \
352 return subx(s, asubw_string(), p, hash, c); \
353 } while (0)
354
355 #define SUBT(s,p,c) \
356 do { \
357 return subx(s, asubt_string(), p, hash, c); \
358 } while (0)
359 #endif
360
361 #include "zonetab.h"
362
363 static int
364 str_end_with_word(const char *s, long l, const char *w)
365 {
366 int n = (int)strlen(w);
367 if (l <= n || !isspace(s[l - n - 1])) return 0;
368 if (strncasecmp(&s[l - n], w, n)) return 0;
369 do ++n; while (l > n && isspace(s[l - n - 1]));
370 return n;
371 }
372
373 static long
374 shrunk_size(const char *s, long l)
375 {
376 long i, ni;
377 int sp = 0;
378 for (i = ni = 0; i < l; ++i) {
379 if (!isspace(s[i])) {
380 if (sp) ni++;
381 sp = 0;
382 ni++;
383 }
384 else {
385 sp = 1;
386 }
387 }
388 return ni < l ? ni : 0;
389 }
390
391 static long
392 shrink_space(char *d, const char *s, long l)
393 {
394 long i, ni;
395 int sp = 0;
396 for (i = ni = 0; i < l; ++i) {
397 if (!isspace(s[i])) {
398 if (sp) d[ni++] = ' ';
399 sp = 0;
400 d[ni++] = s[i];
401 }
402 else {
403 sp = 1;
404 }
405 }
406 return ni;
407 }
408
409 VALUE
410 date_zone_to_diff(VALUE str)
411 {
412 VALUE offset = Qnil;
413 VALUE vbuf = 0;
414 long l = RSTRING_LEN(str);
415 const char *s = RSTRING_PTR(str);
416
417 {
418 int dst = 0;
419 int w;
420
421 if ((w = str_end_with_word(s, l, "time")) > 0) {
422 int wtime = w;
423 l -= w;
424 if ((w = str_end_with_word(s, l, "standard")) > 0) {
425 l -= w;
426 }
427 else if ((w = str_end_with_word(s, l, "daylight")) > 0) {
428 l -= w;
429 dst = 1;
430 }
431 else {
432 l += wtime;
433 }
434 }
435 else if ((w = str_end_with_word(s, l, "dst")) > 0) {
436 l -= w;
437 dst = 1;
438 }
439 {
440 long sl = shrunk_size(s, l);
441 if (sl > 0 && sl <= MAX_WORD_LENGTH) {
442 char *d = ALLOCV_N(char, vbuf, sl);
443 l = shrink_space(d, s, l);
444 s = d;
445 }
446 }
447 if (l > 0 && l <= MAX_WORD_LENGTH) {
448 const struct zone *z = zonetab(s, (unsigned int)l);
449 if (z) {
450 int d = z->offset;
451 if (dst)
452 d += 3600;
453 offset = INT2FIX(d);
454 goto ok;
455 }
456 }
457 {
458 char *p;
459 int sign = 0;
460 long hour = 0, min = 0, sec = 0;
461
462 if (l > 3 &&
463 (strncasecmp(s, "gmt", 3) == 0 ||
464 strncasecmp(s, "utc", 3) == 0)) {
465 s += 3;
466 l -= 3;
467 }
468 if (issign(*s)) {
469 sign = *s == '-';
470 s++;
471 l--;
472
473 hour = STRTOUL(s, &p, 10);
474 if (*p == ':') {
475 s = ++p;
476 min = STRTOUL(s, &p, 10);
477 if (*p == ':') {
478 s = ++p;
479 sec = STRTOUL(s, &p, 10);
480 }
481 goto num;
482 }
483 if (*p == ',' || *p == '.') {
484 char *e = 0;
485 p++;
486 min = STRTOUL(p, &e, 10) * 3600;
487 if (sign) {
488 hour = -hour;
489 min = -min;
490 }
491 offset = rb_rational_new(INT2FIX(min),
492 rb_int_positive_pow(10, (int)(e - p)));
493 offset = f_add(INT2FIX(hour * 3600), offset);
494 goto ok;
495 }
496 else if (l > 2) {
497 size_t n;
498 int ov;
499
500 if (l >= 1)
501 hour = ruby_scan_digits(&s[0], 2 - l % 2, 10, &n, &ov);
502 if (l >= 3)
503 min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
504 if (l >= 5)
505 sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
506 goto num;
507 }
508 num:
509 sec += min * 60 + hour * 3600;
510 if (sign) sec = -sec;
511 offset = INT2FIX(sec);
512 }
513 }
514 }
515 RB_GC_GUARD(str);
516 ok:
517 ALLOCV_END(vbuf);
518 return offset;
519 }
520
521 static int
522 day_num(VALUE s)
523 {
524 int i;
525
526 for (i = 0; i < (int)sizeof_array(abbr_days); i++)
527 if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0)
528 break;
529 return i;
530 }
531
532 static int
533 mon_num(VALUE s)
534 {
535 int i;
536
537 for (i = 0; i < (int)sizeof_array(abbr_months); i++)
538 if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0)
539 break;
540 return i + 1;
541 }
542
543 static int
544 parse_day_cb(VALUE m, VALUE hash)
545 {
546 VALUE s;
547
548 s = rb_reg_nth_match(1, m);
549 set_hash("wday", INT2FIX(day_num(s)));
550 return 1;
551 }
552
553 static int
554 parse_day(VALUE str, VALUE hash)
555 {
556 static const char pat_source[] =
557 #ifndef TIGHT_PARSER
558 "\\b(" ABBR_DAYS ")[^-/\\d\\s]*"
559 #else
560 "(" VALID_DAYS ")"
561 #endif
562 ;
563 static VALUE pat = Qnil;
564
565 REGCOMP_I(pat);
566 #ifndef TIGHT_PARSER
567 SUBS(str, pat, parse_day_cb);
568 #else
569 SUBW(str, pat, parse_day_cb);
570 #endif
571 }
572
573 static int
574 parse_time2_cb(VALUE m, VALUE hash)
575 {
576 VALUE h, min, s, f, p;
577
578 h = rb_reg_nth_match(1, m);
579 h = str2num(h);
580
581 min = rb_reg_nth_match(2, m);
582 if (!NIL_P(min))
583 min = str2num(min);
584
585 s = rb_reg_nth_match(3, m);
586 if (!NIL_P(s))
587 s = str2num(s);
588
589 f = rb_reg_nth_match(4, m);
590
591 if (!NIL_P(f))
592 f = rb_rational_new2(str2num(f),
593 f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f))));
594
595 p = rb_reg_nth_match(5, m);
596
597 if (!NIL_P(p)) {
598 int ih = NUM2INT(h);
599 ih %= 12;
600 if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p')
601 ih += 12;
602 h = INT2FIX(ih);
603 }
604
605 set_hash("hour", h);
606 if (!NIL_P(min))
607 set_hash("min", min);
608 if (!NIL_P(s))
609 set_hash("sec", s);
610 if (!NIL_P(f))
611 set_hash("sec_fraction", f);
612
613 return 1;
614 }
615
616 static int
617 parse_time_cb(VALUE m, VALUE hash)
618 {
619 static const char pat_source[] =
620 "\\A(\\d+)h?"
621 "(?:\\s*:?\\s*(\\d+)m?"
622 "(?:"
623 "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?"
624 ")?"
625 ")?"
626 "(?:\\s*([ap])(?:m\\b|\\.m\\.))?";
627 static VALUE pat = Qnil;
628 VALUE s1, s2;
629
630 s1 = rb_reg_nth_match(1, m);
631 s2 = rb_reg_nth_match(2, m);
632
633 if (!NIL_P(s2))
634 set_hash("zone", s2);
635
636 REGCOMP_I(pat);
637
638 {
639 VALUE m = f_match(pat, s1);
640
641 if (NIL_P(m))
642 return 0;
643 parse_time2_cb(m, hash);
644 }
645
646 return 1;
647 }
648
649 static int
650 parse_time(VALUE str, VALUE hash)
651 {
652 static const char pat_source[] =
653 "("
654 "(?:"
655 "\\d+\\s*:\\s*\\d+"
656 "(?:"
657 #ifndef TIGHT_PARSER
658 "\\s*:\\s*\\d+(?:[,.]\\d*)?"
659 #else
660 "\\s*:\\s*\\d+(?:[,.]\\d+)?"
661 #endif
662 ")?"
663 "|"
664 "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
665 ")"
666 "(?:"
667 "\\s*"
668 "[ap](?:m\\b|\\.m\\.)"
669 ")?"
670 "|"
671 "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
672 ")"
673 "(?:"
674 "\\s*"
675 "("
676 "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
677 "|"
678 "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
679 "|"
680 "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
681 ")"
682 ")?";
683 static VALUE pat = Qnil;
684
685 REGCOMP_I(pat);
686 #ifndef TIGHT_PARSER
687 SUBS(str, pat, parse_time_cb);
688 #else
689 SUBT(str, pat, parse_time_cb);
690 #endif
691 }
692
693 #ifdef TIGHT_PARSER
694 static int
695 parse_era1_cb(VALUE m, VALUE hash)
696 {
697 return 1;
698 }
699
700 static int
701 parse_era1(VALUE str, VALUE hash)
702 {
703 static const char pat_source[] =
704 "(a(?:d|\\.d\\.))";
705 static VALUE pat = Qnil;
706
707 REGCOMP_I(pat);
708 SUBA(str, pat, parse_era1_cb);
709 }
710
711 static int
712 parse_era2_cb(VALUE m, VALUE hash)
713 {
714 VALUE b;
715
716 b = rb_reg_nth_match(1, m);
717 if (*RSTRING_PTR(b) == 'B' ||
718 *RSTRING_PTR(b) == 'b')
719 set_hash("_bc", Qtrue);
720 return 1;
721 }
722
723 static int
724 parse_era2(VALUE str, VALUE hash)
725 {
726 static const char pat_source[] =
727 "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
728 static VALUE pat = Qnil;
729
730 REGCOMP_I(pat);
731 SUBB(str, pat, parse_era2_cb);
732 }
733
734 static int
735 parse_era(VALUE str, VALUE hash)
736 {
737 if (parse_era1(str, hash)) /* pre */
738 goto ok;
739 if (parse_era2(str, hash)) /* post */
740 goto ok;
741 return 0;
742 ok:
743 return 1;
744 }
745 #endif
746
747 #ifdef TIGHT_PARSER
748 static int
749 check_year_width(VALUE y)
750 {
751 const char *s;
752 long l;
753
754 l = RSTRING_LEN(y);
755 if (l < 2) return 0;
756 s = RSTRING_PTR(y);
757 if (!isdigit(s[1])) return 0;
758 return (l == 2 || !isdigit(s[2]));
759 }
760
761 static int
762 check_apost(VALUE a, VALUE b, VALUE c)
763 {
764 int f = 0;
765
766 if (!NIL_P(a) && *RSTRING_PTR(a) == '\'') {
767 if (!check_year_width(a))
768 return 0;
769 f++;
770 }
771 if (!NIL_P(b) && *RSTRING_PTR(b) == '\'') {
772 if (!check_year_width(b))
773 return 0;
774 if (!NIL_P(c))
775 return 0;
776 f++;
777 }
778 if (!NIL_P(c) && *RSTRING_PTR(c) == '\'') {
779 if (!check_year_width(c))
780 return 0;
781 f++;
782 }
783 if (f > 1)
784 return 0;
785 return 1;
786 }
787 #endif
788
789 static int
790 parse_eu_cb(VALUE m, VALUE hash)
791 {
792 #ifndef TIGHT_PARSER
793 VALUE y, mon, d, b;
794
795 d = rb_reg_nth_match(1, m);
796 mon = rb_reg_nth_match(2, m);
797 b = rb_reg_nth_match(3, m);
798 y = rb_reg_nth_match(4, m);
799
800 mon = INT2FIX(mon_num(mon));
801
802 s3e(hash, y, mon, d, !NIL_P(b) &&
803 (*RSTRING_PTR(b) == 'B' ||
804 *RSTRING_PTR(b) == 'b'));
805 #else
806 VALUE y, mon, d;
807
808 d = rb_reg_nth_match(1, m);
809 mon = rb_reg_nth_match(2, m);
810 y = rb_reg_nth_match(3, m);
811
812 if (!check_apost(d, mon, y))
813 return 0;
814
815 mon = INT2FIX(mon_num(mon));
816
817 s3e(hash, y, mon, d, 0);
818 #endif
819 return 1;
820 }
821
822 static int
823 parse_eu(VALUE str, VALUE hash)
824 {
825 static const char pat_source[] =
826 #ifdef TIGHT_PARSER
827 BOS
828 FPW_COM FPT_COM
829 #endif
830 #ifndef TIGHT_PARSER
831 "('?\\d+)[^-\\d\\s]*"
832 #else
833 "(\\d+)(?:(?:st|nd|rd|th)\\b)?"
834 #endif
835 "\\s*"
836 #ifndef TIGHT_PARSER
837 "(" ABBR_MONTHS ")[^-\\d\\s']*"
838 #else
839 "(" VALID_MONTHS ")"
840 #endif
841 "(?:"
842 "\\s*"
843 #ifndef TIGHT_PARSER
844 "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
845 "\\s*"
846 "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
847 #else
848 "(?:" FPA ")?"
849 "\\s*"
850 "([-']?\\d+)"
851 "\\s*"
852 "(?:" FPA "|" FPB ")?"
853 #endif
854 ")?"
855 #ifdef TIGHT_PARSER
856 COM_FPT COM_FPW
857 EOS
858 #endif
859 ;
860 static VALUE pat = Qnil;
861
862 REGCOMP_I(pat);
863 SUBS(str, pat, parse_eu_cb);
864 }
865
866 static int
867 parse_us_cb(VALUE m, VALUE hash)
868 {
869 #ifndef TIGHT_PARSER
870 VALUE y, mon, d, b;
871
872 mon = rb_reg_nth_match(1, m);
873 d = rb_reg_nth_match(2, m);
874
875 b = rb_reg_nth_match(3, m);
876 y = rb_reg_nth_match(4, m);
877
878 mon = INT2FIX(mon_num(mon));
879
880 s3e(hash, y, mon, d, !NIL_P(b) &&
881 (*RSTRING_PTR(b) == 'B' ||
882 *RSTRING_PTR(b) == 'b'));
883 #else
884 VALUE y, mon, d;
885
886 mon = rb_reg_nth_match(1, m);
887 d = rb_reg_nth_match(2, m);
888 y = rb_reg_nth_match(3, m);
889
890 if (!check_apost(mon, d, y))
891 return 0;
892
893 mon = INT2FIX(mon_num(mon));
894
895 s3e(hash, y, mon, d, 0);
896 #endif
897 return 1;
898 }
899
900 static int
901 parse_us(VALUE str, VALUE hash)
902 {
903 static const char pat_source[] =
904 #ifdef TIGHT_PARSER
905 BOS
906 FPW_COM FPT_COM
907 #endif
908 #ifndef TIGHT_PARSER
909 "\\b(" ABBR_MONTHS ")[^-\\d\\s']*"
910 #else
911 "\\b(" VALID_MONTHS ")"
912 #endif
913 "\\s*"
914 #ifndef TIGHT_PARSER
915 "('?\\d+)[^-\\d\\s']*"
916 #else
917 "('?\\d+)(?:(?:st|nd|rd|th)\\b)?"
918 COM_FPT
919 #endif
920 "(?:"
921 "\\s*,?"
922 "\\s*"
923 #ifndef TIGHT_PARSER
924 "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
925 "\\s*"
926 "('?-?\\d+)"
927 #else
928 "(?:" FPA ")?"
929 "\\s*"
930 "([-']?\\d+)"
931 "\\s*"
932 "(?:" FPA "|" FPB ")?"
933 #endif
934 ")?"
935 #ifdef TIGHT_PARSER
936 COM_FPT COM_FPW
937 EOS
938 #endif
939 ;
940 static VALUE pat = Qnil;
941
942 REGCOMP_I(pat);
943 SUBS(str, pat, parse_us_cb);
944 }
945
946 static int
947 parse_iso_cb(VALUE m, VALUE hash)
948 {
949 VALUE y, mon, d;
950
951 y = rb_reg_nth_match(1, m);
952 mon = rb_reg_nth_match(2, m);
953 d = rb_reg_nth_match(3, m);
954
955 #ifdef TIGHT_PARSER
956 if (!check_apost(y, mon, d))
957 return 0;
958 #endif
959
960 s3e(hash, y, mon, d, 0);
961 return 1;
962 }
963
964 static int
965 parse_iso(VALUE str, VALUE hash)
966 {
967 static const char pat_source[] =
968 #ifndef TIGHT_PARSER
969 "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
970 #else
971 BOS
972 FPW_COM FPT_COM
973 "([-+']?\\d+)-(\\d+)-([-']?\\d+)"
974 TEE_FPT COM_FPW
975 EOS
976 #endif
977 ;
978 static VALUE pat = Qnil;
979
980 REGCOMP_0(pat);
981 SUBS(str, pat, parse_iso_cb);
982 }
983
984 static int
985 parse_iso21_cb(VALUE m, VALUE hash)
986 {
987 VALUE y, w, d;
988
989 y = rb_reg_nth_match(1, m);
990 w = rb_reg_nth_match(2, m);
991 d = rb_reg_nth_match(3, m);
992
993 if (!NIL_P(y))
994 set_hash("cwyear", str2num(y));
995 set_hash("cweek", str2num(w));
996 if (!NIL_P(d))
997 set_hash("cwday", str2num(d));
998
999 return 1;
1000 }
1001
1002 static int
1003 parse_iso21(VALUE str, VALUE hash)
1004 {
1005 static const char pat_source[] =
1006 #ifndef TIGHT_PARSER
1007 "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"
1008 #else
1009 BOS
1010 FPW_COM FPT_COM
1011 "(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?"
1012 TEE_FPT COM_FPW
1013 EOS
1014 #endif
1015 ;
1016 static VALUE pat = Qnil;
1017
1018 REGCOMP_I(pat);
1019 SUBS(str, pat, parse_iso21_cb);
1020 }
1021
1022 static int
1023 parse_iso22_cb(VALUE m, VALUE hash)
1024 {
1025 VALUE d;
1026
1027 d = rb_reg_nth_match(1, m);
1028 set_hash("cwday", str2num(d));
1029 return 1;
1030 }
1031
1032 static int
1033 parse_iso22(VALUE str, VALUE hash)
1034 {
1035 static const char pat_source[] =
1036 #ifndef TIGHT_PARSER
1037 "-w-(\\d)\\b"
1038 #else
1039 BOS
1040 FPW_COM FPT_COM
1041 "-w-(\\d)"
1042 TEE_FPT COM_FPW
1043 EOS
1044 #endif
1045 ;
1046 static VALUE pat = Qnil;
1047
1048 REGCOMP_I(pat);
1049 SUBS(str, pat, parse_iso22_cb);
1050 }
1051
1052 static int
1053 parse_iso23_cb(VALUE m, VALUE hash)
1054 {
1055 VALUE mon, d;
1056
1057 mon = rb_reg_nth_match(1, m);
1058 d = rb_reg_nth_match(2, m);
1059
1060 if (!NIL_P(mon))
1061 set_hash("mon", str2num(mon));
1062 set_hash("mday", str2num(d));
1063
1064 return 1;
1065 }
1066
1067 static int
1068 parse_iso23(VALUE str, VALUE hash)
1069 {
1070 static const char pat_source[] =
1071 #ifndef TIGHT_PARSER
1072 "--(\\d{2})?-(\\d{2})\\b"
1073 #else
1074 BOS
1075 FPW_COM FPT_COM
1076 "--(\\d{2})?-(\\d{2})"
1077 TEE_FPT COM_FPW
1078 EOS
1079 #endif
1080 ;
1081 static VALUE pat = Qnil;
1082
1083 REGCOMP_0(pat);
1084 SUBS(str, pat, parse_iso23_cb);
1085 }
1086
1087 static int
1088 parse_iso24_cb(VALUE m, VALUE hash)
1089 {
1090 VALUE mon, d;
1091
1092 mon = rb_reg_nth_match(1, m);
1093 d = rb_reg_nth_match(2, m);
1094
1095 set_hash("mon", str2num(mon));
1096 if (!NIL_P(d))
1097 set_hash("mday", str2num(d));
1098
1099 return 1;
1100 }
1101
1102 static int
1103 parse_iso24(VALUE str, VALUE hash)
1104 {
1105 static const char pat_source[] =
1106 #ifndef TIGHT_PARSER
1107 "--(\\d{2})(\\d{2})?\\b"
1108 #else
1109 BOS
1110 FPW_COM FPT_COM
1111 "--(\\d{2})(\\d{2})?"
1112 TEE_FPT COM_FPW
1113 EOS
1114 #endif
1115 ;
1116 static VALUE pat = Qnil;
1117
1118 REGCOMP_0(pat);
1119 SUBS(str, pat, parse_iso24_cb);
1120 }
1121
1122 static int
1123 parse_iso25_cb(VALUE m, VALUE hash)
1124 {
1125 VALUE y, d;
1126
1127 y = rb_reg_nth_match(1, m);
1128 d = rb_reg_nth_match(2, m);
1129
1130 set_hash("year", str2num(y));
1131 set_hash("yday", str2num(d));
1132
1133 return 1;
1134 }
1135
1136 static int
1137 parse_iso25(VALUE str, VALUE hash)
1138 {
1139 static const char pat0_source[] =
1140 #ifndef TIGHT_PARSER
1141 "[,.](\\d{2}|\\d{4})-\\d{3}\\b"
1142 #else
1143 BOS
1144 FPW_COM FPT_COM
1145 "[,.](\\d{2}|\\d{4})-\\d{3}"
1146 TEE_FPT COM_FPW
1147 EOS
1148 #endif
1149 ;
1150 static VALUE pat0 = Qnil;
1151 static const char pat_source[] =
1152 #ifndef TIGHT_PARSER
1153 "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"
1154 #else
1155 BOS
1156 FPW_COM FPT_COM
1157 "(\\d{2}|\\d{4})-(\\d{3})"
1158 TEE_FPT COM_FPW
1159 EOS
1160 #endif
1161 ;
1162 static VALUE pat = Qnil;
1163
1164 REGCOMP_0(pat0);
1165 REGCOMP_0(pat);
1166
1167 if (!NIL_P(f_match(pat0, str)))
1168 return 0;
1169 SUBS(str, pat, parse_iso25_cb);
1170 }
1171
1172 static int
1173 parse_iso26_cb(VALUE m, VALUE hash)
1174 {
1175 VALUE d;
1176
1177 d = rb_reg_nth_match(1, m);
1178 set_hash("yday", str2num(d));
1179
1180 return 1;
1181 }
1182 static int
1183 parse_iso26(VALUE str, VALUE hash)
1184 {
1185 static const char pat0_source[] =
1186 #ifndef TIGHT_PARSER
1187 "\\d-\\d{3}\\b"
1188 #else
1189 BOS
1190 FPW_COM FPT_COM
1191 "\\d-\\d{3}"
1192 TEE_FPT COM_FPW
1193 EOS
1194 #endif
1195 ;
1196 static VALUE pat0 = Qnil;
1197 static const char pat_source[] =
1198 #ifndef TIGHT_PARSER
1199 "\\b-(\\d{3})\\b"
1200 #else
1201 BOS
1202 FPW_COM FPT_COM
1203 "-(\\d{3})"
1204 TEE_FPT COM_FPW
1205 EOS
1206 #endif
1207 ;
1208 static VALUE pat = Qnil;
1209
1210 REGCOMP_0(pat0);
1211 REGCOMP_0(pat);
1212
1213 if (!NIL_P(f_match(pat0, str)))
1214 return 0;
1215 SUBS(str, pat, parse_iso26_cb);
1216 }
1217
1218 static int
1219 parse_iso2(VALUE str, VALUE hash)
1220 {
1221 if (parse_iso21(str, hash))
1222 goto ok;
1223 if (parse_iso22(str, hash))
1224 goto ok;
1225 if (parse_iso23(str, hash))
1226 goto ok;
1227 if (parse_iso24(str, hash))
1228 goto ok;
1229 if (parse_iso25(str, hash))
1230 goto ok;
1231 if (parse_iso26(str, hash))
1232 goto ok;
1233 return 0;
1234
1235 ok:
1236 return 1;
1237 }
1238
1239 #define JISX0301_ERA_INITIALS "mtshr"
1240 #define JISX0301_DEFAULT_ERA 'H' /* obsolete */
1241
1242 static int
1243 gengo(int c)
1244 {
1245 int e;
1246
1247 switch (c) {
1248 case 'M': case 'm': e = 1867; break;
1249 case 'T': case 't': e = 1911; break;
1250 case 'S': case 's': e = 1925; break;
1251 case 'H': case 'h': e = 1988; break;
1252 case 'R': case 'r': e = 2018; break;
1253 default: e = 0; break;
1254 }
1255 return e;
1256 }
1257
1258 static int
1259 parse_jis_cb(VALUE m, VALUE hash)
1260 {
1261 VALUE e, y, mon, d;
1262 int ep;
1263
1264 e = rb_reg_nth_match(1, m);
1265 y = rb_reg_nth_match(2, m);
1266 mon = rb_reg_nth_match(3, m);
1267 d = rb_reg_nth_match(4, m);
1268
1269 ep = gengo(*RSTRING_PTR(e));
1270
1271 set_hash("year", f_add(str2num(y), INT2FIX(ep)));
1272 set_hash("mon", str2num(mon));
1273 set_hash("mday", str2num(d));
1274
1275 return 1;
1276 }
1277
1278 static int
1279 parse_jis(VALUE str, VALUE hash)
1280 {
1281 static const char pat_source[] =
1282 #ifndef TIGHT_PARSER
1283 "\\b([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
1284 #else
1285 BOS
1286 FPW_COM FPT_COM
1287 "([" JISX0301_ERA_INITIALS "])(\\d+)\\.(\\d+)\\.(\\d+)"
1288 TEE_FPT COM_FPW
1289 EOS
1290 #endif
1291 ;
1292 static VALUE pat = Qnil;
1293
1294 REGCOMP_I(pat);
1295 SUBS(str, pat, parse_jis_cb);
1296 }
1297
1298 static int
1299 parse_vms11_cb(VALUE m, VALUE hash)
1300 {
1301 VALUE y, mon, d;
1302
1303 d = rb_reg_nth_match(1, m);
1304 mon = rb_reg_nth_match(2, m);
1305 y = rb_reg_nth_match(3, m);
1306
1307 #ifdef TIGHT_PARSER
1308 if (!check_apost(d, mon, y))
1309 return 0;
1310 #endif
1311
1312 mon = INT2FIX(mon_num(mon));
1313
1314 s3e(hash, y, mon, d, 0);
1315 return 1;
1316 }
1317
1318 static int
1319 parse_vms11(VALUE str, VALUE hash)
1320 {
1321 static const char pat_source[] =
1322 #ifndef TIGHT_PARSER
1323 "('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
1324 "-('?-?\\d+)"
1325 #else
1326 BOS
1327 FPW_COM FPT_COM
1328 "([-']?\\d+)-(" DOTLESS_VALID_MONTHS ")"
1329 "-([-']?\\d+)"
1330 COM_FPT COM_FPW
1331 EOS
1332 #endif
1333 ;
1334 static VALUE pat = Qnil;
1335
1336 REGCOMP_I(pat);
1337 SUBS(str, pat, parse_vms11_cb);
1338 }
1339
1340 static int
1341 parse_vms12_cb(VALUE m, VALUE hash)
1342 {
1343 VALUE y, mon, d;
1344
1345 mon = rb_reg_nth_match(1, m);
1346 d = rb_reg_nth_match(2, m);
1347 y = rb_reg_nth_match(3, m);
1348
1349 #ifdef TIGHT_PARSER
1350 if (!check_apost(mon, d, y))
1351 return 0;
1352 #endif
1353
1354 mon = INT2FIX(mon_num(mon));
1355
1356 s3e(hash, y, mon, d, 0);
1357 return 1;
1358 }
1359
1360 static int
1361 parse_vms12(VALUE str, VALUE hash)
1362 {
1363 static const char pat_source[] =
1364 #ifndef TIGHT_PARSER
1365 "\\b(" ABBR_MONTHS ")[^-/.]*"
1366 "-('?-?\\d+)(?:-('?-?\\d+))?"
1367 #else
1368 BOS
1369 FPW_COM FPT_COM
1370 "(" DOTLESS_VALID_MONTHS ")"
1371 "-([-']?\\d+)(?:-([-']?\\d+))?"
1372 COM_FPT COM_FPW
1373 EOS
1374 #endif
1375 ;
1376 static VALUE pat = Qnil;
1377
1378 REGCOMP_I(pat);
1379 SUBS(str, pat, parse_vms12_cb);
1380 }
1381
1382 static int
1383 parse_vms(VALUE str, VALUE hash)
1384 {
1385 if (parse_vms11(str, hash))
1386 goto ok;
1387 if (parse_vms12(str, hash))
1388 goto ok;
1389 return 0;
1390
1391 ok:
1392 return 1;
1393 }
1394
1395 static int
1396 parse_sla_cb(VALUE m, VALUE hash)
1397 {
1398 VALUE y, mon, d;
1399
1400 y = rb_reg_nth_match(1, m);
1401 mon = rb_reg_nth_match(2, m);
1402 d = rb_reg_nth_match(3, m);
1403
1404 #ifdef TIGHT_PARSER
1405 if (!check_apost(y, mon, d))
1406 return 0;
1407 #endif
1408
1409 s3e(hash, y, mon, d, 0);
1410 return 1;
1411 }
1412
1413 static int
1414 parse_sla(VALUE str, VALUE hash)
1415 {
1416 static const char pat_source[] =
1417 #ifndef TIGHT_PARSER
1418 "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
1419 #else
1420 BOS
1421 FPW_COM FPT_COM
1422 "([-']?\\d+)/\\s*('?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1423 COM_FPT COM_FPW
1424 EOS
1425 #endif
1426 ;
1427 static VALUE pat = Qnil;
1428
1429 REGCOMP_I(pat);
1430 SUBS(str, pat, parse_sla_cb);
1431 }
1432
1433 #ifdef TIGHT_PARSER
1434 static int
1435 parse_sla2_cb(VALUE m, VALUE hash)
1436 {
1437 VALUE y, mon, d;
1438
1439 d = rb_reg_nth_match(1, m);
1440 mon = rb_reg_nth_match(2, m);
1441 y = rb_reg_nth_match(3, m);
1442
1443 if (!check_apost(d, mon, y))
1444 return 0;
1445
1446 mon = INT2FIX(mon_num(mon));
1447
1448 s3e(hash, y, mon, d, 0);
1449 return 1;
1450 }
1451
1452 static int
1453 parse_sla2(VALUE str, VALUE hash)
1454 {
1455 static const char pat_source[] =
1456 BOS
1457 FPW_COM FPT_COM
1458 "([-']?\\d+)/\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1459 COM_FPT COM_FPW
1460 EOS
1461 ;
1462 static VALUE pat = Qnil;
1463
1464 REGCOMP_I(pat);
1465 SUBS(str, pat, parse_sla2_cb);
1466 }
1467
1468 static int
1469 parse_sla3_cb(VALUE m, VALUE hash)
1470 {
1471 VALUE y, mon, d;
1472
1473 mon = rb_reg_nth_match(1, m);
1474 d = rb_reg_nth_match(2, m);
1475 y = rb_reg_nth_match(3, m);
1476
1477 if (!check_apost(mon, d, y))
1478 return 0;
1479
1480 mon = INT2FIX(mon_num(mon));
1481
1482 s3e(hash, y, mon, d, 0);
1483 return 1;
1484 }
1485
1486 static int
1487 parse_sla3(VALUE str, VALUE hash)
1488 {
1489 static const char pat_source[] =
1490 BOS
1491 FPW_COM FPT_COM
1492 "(" DOTLESS_VALID_MONTHS ")/\\s*([-']?\\d+)(?:(?:[-/]|\\s+)\\s*([-']?\\d+))?"
1493 COM_FPT COM_FPW
1494 EOS
1495 ;
1496 static VALUE pat = Qnil;
1497
1498 REGCOMP_I(pat);
1499 SUBS(str, pat, parse_sla3_cb);
1500 }
1501 #endif
1502
1503 static int
1504 parse_dot_cb(VALUE m, VALUE hash)
1505 {
1506 VALUE y, mon, d;
1507
1508 y = rb_reg_nth_match(1, m);
1509 mon = rb_reg_nth_match(2, m);
1510 d = rb_reg_nth_match(3, m);
1511
1512 #ifdef TIGHT_PARSER
1513 if (!check_apost(y, mon, d))
1514 return 0;
1515 #endif
1516
1517 s3e(hash, y, mon, d, 0);
1518 return 1;
1519 }
1520
1521 static int
1522 parse_dot(VALUE str, VALUE hash)
1523 {
1524 static const char pat_source[] =
1525 #ifndef TIGHT_PARSER
1526 "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
1527 #else
1528 BOS
1529 FPW_COM FPT_COM
1530 "([-']?\\d+)\\.\\s*(\\d+)\\.\\s*([-']?\\d+)"
1531 COM_FPT COM_FPW
1532 EOS
1533 #endif
1534 ;
1535 static VALUE pat = Qnil;
1536
1537 REGCOMP_I(pat);
1538 SUBS(str, pat, parse_dot_cb);
1539 }
1540
1541 #ifdef TIGHT_PARSER
1542 static int
1543 parse_dot2_cb(VALUE m, VALUE hash)
1544 {
1545 VALUE y, mon, d;
1546
1547 d = rb_reg_nth_match(1, m);
1548 mon = rb_reg_nth_match(2, m);
1549 y = rb_reg_nth_match(3, m);
1550
1551 if (!check_apost(d, mon, y))
1552 return 0;
1553
1554 mon = INT2FIX(mon_num(mon));
1555
1556 s3e(hash, y, mon, d, 0);
1557 return 1;
1558 }
1559
1560 static int
1561 parse_dot2(VALUE str, VALUE hash)
1562 {
1563 static const char pat_source[] =
1564 BOS
1565 FPW_COM FPT_COM
1566 "([-']?\\d+)\\.\\s*(" DOTLESS_VALID_MONTHS ")(?:(?:[./])\\s*([-']?\\d+))?"
1567 COM_FPT COM_FPW
1568 EOS
1569 ;
1570 static VALUE pat = Qnil;
1571
1572 REGCOMP_I(pat);
1573 SUBS(str, pat, parse_dot2_cb);
1574 }
1575
1576 static int
1577 parse_dot3_cb(VALUE m, VALUE hash)
1578 {
1579 VALUE y, mon, d;
1580
1581 mon = rb_reg_nth_match(1, m);
1582 d = rb_reg_nth_match(2, m);
1583 y = rb_reg_nth_match(3, m);
1584
1585 if (!check_apost(mon, d, y))
1586 return 0;
1587
1588 mon = INT2FIX(mon_num(mon));
1589
1590 s3e(hash, y, mon, d, 0);
1591 return 1;
1592 }
1593
1594 static int
1595 parse_dot3(VALUE str, VALUE hash)
1596 {
1597 static const char pat_source[] =
1598 BOS
1599 FPW_COM FPT_COM
1600 "(" DOTLESS_VALID_MONTHS ")\\.\\s*([-']?\\d+)(?:(?:[./])\\s*([-']?\\d+))?"
1601 COM_FPT COM_FPW
1602 EOS
1603 ;
1604 static VALUE pat = Qnil;
1605
1606 REGCOMP_I(pat);
1607 SUBS(str, pat, parse_dot3_cb);
1608 }
1609 #endif
1610
1611 static int
1612 parse_year_cb(VALUE m, VALUE hash)
1613 {
1614 VALUE y;
1615
1616 y = rb_reg_nth_match(1, m);
1617 set_hash("year", str2num(y));
1618 return 1;
1619 }
1620
1621 static int
1622 parse_year(VALUE str, VALUE hash)
1623 {
1624 static const char pat_source[] =
1625 #ifndef TIGHT_PARSER
1626 "'(\\d+)\\b"
1627 #else
1628 BOS
1629 FPW_COM FPT_COM
1630 "'(\\d+)"
1631 COM_FPT COM_FPW
1632 EOS
1633 #endif
1634 ;
1635 static VALUE pat = Qnil;
1636
1637 REGCOMP_0(pat);
1638 SUBS(str, pat, parse_year_cb);
1639 }
1640
1641 static int
1642 parse_mon_cb(VALUE m, VALUE hash)
1643 {
1644 VALUE mon;
1645
1646 mon = rb_reg_nth_match(1, m);
1647 set_hash("mon", INT2FIX(mon_num(mon)));
1648 return 1;
1649 }
1650
1651 static int
1652 parse_mon(VALUE str, VALUE hash)
1653 {
1654 static const char pat_source[] =
1655 #ifndef TIGHT_PARSER
1656 "\\b(" ABBR_MONTHS ")\\S*"
1657 #else
1658 BOS
1659 FPW_COM FPT_COM
1660 "(" VALID_MONTHS ")"
1661 COM_FPT COM_FPW
1662 EOS
1663 #endif
1664 ;
1665 static VALUE pat = Qnil;
1666
1667 REGCOMP_I(pat);
1668 SUBS(str, pat, parse_mon_cb);
1669 }
1670
1671 static int
1672 parse_mday_cb(VALUE m, VALUE hash)
1673 {
1674 VALUE d;
1675
1676 d = rb_reg_nth_match(1, m);
1677 set_hash("mday", str2num(d));
1678 return 1;
1679 }
1680
1681 static int
1682 parse_mday(VALUE str, VALUE hash)
1683 {
1684 static const char pat_source[] =
1685 #ifndef TIGHT_PARSER
1686 "(\\d+)(st|nd|rd|th)\\b"
1687 #else
1688 BOS
1689 FPW_COM FPT_COM
1690 "(\\d+)(st|nd|rd|th)"
1691 COM_FPT COM_FPW
1692 EOS
1693 #endif
1694 ;
1695 static VALUE pat = Qnil;
1696
1697 REGCOMP_I(pat);
1698 SUBS(str, pat, parse_mday_cb);
1699 }
1700
1701 static int
1702 n2i(const char *s, long f, long w)
1703 {
1704 long e, i;
1705 int v;
1706
1707 e = f + w;
1708 v = 0;
1709 for (i = f; i < e; i++) {
1710 v *= 10;
1711 v += s[i] - '0';
1712 }
1713 return v;
1714 }
1715
1716 static int
1717 parse_ddd_cb(VALUE m, VALUE hash)
1718 {
1719 VALUE s1, s2, s3, s4, s5;
1720 const char *cs2, *cs3, *cs5;
1721 long l2, l3, l4, l5;
1722
1723 s1 = rb_reg_nth_match(1, m);
1724 s2 = rb_reg_nth_match(2, m);
1725 s3 = rb_reg_nth_match(3, m);
1726 s4 = rb_reg_nth_match(4, m);
1727 s5 = rb_reg_nth_match(5, m);
1728
1729 cs2 = RSTRING_PTR(s2);
1730 l2 = RSTRING_LEN(s2);
1731
1732 switch (l2) {
1733 case 2:
1734 if (NIL_P(s3) && !NIL_P(s4))
1735 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1736 else
1737 set_hash("mday", INT2FIX(n2i(cs2, 0, 2)));
1738 break;
1739 case 4:
1740 if (NIL_P(s3) && !NIL_P(s4)) {
1741 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1742 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1743 }
1744 else {
1745 set_hash("mon", INT2FIX(n2i(cs2, 0, 2)));
1746 set_hash("mday", INT2FIX(n2i(cs2, 2, 2)));
1747 }
1748 break;
1749 case 6:
1750 if (NIL_P(s3) && !NIL_P(s4)) {
1751 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1752 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1753 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1754 }
1755 else {
1756 int y = n2i(cs2, 0, 2);
1757 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1758 y = -y;
1759 set_hash("year", INT2FIX(y));
1760 set_hash("mon", INT2FIX(n2i(cs2, 2, 2)));
1761 set_hash("mday", INT2FIX(n2i(cs2, 4, 2)));
1762 }
1763 break;
1764 case 8:
1765 case 10:
1766 case 12:
1767 case 14:
1768 if (NIL_P(s3) && !NIL_P(s4)) {
1769 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1770 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1771 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1772 set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2)));
1773 if (l2 >= 10)
1774 set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2)));
1775 if (l2 == 12) {
1776 int y = n2i(cs2, l2-12, 2);
1777 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1778 y = -y;
1779 set_hash("year", INT2FIX(y));
1780 }
1781 if (l2 == 14) {
1782 int y = n2i(cs2, l2-14, 4);
1783 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1784 y = -y;
1785 set_hash("year", INT2FIX(y));
1786 set_hash("_comp", Qfalse);
1787 }
1788 }
1789 else {
1790 int y = n2i(cs2, 0, 4);
1791 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1792 y = -y;
1793 set_hash("year", INT2FIX(y));
1794 set_hash("mon", INT2FIX(n2i(cs2, 4, 2)));
1795 set_hash("mday", INT2FIX(n2i(cs2, 6, 2)));
1796 if (l2 >= 10)
1797 set_hash("hour", INT2FIX(n2i(cs2, 8, 2)));
1798 if (l2 >= 12)
1799 set_hash("min", INT2FIX(n2i(cs2, 10, 2)));
1800 if (l2 >= 14)
1801 set_hash("sec", INT2FIX(n2i(cs2, 12, 2)));
1802 set_hash("_comp", Qfalse);
1803 }
1804 break;
1805 case 3:
1806 if (NIL_P(s3) && !NIL_P(s4)) {
1807 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1808 set_hash("min", INT2FIX(n2i(cs2, l2-3, 1)));
1809 }
1810 else
1811 set_hash("yday", INT2FIX(n2i(cs2, 0, 3)));
1812 break;
1813 case 5:
1814 if (NIL_P(s3) && !NIL_P(s4)) {
1815 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1816 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1817 set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1)));
1818 }
1819 else {
1820 int y = n2i(cs2, 0, 2);
1821 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1822 y = -y;
1823 set_hash("year", INT2FIX(y));
1824 set_hash("yday", INT2FIX(n2i(cs2, 2, 3)));
1825 }
1826 break;
1827 case 7:
1828 if (NIL_P(s3) && !NIL_P(s4)) {
1829 set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2)));
1830 set_hash("min", INT2FIX(n2i(cs2, l2-4, 2)));
1831 set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2)));
1832 set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1)));
1833 }
1834 else {
1835 int y = n2i(cs2, 0, 4);
1836 if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-')
1837 y = -y;
1838 set_hash("year", INT2FIX(y));
1839 set_hash("yday", INT2FIX(n2i(cs2, 4, 3)));
1840 }
1841 break;
1842 }
1843 RB_GC_GUARD(s2);
1844 if (!NIL_P(s3)) {
1845 cs3 = RSTRING_PTR(s3);
1846 l3 = RSTRING_LEN(s3);
1847
1848 if (!NIL_P(s4)) {
1849 switch (l3) {
1850 case 2:
1851 case 4:
1852 case 6:
1853 set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2)));
1854 if (l3 >= 4)
1855 set_hash("min", INT2FIX(n2i(cs3, l3-4, 2)));
1856 if (l3 >= 6)
1857 set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2)));
1858 break;
1859 }
1860 }
1861 else {
1862 switch (l3) {
1863 case 2:
1864 case 4:
1865 case 6:
1866 set_hash("hour", INT2FIX(n2i(cs3, 0, 2)));
1867 if (l3 >= 4)
1868 set_hash("min", INT2FIX(n2i(cs3, 2, 2)));
1869 if (l3 >= 6)
1870 set_hash("sec", INT2FIX(n2i(cs3, 4, 2)));
1871 break;
1872 }
1873 }
1874 RB_GC_GUARD(s3);
1875 }
1876 if (!NIL_P(s4)) {
1877 l4 = RSTRING_LEN(s4);
1878
1879 set_hash("sec_fraction",
1880 rb_rational_new2(str2num(s4),
1881 f_expt(INT2FIX(10), LONG2NUM(l4))));
1882 }
1883 if (!NIL_P(s5)) {
1884 cs5 = RSTRING_PTR(s5);
1885 l5 = RSTRING_LEN(s5);
1886
1887 set_hash("zone", s5);
1888
1889 if (*cs5 == '[') {
1890 const char *s1, *s2;
1891 VALUE zone;
1892
1893 l5 -= 2;
1894 s1 = cs5 + 1;
1895 s2 = memchr(s1, ':', l5);
1896 if (s2) {
1897 s2++;
1898 zone = rb_str_subseq(s5, s2 - cs5, l5 - (s2 - s1));
1899 s5 = rb_str_subseq(s5, 1, s2 - s1);
1900 }
1901 else {
1902 zone = rb_str_subseq(s5, 1, l5);
1903 if (isdigit((unsigned char)*s1))
1904 s5 = rb_str_append(rb_str_new_cstr("+"), zone);
1905 else
1906 s5 = zone;
1907 }
1908 set_hash("zone", zone);
1909 set_hash("offset", date_zone_to_diff(s5));
1910 }
1911 RB_GC_GUARD(s5);
1912 }
1913
1914 return 1;
1915 }
1916
1917 static int
1918 parse_ddd(VALUE str, VALUE hash)
1919 {
1920 static const char pat_source[] =
1921 #ifdef TIGHT_PARSER
1922 BOS
1923 #endif
1924 "([-+]?)(\\d{2,14})"
1925 "(?:"
1926 "\\s*"
1927 "t?"
1928 "\\s*"
1929 "(\\d{2,6})?(?:[,.](\\d*))?"
1930 ")?"
1931 "(?:"
1932 "\\s*"
1933 "("
1934 "z\\b"
1935 "|"
1936 "[-+]\\d{1,4}\\b"
1937 "|"
1938 "\\[[-+]?\\d[^\\]]*\\]"
1939 ")"
1940 ")?"
1941 #ifdef TIGHT_PARSER
1942 EOS
1943 #endif
1944 ;
1945 static VALUE pat = Qnil;
1946
1947 REGCOMP_I(pat);
1948 SUBS(str, pat, parse_ddd_cb);
1949 }
1950
1951 #ifndef TIGHT_PARSER
1952 static int
1953 parse_bc_cb(VALUE m, VALUE hash)
1954 {
1955 set_hash("_bc", Qtrue);
1956 return 1;
1957 }
1958
1959 static int
1960 parse_bc(VALUE str, VALUE hash)
1961 {
1962 static const char pat_source[] =
1963 "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)";
1964 static VALUE pat = Qnil;
1965
1966 REGCOMP_I(pat);
1967 SUBS(str, pat, parse_bc_cb);
1968 }
1969
1970 static int
1971 parse_frag_cb(VALUE m, VALUE hash)
1972 {
1973 VALUE s, n;
1974
1975 s = rb_reg_nth_match(1, m);
1976
1977 if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) {
1978 n = str2num(s);
1979 if (f_ge_p(n, INT2FIX(1)) &&
1980 f_le_p(n, INT2FIX(31)))
1981 set_hash("mday", n);
1982 }
1983 if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) {
1984 n = str2num(s);
1985 if (f_ge_p(n, INT2FIX(0)) &&
1986 f_le_p(n, INT2FIX(24)))
1987 set_hash("hour", n);
1988 }
1989
1990 return 1;
1991 }
1992
1993 static int
1994 parse_frag(VALUE str, VALUE hash)
1995 {
1996 static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z";
1997 static VALUE pat = Qnil;
1998
1999 REGCOMP_I(pat);
2000 SUBS(str, pat, parse_frag_cb);
2001 }
2002 #endif
2003
2004 #ifdef TIGHT_PARSER
2005 static int
2006 parse_dummy_cb(VALUE m, VALUE hash)
2007 {
2008 return 1;
2009 }
2010
2011 static int
2012 parse_wday_only(VALUE str, VALUE hash)
2013 {
2014 static const char pat_source[] = "\\A\\s*" FPW "\\s*\\z";
2015 static VALUE pat = Qnil;
2016
2017 REGCOMP_0(pat);
2018 SUBS(str, pat, parse_dummy_cb);
2019 }
2020
2021 static int
2022 parse_time_only(VALUE str, VALUE hash)
2023 {
2024 static const char pat_source[] = "\\A\\s*" FPT "\\s*\\z";
2025 static VALUE pat = Qnil;
2026
2027 REGCOMP_0(pat);
2028 SUBS(str, pat, parse_dummy_cb);
2029 }
2030
2031 static int
2032 parse_wday_and_time(VALUE str, VALUE hash)
2033 {
2034 static const char pat_source[] = "\\A\\s*(" FPW "\\s+" FPT "|" FPT "\\s+" FPW ")\\s*\\z";
2035 static VALUE pat = Qnil;
2036
2037 REGCOMP_0(pat);
2038 SUBS(str, pat, parse_dummy_cb);
2039 }
2040
2041 static unsigned
2042 have_invalid_char_p(VALUE s)
2043 {
2044 long i;
2045
2046 for (i = 0; i < RSTRING_LEN(s); i++)
2047 if (iscntrl((unsigned char)RSTRING_PTR(s)[i]) &&
2048 !isspace((unsigned char)RSTRING_PTR(s)[i]))
2049 return 1;
2050 return 0;
2051 }
2052 #endif
2053
2054 #define HAVE_ALPHA (1<<0)
2055 #define HAVE_DIGIT (1<<1)
2056 #define HAVE_DASH (1<<2)
2057 #define HAVE_DOT (1<<3)
2058 #define HAVE_SLASH (1<<4)
2059
2060 static unsigned
2061 check_class(VALUE s)
2062 {
2063 unsigned flags;
2064 long i;
2065
2066 flags = 0;
2067 for (i = 0; i < RSTRING_LEN(s); i++) {
2068 if (isalpha((unsigned char)RSTRING_PTR(s)[i]))
2069 flags |= HAVE_ALPHA;
2070 if (isdigit((unsigned char)RSTRING_PTR(s)[i]))
2071 flags |= HAVE_DIGIT;
2072 if (RSTRING_PTR(s)[i] == '-')
2073 flags |= HAVE_DASH;
2074 if (RSTRING_PTR(s)[i] == '.')
2075 flags |= HAVE_DOT;
2076 if (RSTRING_PTR(s)[i] == '/')
2077 flags |= HAVE_SLASH;
2078 }
2079 return flags;
2080 }
2081
2082 #define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x))
2083
2084 #ifdef TIGHT_PARSER
2085 #define PARSER_ERROR return rb_hash_new()
2086 #endif
2087
2088 VALUE
2089 date__parse(VALUE str, VALUE comp)
2090 {
2091 VALUE backref, hash;
2092
2093 #ifdef TIGHT_PARSER
2094 if (have_invalid_char_p(str))
2095 PARSER_ERROR;
2096 #endif
2097
2098 backref = rb_backref_get();
2099 rb_match_busy(backref);
2100
2101 {
2102 static const char pat_source[] =
2103 #ifndef TIGHT_PARSER
2104 "[^-+',./:@[:alnum:]\\[\\]]+"
2105 #else
2106 "[^[:graph:]]+"
2107 #endif
2108 ;
2109 static VALUE pat = Qnil;
2110
2111 REGCOMP_0(pat);
2112 str = rb_str_dup(str);
2113 f_gsub_bang(str, pat, asp_string());
2114 }
2115
2116 hash = rb_hash_new();
2117 set_hash("_comp", comp);
2118
2119 if (HAVE_ELEM_P(HAVE_ALPHA))
2120 parse_day(str, hash);
2121 if (HAVE_ELEM_P(HAVE_DIGIT))
2122 parse_time(str, hash);
2123
2124 #ifdef TIGHT_PARSER
2125 if (HAVE_ELEM_P(HAVE_ALPHA))
2126 parse_era(str, hash);
2127 #endif
2128
2129 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) {
2130 if (parse_eu(str, hash))
2131 goto ok;
2132 if (parse_us(str, hash))
2133 goto ok;
2134 }
2135 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH))
2136 if (parse_iso(str, hash))
2137 goto ok;
2138 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
2139 if (parse_jis(str, hash))
2140 goto ok;
2141 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH))
2142 if (parse_vms(str, hash))
2143 goto ok;
2144 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH))
2145 if (parse_sla(str, hash))
2146 goto ok;
2147 #ifdef TIGHT_PARSER
2148 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_SLASH)) {
2149 if (parse_sla2(str, hash))
2150 goto ok;
2151 if (parse_sla3(str, hash))
2152 goto ok;
2153 }
2154 #endif
2155 if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT))
2156 if (parse_dot(str, hash))
2157 goto ok;
2158 #ifdef TIGHT_PARSER
2159 if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DOT)) {
2160 if (parse_dot2(str, hash))
2161 goto ok;
2162 if (parse_dot3(str, hash))
2163 goto ok;
2164 }
2165 #endif
2166 if (HAVE_ELEM_P(HAVE_DIGIT))
2167 if (parse_iso2(str, hash))
2168 goto ok;
2169 if (HAVE_ELEM_P(HAVE_DIGIT))
2170 if (parse_year(str, hash))
2171 goto ok;
2172 if (HAVE_ELEM_P(HAVE_ALPHA))
2173 if (parse_mon(str, hash))
2174 goto ok;
2175 if (HAVE_ELEM_P(HAVE_DIGIT))
2176 if (parse_mday(str, hash))
2177 goto ok;
2178 if (HAVE_ELEM_P(HAVE_DIGIT))
2179 if (parse_ddd(str, hash))
2180 goto ok;
2181
2182 #ifdef TIGHT_PARSER
2183 if (parse_wday_only(str, hash))
2184 goto ok;
2185 if (parse_time_only(str, hash))
2186 goto ok;
2187 if (parse_wday_and_time(str, hash))
2188 goto ok;
2189
2190 PARSER_ERROR; /* not found */
2191 #endif
2192
2193 ok:
2194 #ifndef TIGHT_PARSER
2195 if (HAVE_ELEM_P(HAVE_ALPHA))
2196 parse_bc(str, hash);
2197 if (HAVE_ELEM_P(HAVE_DIGIT))
2198 parse_frag(str, hash);
2199 #endif
2200
2201 {
2202 if (RTEST(del_hash("_bc"))) {
2203 VALUE y;
2204
2205 y = ref_hash("cwyear");
2206 if (!NIL_P(y)) {
2207 y = f_add(f_negate(y), INT2FIX(1));
2208 set_hash("cwyear", y);
2209 }
2210 y = ref_hash("year");
2211 if (!NIL_P(y)) {
2212 y = f_add(f_negate(y), INT2FIX(1));
2213 set_hash("year", y);
2214 }
2215 }
2216
2217 if (RTEST(del_hash("_comp"))) {
2218 VALUE y;
2219
2220 y = ref_hash("cwyear");
2221 if (!NIL_P(y))
2222 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2223 if (f_ge_p(y, INT2FIX(69)))
2224 set_hash("cwyear", f_add(y, INT2FIX(1900)));
2225 else
2226 set_hash("cwyear", f_add(y, INT2FIX(2000)));
2227 }
2228 y = ref_hash("year");
2229 if (!NIL_P(y))
2230 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) {
2231 if (f_ge_p(y, INT2FIX(69)))
2232 set_hash("year", f_add(y, INT2FIX(1900)));
2233 else
2234 set_hash("year", f_add(y, INT2FIX(2000)));
2235 }
2236 }
2237
2238 }
2239
2240 {
2241 VALUE zone = ref_hash("zone");
2242 if (!NIL_P(zone) && NIL_P(ref_hash("offset")))
2243 set_hash("offset", date_zone_to_diff(zone));
2244 }
2245
2246 rb_backref_set(backref);
2247
2248 return hash;
2249 }
2250
2251 static VALUE
2252 comp_year69(VALUE y)
2253 {
2254 if (f_ge_p(y, INT2FIX(69)))
2255 return f_add(y, INT2FIX(1900));
2256 return f_add(y, INT2FIX(2000));
2257 }
2258
2259 static VALUE
2260 comp_year50(VALUE y)
2261 {
2262 if (f_ge_p(y, INT2FIX(50)))
2263 return f_add(y, INT2FIX(1900));
2264 return f_add(y, INT2FIX(2000));
2265 }
2266
2267 static VALUE
2268 sec_fraction(VALUE f)
2269 {
2270 return rb_rational_new2(str2num(f),
2271 f_expt(INT2FIX(10),
2272 LONG2NUM(RSTRING_LEN(f))));
2273 }
2274
2275 #define SNUM 14
2276
2277 static int
2278 iso8601_ext_datetime_cb(VALUE m, VALUE hash)
2279 {
2280 VALUE s[SNUM + 1], y;
2281
2282 {
2283 int i;
2284 s[0] = Qnil;
2285 for (i = 1; i <= SNUM; i++)
2286 s[i] = rb_reg_nth_match(i, m);
2287 }
2288
2289 if (!NIL_P(s[1])) {
2290 if (!NIL_P(s[3])) set_hash("mday", str2num(s[3]));
2291 if (strcmp(RSTRING_PTR(s[1]), "-") != 0) {
2292 y = str2num(s[1]);
2293 if (RSTRING_LEN(s[1]) < 4)
2294 y = comp_year69(y);
2295 set_hash("year", y);
2296 }
2297 if (NIL_P(s[2])) {
2298 if (strcmp(RSTRING_PTR(s[1]), "-") != 0)
2299 return 0;
2300 }
2301 else
2302 set_hash("mon", str2num(s[2]));
2303 }
2304 else if (!NIL_P(s[5])) {
2305 set_hash("yday", str2num(s[5]));
2306 if (!NIL_P(s[4])) {
2307 y = str2num(s[4]);
2308 if (RSTRING_LEN(s[4]) < 4)
2309 y = comp_year69(y);
2310 set_hash("year", y);
2311 }
2312 }
2313 else if (!NIL_P(s[8])) {
2314 set_hash("cweek", str2num(s[7]));
2315 set_hash("cwday", str2num(s[8]));
2316 if (!NIL_P(s[6])) {
2317 y = str2num(s[6]);
2318 if (RSTRING_LEN(s[6]) < 4)
2319 y = comp_year69(y);
2320 set_hash("cwyear", y);
2321 }
2322 }
2323 else if (!NIL_P(s[9])) {
2324 set_hash("cwday", str2num(s[9]));
2325 }
2326 if (!NIL_P(s[10])) {
2327 set_hash("hour", str2num(s[10]));
2328 set_hash("min", str2num(s[11]));
2329 if (!NIL_P(s[12]))
2330 set_hash("sec", str2num(s[12]));
2331 }
2332 if (!NIL_P(s[13])) {
2333 set_hash("sec_fraction", sec_fraction(s[13]));
2334 }
2335 if (!NIL_P(s[14])) {
2336 set_hash("zone", s[14]);
2337 set_hash("offset", date_zone_to_diff(s[14]));
2338 }
2339
2340 return 1;
2341 }
2342
2343 static int
2344 iso8601_ext_datetime(VALUE str, VALUE hash)
2345 {
2346 static const char pat_source[] =
2347 "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?(?:-(\\d{2}))?|"
2348 "([-+]?\\d{2,})?-(\\d{3})|"
2349 "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|"
2350 "-w-(\\d))"
2351 "(?:t"
2352 "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?"
2353 "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z";
2354 static VALUE pat = Qnil;
2355
2356 REGCOMP_I(pat);
2357 MATCH(str, pat, iso8601_ext_datetime_cb);
2358 }
2359
2360 #undef SNUM
2361 #define SNUM 17
2362
2363 static int
2364 iso8601_bas_datetime_cb(VALUE m, VALUE hash)
2365 {
2366 VALUE s[SNUM + 1], y;
2367
2368 {
2369 int i;
2370 s[0] = Qnil;
2371 for (i = 1; i <= SNUM; i++)
2372 s[i] = rb_reg_nth_match(i, m);
2373 }
2374
2375 if (!NIL_P(s[3])) {
2376 set_hash("mday", str2num(s[3]));
2377 if (strcmp(RSTRING_PTR(s[1]), "--") != 0) {
2378 y = str2num(s[1]);
2379 if (RSTRING_LEN(s[1]) < 4)
2380 y = comp_year69(y);
2381 set_hash("year", y);
2382 }
2383 if (*RSTRING_PTR(s[2]) == '-') {
2384 if (strcmp(RSTRING_PTR(s[1]), "--") != 0)
2385 return 0;
2386 }
2387 else
2388 set_hash("mon", str2num(s[2]));
2389 }
2390 else if (!NIL_P(s[5])) {
2391 set_hash("yday", str2num(s[5]));
2392 y = str2num(s[4]);
2393 if (RSTRING_LEN(s[4]) < 4)
2394 y = comp_year69(y);
2395 set_hash("year", y);
2396 }
2397 else if (!NIL_P(s[6])) {
2398 set_hash("yday", str2num(s[6]));
2399 }
2400 else if (!NIL_P(s[9])) {
2401 set_hash("cweek", str2num(s[8]));
2402 set_hash("cwday", str2num(s[9]));
2403 y = str2num(s[7]);
2404 if (RSTRING_LEN(s[7]) < 4)
2405 y = comp_year69(y);
2406 set_hash("cwyear", y);
2407 }
2408 else if (!NIL_P(s[11])) {
2409 set_hash("cweek", str2num(s[10]));
2410 set_hash("cwday", str2num(s[11]));
2411 }
2412 else if (!NIL_P(s[12])) {
2413 set_hash("cwday", str2num(s[12]));
2414 }
2415 if (!NIL_P(s[13])) {
2416 set_hash("hour", str2num(s[13]));
2417 set_hash("min", str2num(s[14]));
2418 if (!NIL_P(s[15]))
2419 set_hash("sec", str2num(s[15]));
2420 }
2421 if (!NIL_P(s[16])) {
2422 set_hash("sec_fraction", sec_fraction(s[16]));
2423 }
2424 if (!NIL_P(s[17])) {
2425 set_hash("zone", s[17]);
2426 set_hash("offset", date_zone_to_diff(s[17]));
2427 }
2428
2429 return 1;
2430 }
2431
2432 static int
2433 iso8601_bas_datetime(VALUE str, VALUE hash)
2434 {
2435 static const char pat_source[] =
2436 "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|"
2437 "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|"
2438 "-(\\d{3})|"
2439 "(\\d{4}|\\d{2})w(\\d{2})(\\d)|"
2440 "-w(\\d{2})(\\d)|"
2441 "-w-(\\d))"
2442 "(?:t?"
2443 "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?"
2444 "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z";
2445 static VALUE pat = Qnil;
2446
2447 REGCOMP_I(pat);
2448 MATCH(str, pat, iso8601_bas_datetime_cb);
2449 }
2450
2451 #undef SNUM
2452 #define SNUM 5
2453
2454 static int
2455 iso8601_ext_time_cb(VALUE m, VALUE hash)
2456 {
2457 VALUE s[SNUM + 1];
2458
2459 {
2460 int i;
2461 s[0] = Qnil;
2462 for (i = 1; i <= SNUM; i++)
2463 s[i] = rb_reg_nth_match(i, m);
2464 }
2465
2466 set_hash("hour", str2num(s[1]));
2467 set_hash("min", str2num(s[2]));
2468 if (!NIL_P(s[3]))
2469 set_hash("sec", str2num(s[3]));
2470 if (!NIL_P(s[4]))
2471 set_hash("sec_fraction", sec_fraction(s[4]));
2472 if (!NIL_P(s[5])) {
2473 set_hash("zone", s[5]);
2474 set_hash("offset", date_zone_to_diff(s[5]));
2475 }
2476
2477 return 1;
2478 }
2479
2480 #define iso8601_bas_time_cb iso8601_ext_time_cb
2481
2482 static int
2483 iso8601_ext_time(VALUE str, VALUE hash)
2484 {
2485 static const char pat_source[] =
2486 "\\A\\s*(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?"
2487 "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z";
2488 static VALUE pat = Qnil;
2489
2490 REGCOMP_I(pat);
2491 MATCH(str, pat, iso8601_ext_time_cb);
2492 }
2493
2494 static int
2495 iso8601_bas_time(VALUE str, VALUE hash)
2496 {
2497 static const char pat_source[] =
2498 "\\A\\s*(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?"
2499 "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z";
2500 static VALUE pat = Qnil;
2501
2502 REGCOMP_I(pat);
2503 MATCH(str, pat, iso8601_bas_time_cb);
2504 }
2505
2506 VALUE
2507 date__iso8601(VALUE str)
2508 {
2509 VALUE backref, hash;
2510
2511 backref = rb_backref_get();
2512 rb_match_busy(backref);
2513
2514 hash = rb_hash_new();
2515
2516 if (iso8601_ext_datetime(str, hash))
2517 goto ok;
2518 if (iso8601_bas_datetime(str, hash))
2519 goto ok;
2520 if (iso8601_ext_time(str, hash))
2521 goto ok;
2522 if (iso8601_bas_time(str, hash))
2523 goto ok;
2524
2525 ok:
2526 rb_backref_set(backref);
2527
2528 return hash;
2529 }
2530
2531 #undef SNUM
2532 #define SNUM 8
2533
2534 static int
2535 rfc3339_cb(VALUE m, VALUE hash)
2536 {
2537 VALUE s[SNUM + 1];
2538
2539 {
2540 int i;
2541 s[0] = Qnil;
2542 for (i = 1; i <= SNUM; i++)
2543 s[i] = rb_reg_nth_match(i, m);
2544 }
2545
2546 set_hash("year", str2num(s[1]));
2547 set_hash("mon", str2num(s[2]));
2548 set_hash("mday", str2num(s[3]));
2549 set_hash("hour", str2num(s[4]));
2550 set_hash("min", str2num(s[5]));
2551 set_hash("sec", str2num(s[6]));
2552 set_hash("zone", s[8]);
2553 set_hash("offset", date_zone_to_diff(s[8]));
2554 if (!NIL_P(s[7]))
2555 set_hash("sec_fraction", sec_fraction(s[7]));
2556
2557 return 1;
2558 }
2559
2560 static int
2561 rfc3339(VALUE str, VALUE hash)
2562 {
2563 static const char pat_source[] =
2564 "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})"
2565 "(?:t|\\s)"
2566 "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2567 "(z|[-+]\\d{2}:\\d{2})\\s*\\z";
2568 static VALUE pat = Qnil;
2569
2570 REGCOMP_I(pat);
2571 MATCH(str, pat, rfc3339_cb);
2572 }
2573
2574 VALUE
2575 date__rfc3339(VALUE str)
2576 {
2577 VALUE backref, hash;
2578
2579 backref = rb_backref_get();
2580 rb_match_busy(backref);
2581
2582 hash = rb_hash_new();
2583 rfc3339(str, hash);
2584 rb_backref_set(backref);
2585 return hash;
2586 }
2587
2588 #undef SNUM
2589 #define SNUM 8
2590
2591 static int
2592 xmlschema_datetime_cb(VALUE m, VALUE hash)
2593 {
2594 VALUE s[SNUM + 1];
2595
2596 {
2597 int i;
2598 s[0] = Qnil;
2599 for (i = 1; i <= SNUM; i++)
2600 s[i] = rb_reg_nth_match(i, m);
2601 }
2602
2603 set_hash("year", str2num(s[1]));
2604 if (!NIL_P(s[2]))
2605 set_hash("mon", str2num(s[2]));
2606 if (!NIL_P(s[3]))
2607 set_hash("mday", str2num(s[3]));
2608 if (!NIL_P(s[4]))
2609 set_hash("hour", str2num(s[4]));
2610 if (!NIL_P(s[5]))
2611 set_hash("min", str2num(s[5]));
2612 if (!NIL_P(s[6]))
2613 set_hash("sec", str2num(s[6]));
2614 if (!NIL_P(s[7]))
2615 set_hash("sec_fraction", sec_fraction(s[7]));
2616 if (!NIL_P(s[8])) {
2617 set_hash("zone", s[8]);
2618 set_hash("offset", date_zone_to_diff(s[8]));
2619 }
2620
2621 return 1;
2622 }
2623
2624 static int
2625 xmlschema_datetime(VALUE str, VALUE hash)
2626 {
2627 static const char pat_source[] =
2628 "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?"
2629 "(?:t"
2630 "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?"
2631 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2632 static VALUE pat = Qnil;
2633
2634 REGCOMP_I(pat);
2635 MATCH(str, pat, xmlschema_datetime_cb);
2636 }
2637
2638 #undef SNUM
2639 #define SNUM 5
2640
2641 static int
2642 xmlschema_time_cb(VALUE m, VALUE hash)
2643 {
2644 VALUE s[SNUM + 1];
2645
2646 {
2647 int i;
2648 s[0] = Qnil;
2649 for (i = 1; i <= SNUM; i++)
2650 s[i] = rb_reg_nth_match(i, m);
2651 }
2652
2653 set_hash("hour", str2num(s[1]));
2654 set_hash("min", str2num(s[2]));
2655 if (!NIL_P(s[3]))
2656 set_hash("sec", str2num(s[3]));
2657 if (!NIL_P(s[4]))
2658 set_hash("sec_fraction", sec_fraction(s[4]));
2659 if (!NIL_P(s[5])) {
2660 set_hash("zone", s[5]);
2661 set_hash("offset", date_zone_to_diff(s[5]));
2662 }
2663
2664 return 1;
2665 }
2666
2667 static int
2668 xmlschema_time(VALUE str, VALUE hash)
2669 {
2670 static const char pat_source[] =
2671 "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
2672 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2673 static VALUE pat = Qnil;
2674
2675 REGCOMP_I(pat);
2676 MATCH(str, pat, xmlschema_time_cb);
2677 }
2678
2679 #undef SNUM
2680 #define SNUM 4
2681
2682 static int
2683 xmlschema_trunc_cb(VALUE m, VALUE hash)
2684 {
2685 VALUE s[SNUM + 1];
2686
2687 {
2688 int i;
2689 s[0] = Qnil;
2690 for (i = 1; i <= SNUM; i++)
2691 s[i] = rb_reg_nth_match(i, m);
2692 }
2693
2694 if (!NIL_P(s[1]))
2695 set_hash("mon", str2num(s[1]));
2696 if (!NIL_P(s[2]))
2697 set_hash("mday", str2num(s[2]));
2698 if (!NIL_P(s[3]))
2699 set_hash("mday", str2num(s[3]));
2700 if (!NIL_P(s[4])) {
2701 set_hash("zone", s[4]);
2702 set_hash("offset", date_zone_to_diff(s[4]));
2703 }
2704
2705 return 1;
2706 }
2707
2708 static int
2709 xmlschema_trunc(VALUE str, VALUE hash)
2710 {
2711 static const char pat_source[] =
2712 "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))"
2713 "(z|[-+]\\d{2}:\\d{2})?\\s*\\z";
2714 static VALUE pat = Qnil;
2715
2716 REGCOMP_I(pat);
2717 MATCH(str, pat, xmlschema_trunc_cb);
2718 }
2719
2720 VALUE
2721 date__xmlschema(VALUE str)
2722 {
2723 VALUE backref, hash;
2724
2725 backref = rb_backref_get();
2726 rb_match_busy(backref);
2727
2728 hash = rb_hash_new();
2729
2730 if (xmlschema_datetime(str, hash))
2731 goto ok;
2732 if (xmlschema_time(str, hash))
2733 goto ok;
2734 if (xmlschema_trunc(str, hash))
2735 goto ok;
2736
2737 ok:
2738 rb_backref_set(backref);
2739
2740 return hash;
2741 }
2742
2743 #undef SNUM
2744 #define SNUM 8
2745
2746 static int
2747 rfc2822_cb(VALUE m, VALUE hash)
2748 {
2749 VALUE s[SNUM + 1], y;
2750
2751 {
2752 int i;
2753 s[0] = Qnil;
2754 for (i = 1; i <= SNUM; i++)
2755 s[i] = rb_reg_nth_match(i, m);
2756 }
2757
2758 if (!NIL_P(s[1])) {
2759 set_hash("wday", INT2FIX(day_num(s[1])));
2760 }
2761 set_hash("mday", str2num(s[2]));
2762 set_hash("mon", INT2FIX(mon_num(s[3])));
2763 y = str2num(s[4]);
2764 if (RSTRING_LEN(s[4]) < 4)
2765 y = comp_year50(y);
2766 set_hash("year", y);
2767 set_hash("hour", str2num(s[5]));
2768 set_hash("min", str2num(s[6]));
2769 if (!NIL_P(s[7]))
2770 set_hash("sec", str2num(s[7]));
2771 set_hash("zone", s[8]);
2772 set_hash("offset", date_zone_to_diff(s[8]));
2773
2774 return 1;
2775 }
2776
2777 static int
2778 rfc2822(VALUE str, VALUE hash)
2779 {
2780 static const char pat_source[] =
2781 "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?"
2782 "(\\d{1,2})\\s+"
2783 "(" ABBR_MONTHS ")\\s+"
2784 "(-?\\d{2,})\\s+"
2785 "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*"
2786 "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z";
2787 static VALUE pat = Qnil;
2788
2789 REGCOMP_I(pat);
2790 MATCH(str, pat, rfc2822_cb);
2791 }
2792
2793 VALUE
2794 date__rfc2822(VALUE str)
2795 {
2796 VALUE backref, hash;
2797
2798 backref = rb_backref_get();
2799 rb_match_busy(backref);
2800
2801 hash = rb_hash_new();
2802 rfc2822(str, hash);
2803 rb_backref_set(backref);
2804 return hash;
2805 }
2806
2807 #undef SNUM
2808 #define SNUM 8
2809
2810 static int
2811 httpdate_type1_cb(VALUE m, VALUE hash)
2812 {
2813 VALUE s[SNUM + 1];
2814
2815 {
2816 int i;
2817 s[0] = Qnil;
2818 for (i = 1; i <= SNUM; i++)
2819 s[i] = rb_reg_nth_match(i, m);
2820 }
2821
2822 set_hash("wday", INT2FIX(day_num(s[1])));
2823 set_hash("mday", str2num(s[2]));
2824 set_hash("mon", INT2FIX(mon_num(s[3])));
2825 set_hash("year", str2num(s[4]));
2826 set_hash("hour", str2num(s[5]));
2827 set_hash("min", str2num(s[6]));
2828 set_hash("sec", str2num(s[7]));
2829 set_hash("zone", s[8]);
2830 set_hash("offset", INT2FIX(0));
2831
2832 return 1;
2833 }
2834
2835 static int
2836 httpdate_type1(VALUE str, VALUE hash)
2837 {
2838 static const char pat_source[] =
2839 "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+"
2840 "(\\d{2})\\s+"
2841 "(" ABBR_MONTHS ")\\s+"
2842 "(-?\\d{4})\\s+"
2843 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2844 "(gmt)\\s*\\z";
2845 static VALUE pat = Qnil;
2846
2847 REGCOMP_I(pat);
2848 MATCH(str, pat, httpdate_type1_cb);
2849 }
2850
2851 #undef SNUM
2852 #define SNUM 8
2853
2854 static int
2855 httpdate_type2_cb(VALUE m, VALUE hash)
2856 {
2857 VALUE s[SNUM + 1], y;
2858
2859 {
2860 int i;
2861 s[0] = Qnil;
2862 for (i = 1; i <= SNUM; i++)
2863 s[i] = rb_reg_nth_match(i, m);
2864 }
2865
2866 set_hash("wday", INT2FIX(day_num(s[1])));
2867 set_hash("mday", str2num(s[2]));
2868 set_hash("mon", INT2FIX(mon_num(s[3])));
2869 y = str2num(s[4]);
2870 if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99)))
2871 y = comp_year69(y);
2872 set_hash("year", y);
2873 set_hash("hour", str2num(s[5]));
2874 set_hash("min", str2num(s[6]));
2875 set_hash("sec", str2num(s[7]));
2876 set_hash("zone", s[8]);
2877 set_hash("offset", INT2FIX(0));
2878
2879 return 1;
2880 }
2881
2882 static int
2883 httpdate_type2(VALUE str, VALUE hash)
2884 {
2885 static const char pat_source[] =
2886 "\\A\\s*(" DAYS ")\\s*,\\s+"
2887 "(\\d{2})\\s*-\\s*"
2888 "(" ABBR_MONTHS ")\\s*-\\s*"
2889 "(\\d{2})\\s+"
2890 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2891 "(gmt)\\s*\\z";
2892 static VALUE pat = Qnil;
2893
2894 REGCOMP_I(pat);
2895 MATCH(str, pat, httpdate_type2_cb);
2896 }
2897
2898 #undef SNUM
2899 #define SNUM 7
2900
2901 static int
2902 httpdate_type3_cb(VALUE m, VALUE hash)
2903 {
2904 VALUE s[SNUM + 1];
2905
2906 {
2907 int i;
2908 s[0] = Qnil;
2909 for (i = 1; i <= SNUM; i++)
2910 s[i] = rb_reg_nth_match(i, m);
2911 }
2912
2913 set_hash("wday", INT2FIX(day_num(s[1])));
2914 set_hash("mon", INT2FIX(mon_num(s[2])));
2915 set_hash("mday", str2num(s[3]));
2916 set_hash("hour", str2num(s[4]));
2917 set_hash("min", str2num(s[5]));
2918 set_hash("sec", str2num(s[6]));
2919 set_hash("year", str2num(s[7]));
2920
2921 return 1;
2922 }
2923
2924 static int
2925 httpdate_type3(VALUE str, VALUE hash)
2926 {
2927 static const char pat_source[] =
2928 "\\A\\s*(" ABBR_DAYS ")\\s+"
2929 "(" ABBR_MONTHS ")\\s+"
2930 "(\\d{1,2})\\s+"
2931 "(\\d{2}):(\\d{2}):(\\d{2})\\s+"
2932 "(\\d{4})\\s*\\z";
2933 static VALUE pat = Qnil;
2934
2935 REGCOMP_I(pat);
2936 MATCH(str, pat, httpdate_type3_cb);
2937 }
2938
2939 VALUE
2940 date__httpdate(VALUE str)
2941 {
2942 VALUE backref, hash;
2943
2944 backref = rb_backref_get();
2945 rb_match_busy(backref);
2946
2947 hash = rb_hash_new();
2948
2949 if (httpdate_type1(str, hash))
2950 goto ok;
2951 if (httpdate_type2(str, hash))
2952 goto ok;
2953 if (httpdate_type3(str, hash))
2954 goto ok;
2955
2956 ok:
2957 rb_backref_set(backref);
2958
2959 return hash;
2960 }
2961
2962 #undef SNUM
2963 #define SNUM 9
2964
2965 static int
2966 jisx0301_cb(VALUE m, VALUE hash)
2967 {
2968 VALUE s[SNUM + 1];
2969 int ep;
2970
2971 {
2972 int i;
2973 s[0] = Qnil;
2974 for (i = 1; i <= SNUM; i++)
2975 s[i] = rb_reg_nth_match(i, m);
2976 }
2977
2978 ep = gengo(NIL_P(s[1]) ? JISX0301_DEFAULT_ERA : *RSTRING_PTR(s[1]));
2979 set_hash("year", f_add(str2num(s[2]), INT2FIX(ep)));
2980 set_hash("mon", str2num(s[3]));
2981 set_hash("mday", str2num(s[4]));
2982 if (!NIL_P(s[5])) {
2983 set_hash("hour", str2num(s[5]));
2984 if (!NIL_P(s[6]))
2985 set_hash("min", str2num(s[6]));
2986 if (!NIL_P(s[7]))
2987 set_hash("sec", str2num(s[7]));
2988 }
2989 if (!NIL_P(s[8]))
2990 set_hash("sec_fraction", sec_fraction(s[8]));
2991 if (!NIL_P(s[9])) {
2992 set_hash("zone", s[9]);
2993 set_hash("offset", date_zone_to_diff(s[9]));
2994 }
2995
2996 return 1;
2997 }
2998
2999 static int
3000 jisx0301(VALUE str, VALUE hash)
3001 {
3002 static const char pat_source[] =
3003 "\\A\\s*([" JISX0301_ERA_INITIALS "])?(\\d{2})\\.(\\d{2})\\.(\\d{2})"
3004 "(?:t"
3005 "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?"
3006 "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z";
3007 static VALUE pat = Qnil;
3008
3009 REGCOMP_I(pat);
3010 MATCH(str, pat, jisx0301_cb);
3011 }
3012
3013 VALUE
3014 date__jisx0301(VALUE str)
3015 {
3016 VALUE backref, hash;
3017
3018 backref = rb_backref_get();
3019 rb_match_busy(backref);
3020
3021 hash = rb_hash_new();
3022 if (jisx0301(str, hash))
3023 goto ok;
3024 hash = date__iso8601(str);
3025
3026 ok:
3027 rb_backref_set(backref);
3028 return hash;
3029 }
3030
3031 /*
3032 Local variables:
3033 c-file-style: "ruby"
3034 End:
3035 */
zonetab
const struct zone * zonetab(register const char *str, register size_t len)
Definition: zonetab.h:806
rb_match_busy
void rb_match_busy(VALUE)
Definition: re.c:1287
HAVE_DOT
#define HAVE_DOT
REGCOMP_0
#define REGCOMP_0(pat)
Definition: date_parse.c:289
id
const int id
Definition: nkf.c:209
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1501
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
FPT
#define FPT
Definition: vsnprintf.c:537
date_zone_to_diff
VALUE date_zone_to_diff(VALUE str)
Definition: date_parse.c:410
date__jisx0301
VALUE date__jisx0301(VALUE)
HAVE_DASH
#define HAVE_DASH
asp_string
#define asp_string()
Definition: date_parse.c:61
MAX_WORD_LENGTH
#define MAX_WORD_LENGTH
Definition: zonetab.h:45
strncasecmp
int strncasecmp(const char *, const char *, size_t) __attribute__((__pure__))
ABBR_DAYS
#define ABBR_DAYS
Definition: date_parse.c:253
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
bp
#define bp()
Definition: internal.h:1445
JISX0301_DEFAULT_ERA
#define JISX0301_DEFAULT_ERA
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
re.h
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_int_positive_pow
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:4033
VALUE
unsigned long VALUE
Definition: ruby.h:102
encoding.h
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
date__rfc3339
VALUE date__rfc3339(VALUE)
f_to_s
#define f_to_s(x)
Definition: date_parse.c:31
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
HAVE_ELEM_P
#define HAVE_ELEM_P(x)
iso8601_bas_time_cb
#define iso8601_bas_time_cb
zone
Definition: zonetab.h:35
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
SNUM
#define SNUM
Qfalse
#define Qfalse
Definition: ruby.h:467
HAVE_DIGIT
#define HAVE_DIGIT
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.0.h:1329
MATCH
#define MATCH(s, p, c)
Definition: date_parse.c:292
sizeof_array
#define sizeof_array(o)
Definition: date_parse.c:15
rb_reg_new
VALUE rb_reg_new(const char *, long, int)
Definition: re.c:2946
strlen
size_t strlen(const char *)
set_hash
#define set_hash(k, v)
Definition: date_parse.c:43
ref_hash
#define ref_hash(k)
Definition: date_parse.c:44
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
f_ge_p
#define f_ge_p(x, y)
Definition: date_parse.c:29
rb_rational_new2
#define rb_rational_new2(x, y)
Definition: intern.h:180
issign
#define issign(c)
Definition: date_parse.c:60
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
SUBS
#define SUBS(s, p, c)
Definition: date_parse.c:334
f_aset2
#define f_aset2(o, i, j, v)
Definition: date_parse.c:39
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
REGCOMP_I
#define REGCOMP_I(pat)
Definition: date_parse.c:290
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
ABBR_MONTHS
#define ABBR_MONTHS
Definition: date_parse.c:254
ruby.h
f_begin
#define f_begin(o, i)
Definition: date_parse.c:36
f_negate
#define f_negate(x)
Definition: date_parse.c:17
date__parse
VALUE date__parse(VALUE str, VALUE comp)
rb_backref_get
VALUE rb_backref_get(void)
Definition: vm.c:1304
STRTOUL
#define STRTOUL(str, endptr, base)
Definition: ruby.h:2327
ruby_scan_digits
RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Definition: util.c:97
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
rb_backref_set
void rb_backref_set(VALUE)
Definition: vm.c:1310
zone::offset
int offset
Definition: zonetab.h:37
strcmp
int strcmp(const char *, const char *)
rb_rational_new
VALUE rb_rational_new(VALUE, VALUE)
Definition: rational.c:1945
date__rfc2822
VALUE date__rfc2822(VALUE)
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
str2num
#define str2num(s)
Definition: date_parse.c:48
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
f_match
#define f_match(r, s)
Definition: date_parse.c:33
f
#define f
DAYS
#define DAYS
Definition: date_parse.c:251
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
f_add
#define f_add(x, y)
Definition: date_parse.c:18
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
date__httpdate
VALUE date__httpdate(VALUE)
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
zonetab.h
HAVE_ALPHA
#define HAVE_ALPHA
RUBY_EXTERN
#define RUBY_EXTERN
Definition: missing.h:77
JISX0301_ERA_INITIALS
#define JISX0301_ERA_INITIALS
s2
const char * s2
Definition: rb_mjit_min_header-2.7.0.h:5454
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
rb_reg_nth_match
VALUE rb_reg_nth_match(int, VALUE)
Definition: re.c:1706
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
date__iso8601
VALUE date__iso8601(VALUE)
HAVE_SLASH
#define HAVE_SLASH
T_STRING
#define T_STRING
Definition: ruby.h:528
date__xmlschema
VALUE date__xmlschema(VALUE)
f_gsub_bang
#define f_gsub_bang(s, r, x)
Definition: date_parse.c:41
del_hash
#define del_hash(k)
Definition: date_parse.c:45
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
f_end
#define f_end(o, i)
Definition: date_parse.c:37
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.0.h:5462
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
f_le_p
#define f_le_p(x, y)
Definition: date_parse.c:28
RTEST
#define RTEST(v)
Definition: ruby.h:481
f_expt
#define f_expt(x, y)
Definition: date_parse.c:24
cstr2num
#define cstr2num(s)
Definition: date_parse.c:47
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
memchr
void * memchr(const void *, int, size_t)