ydate 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3035 @@
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((unsigned char)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((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
+
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((unsigned char)s[l - n - 1])) return 0;
368
+ if (strncasecmp(&s[l - n], w, n)) return 0;
369
+ do ++n; while (l > n && isspace((unsigned char)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((unsigned char)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((unsigned char)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((unsigned char)s[1])) return 0;
758
+ return (l == 2 || !isdigit((unsigned char)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
+ */