ydate 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ */