Ruby: ext/date/date_parse.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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