date 2.0.0 → 3.0.2

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.
data/ext/date/date_core.c CHANGED
@@ -11,6 +11,7 @@
11
11
  #include <sys/time.h>
12
12
  #endif
13
13
 
14
+ #undef NDEBUG
14
15
  #define NDEBUG
15
16
  #include <assert.h>
16
17
 
@@ -22,6 +23,7 @@
22
23
 
23
24
  static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
24
25
  static VALUE cDate, cDateTime;
26
+ static VALUE eDateError;
25
27
  static VALUE half_days_in_day, day_in_nanoseconds;
26
28
  static double positive_inf, negative_inf;
27
29
 
@@ -54,6 +56,14 @@ static double positive_inf, negative_inf;
54
56
  static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
55
57
  static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
56
58
 
59
+ #define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse
60
+ inline static void
61
+ check_numeric(VALUE obj, const char* field) {
62
+ if(!RTEST(rb_obj_is_kind_of(obj, rb_cNumeric))) {
63
+ rb_raise(rb_eTypeError, "invalid %s (not numeric)", field);
64
+ }
65
+ }
66
+
57
67
  inline static int
58
68
  f_cmp(VALUE x, VALUE y)
59
69
  {
@@ -2470,6 +2480,7 @@ date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
2470
2480
 
2471
2481
  rb_scan_args(argc, argv, "11", &vjd, &vsg);
2472
2482
 
2483
+ RETURN_FALSE_UNLESS_NUMERIC(vjd);
2473
2484
  argv2[0] = vjd;
2474
2485
  if (argc < 2)
2475
2486
  argv2[1] = INT2FIX(DEFAULT_SG);
@@ -2545,9 +2556,12 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
2545
2556
  * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool
2546
2557
  *
2547
2558
  * Returns true if the given calendar date is valid, and false if not.
2559
+ * Valid in this context is whether the arguments passed to this
2560
+ * method would be accepted by ::new.
2548
2561
  *
2549
2562
  * Date.valid_date?(2001,2,3) #=> true
2550
2563
  * Date.valid_date?(2001,2,29) #=> false
2564
+ * Date.valid_date?(2001,2,-1) #=> true
2551
2565
  *
2552
2566
  * See also ::jd and ::civil.
2553
2567
  */
@@ -2559,6 +2573,9 @@ date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
2559
2573
 
2560
2574
  rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2561
2575
 
2576
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2577
+ RETURN_FALSE_UNLESS_NUMERIC(vm);
2578
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2562
2579
  argv2[0] = vy;
2563
2580
  argv2[1] = vm;
2564
2581
  argv2[2] = vd;
@@ -2640,6 +2657,8 @@ date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2640
2657
 
2641
2658
  rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2642
2659
 
2660
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2661
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2643
2662
  argv2[0] = vy;
2644
2663
  argv2[1] = vd;
2645
2664
  if (argc < 3)
@@ -2722,6 +2741,9 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2722
2741
 
2723
2742
  rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2724
2743
 
2744
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2745
+ RETURN_FALSE_UNLESS_NUMERIC(vw);
2746
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2725
2747
  argv2[0] = vy;
2726
2748
  argv2[1] = vw;
2727
2749
  argv2[2] = vd;
@@ -2903,6 +2925,7 @@ date_s_julian_leap_p(VALUE klass, VALUE y)
2903
2925
  VALUE nth;
2904
2926
  int ry;
2905
2927
 
2928
+ check_numeric(y, "year");
2906
2929
  decode_year(y, +1, &nth, &ry);
2907
2930
  return f_boolcast(c_julian_leap_p(ry));
2908
2931
  }
@@ -2924,6 +2947,7 @@ date_s_gregorian_leap_p(VALUE klass, VALUE y)
2924
2947
  VALUE nth;
2925
2948
  int ry;
2926
2949
 
2950
+ check_numeric(y, "year");
2927
2951
  decode_year(y, -1, &nth, &ry);
2928
2952
  return f_boolcast(c_gregorian_leap_p(ry));
2929
2953
  }
@@ -3047,7 +3071,7 @@ old_to_new(VALUE ajd, VALUE of, VALUE sg,
3047
3071
  *rsg = NUM2DBL(sg);
3048
3072
 
3049
3073
  if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
3050
- rb_raise(rb_eArgError, "invalid day fraction");
3074
+ rb_raise(eDateError, "invalid day fraction");
3051
3075
 
3052
3076
  if (f_lt_p(*rsf, INT2FIX(0)) ||
3053
3077
  f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
@@ -3209,7 +3233,7 @@ do {\
3209
3233
  s = s##_trunc(v##s, &fr);\
3210
3234
  if (f_nonzero_p(fr)) {\
3211
3235
  if (argc > n)\
3212
- rb_raise(rb_eArgError, "invalid fraction");\
3236
+ rb_raise(eDateError, "invalid fraction");\
3213
3237
  fr2 = fr;\
3214
3238
  }\
3215
3239
  } while (0)
@@ -3219,7 +3243,7 @@ do {\
3219
3243
  s = NUM2INT(s##_trunc(v##s, &fr));\
3220
3244
  if (f_nonzero_p(fr)) {\
3221
3245
  if (argc > n)\
3222
- rb_raise(rb_eArgError, "invalid fraction");\
3246
+ rb_raise(eDateError, "invalid fraction");\
3223
3247
  fr2 = fr;\
3224
3248
  }\
3225
3249
  } while (0)
@@ -3278,6 +3302,7 @@ date_s_jd(int argc, VALUE *argv, VALUE klass)
3278
3302
  case 2:
3279
3303
  val2sg(vsg, sg);
3280
3304
  case 1:
3305
+ check_numeric(vjd, "jd");
3281
3306
  num2num_with_frac(jd, positive_inf);
3282
3307
  }
3283
3308
 
@@ -3330,8 +3355,10 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3330
3355
  case 3:
3331
3356
  val2sg(vsg, sg);
3332
3357
  case 2:
3358
+ check_numeric(vd, "yday");
3333
3359
  num2int_with_frac(d, positive_inf);
3334
3360
  case 1:
3361
+ check_numeric(vy, "year");
3335
3362
  y = vy;
3336
3363
  }
3337
3364
 
@@ -3343,7 +3370,7 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3343
3370
  &nth, &ry,
3344
3371
  &rd, &rjd,
3345
3372
  &ns))
3346
- rb_raise(rb_eArgError, "invalid date");
3373
+ rb_raise(eDateError, "invalid date");
3347
3374
 
3348
3375
  ret = d_simple_new_internal(klass,
3349
3376
  nth, rjd,
@@ -3410,10 +3437,13 @@ date_initialize(int argc, VALUE *argv, VALUE self)
3410
3437
  case 4:
3411
3438
  val2sg(vsg, sg);
3412
3439
  case 3:
3440
+ check_numeric(vd, "day");
3413
3441
  num2int_with_frac(d, positive_inf);
3414
3442
  case 2:
3443
+ check_numeric(vm, "month");
3415
3444
  m = NUM2INT(vm);
3416
3445
  case 1:
3446
+ check_numeric(vy, "year");
3417
3447
  y = vy;
3418
3448
  }
3419
3449
 
@@ -3424,7 +3454,7 @@ date_initialize(int argc, VALUE *argv, VALUE self)
3424
3454
  if (!valid_gregorian_p(y, m, d,
3425
3455
  &nth, &ry,
3426
3456
  &rm, &rd))
3427
- rb_raise(rb_eArgError, "invalid date");
3457
+ rb_raise(eDateError, "invalid date");
3428
3458
 
3429
3459
  set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
3430
3460
  }
@@ -3436,7 +3466,7 @@ date_initialize(int argc, VALUE *argv, VALUE self)
3436
3466
  &nth, &ry,
3437
3467
  &rm, &rd, &rjd,
3438
3468
  &ns))
3439
- rb_raise(rb_eArgError, "invalid date");
3469
+ rb_raise(eDateError, "invalid date");
3440
3470
 
3441
3471
  set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
3442
3472
  }
@@ -3480,10 +3510,13 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
3480
3510
  case 4:
3481
3511
  val2sg(vsg, sg);
3482
3512
  case 3:
3513
+ check_numeric(vd, "cwday");
3483
3514
  num2int_with_frac(d, positive_inf);
3484
3515
  case 2:
3516
+ check_numeric(vw, "cweek");
3485
3517
  w = NUM2INT(vw);
3486
3518
  case 1:
3519
+ check_numeric(vy, "year");
3487
3520
  y = vy;
3488
3521
  }
3489
3522
 
@@ -3495,7 +3528,7 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
3495
3528
  &nth, &ry,
3496
3529
  &rw, &rd, &rjd,
3497
3530
  &ns))
3498
- rb_raise(rb_eArgError, "invalid date");
3531
+ rb_raise(eDateError, "invalid date");
3499
3532
 
3500
3533
  ret = d_simple_new_internal(klass,
3501
3534
  nth, rjd,
@@ -3545,7 +3578,7 @@ date_s_weeknum(int argc, VALUE *argv, VALUE klass)
3545
3578
  &nth, &ry,
3546
3579
  &rw, &rd, &rjd,
3547
3580
  &ns))
3548
- rb_raise(rb_eArgError, "invalid date");
3581
+ rb_raise(eDateError, "invalid date");
3549
3582
 
3550
3583
  ret = d_simple_new_internal(klass,
3551
3584
  nth, rjd,
@@ -3594,7 +3627,7 @@ date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
3594
3627
  &nth, &ry,
3595
3628
  &rm, &rn, &rk, &rjd,
3596
3629
  &ns))
3597
- rb_raise(rb_eArgError, "invalid date");
3630
+ rb_raise(eDateError, "invalid date");
3598
3631
 
3599
3632
  ret = d_simple_new_internal(klass,
3600
3633
  nth, rjd,
@@ -3692,7 +3725,7 @@ rt_rewrite_frags(VALUE hash)
3692
3725
  {
3693
3726
  VALUE seconds;
3694
3727
 
3695
- seconds = ref_hash("seconds");
3728
+ seconds = del_hash("seconds");
3696
3729
  if (!NIL_P(seconds)) {
3697
3730
  VALUE offset, d, h, min, s, fr;
3698
3731
 
@@ -3717,7 +3750,6 @@ rt_rewrite_frags(VALUE hash)
3717
3750
  set_hash("min", min);
3718
3751
  set_hash("sec", s);
3719
3752
  set_hash("sec_fraction", fr);
3720
- del_hash("seconds");
3721
3753
  }
3722
3754
  return hash;
3723
3755
  }
@@ -4142,7 +4174,7 @@ d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4142
4174
  }
4143
4175
 
4144
4176
  if (NIL_P(hash))
4145
- rb_raise(rb_eArgError, "invalid date");
4177
+ rb_raise(eDateError, "invalid date");
4146
4178
 
4147
4179
  if (NIL_P(ref_hash("jd")) &&
4148
4180
  NIL_P(ref_hash("yday")) &&
@@ -4159,7 +4191,7 @@ d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4159
4191
  }
4160
4192
 
4161
4193
  if (NIL_P(jd))
4162
- rb_raise(rb_eArgError, "invalid date");
4194
+ rb_raise(eDateError, "invalid date");
4163
4195
  {
4164
4196
  VALUE nth;
4165
4197
  int rjd;
@@ -4214,12 +4246,10 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
4214
4246
 
4215
4247
  if (!NIL_P(zone)) {
4216
4248
  rb_enc_copy(zone, vstr);
4217
- OBJ_INFECT(zone, vstr);
4218
4249
  set_hash("zone", zone);
4219
4250
  }
4220
4251
  if (!NIL_P(left)) {
4221
4252
  rb_enc_copy(left, vstr);
4222
- OBJ_INFECT(left, vstr);
4223
4253
  set_hash("leftover", left);
4224
4254
  }
4225
4255
  }
@@ -4292,12 +4322,37 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass)
4292
4322
 
4293
4323
  VALUE date__parse(VALUE str, VALUE comp);
4294
4324
 
4325
+ static size_t
4326
+ get_limit(VALUE opt)
4327
+ {
4328
+ if (!NIL_P(opt)) {
4329
+ VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit")));
4330
+ if (NIL_P(limit)) return SIZE_MAX;
4331
+ return NUM2SIZET(limit);
4332
+ }
4333
+ return 128;
4334
+ }
4335
+
4336
+ static void
4337
+ check_limit(VALUE str, VALUE opt)
4338
+ {
4339
+ StringValue(str);
4340
+ size_t slen = RSTRING_LEN(str);
4341
+ size_t limit = get_limit(opt);
4342
+ if (slen > limit) {
4343
+ rb_raise(rb_eArgError,
4344
+ "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
4345
+ }
4346
+ }
4347
+
4295
4348
  static VALUE
4296
4349
  date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4297
4350
  {
4298
- VALUE vstr, vcomp, hash;
4351
+ VALUE vstr, vcomp, hash, opt;
4299
4352
 
4300
- rb_scan_args(argc, argv, "11", &vstr, &vcomp);
4353
+ rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
4354
+ if (!NIL_P(opt)) argc--;
4355
+ check_limit(vstr, opt);
4301
4356
  StringValue(vstr);
4302
4357
  if (!rb_enc_str_asciicompat_p(vstr))
4303
4358
  rb_raise(rb_eArgError,
@@ -4307,22 +4362,12 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4307
4362
 
4308
4363
  hash = date__parse(vstr, vcomp);
4309
4364
 
4310
- {
4311
- VALUE zone = ref_hash("zone");
4312
-
4313
- if (!NIL_P(zone)) {
4314
- rb_enc_copy(zone, vstr);
4315
- OBJ_INFECT(zone, vstr);
4316
- set_hash("zone", zone);
4317
- }
4318
- }
4319
-
4320
4365
  return hash;
4321
4366
  }
4322
4367
 
4323
4368
  /*
4324
4369
  * call-seq:
4325
- * Date._parse(string[, comp=true]) -> hash
4370
+ * Date._parse(string[, comp=true], limit: 128) -> hash
4326
4371
  *
4327
4372
  * Parses the given representation of date and time, and returns a
4328
4373
  * hash of parsed elements. This method does not function as a
@@ -4333,6 +4378,10 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4333
4378
  * it full.
4334
4379
  *
4335
4380
  * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3}
4381
+ *
4382
+ * Raise an ArgumentError when the string length is longer than _limit_.
4383
+ * You can stop this check by passing `limit: nil`, but note that
4384
+ * it may take a long time to parse.
4336
4385
  */
4337
4386
  static VALUE
4338
4387
  date_s__parse(int argc, VALUE *argv, VALUE klass)
@@ -4342,7 +4391,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
4342
4391
 
4343
4392
  /*
4344
4393
  * call-seq:
4345
- * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date
4394
+ * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128) -> date
4346
4395
  *
4347
4396
  * Parses the given representation of date and time, and creates a
4348
4397
  * date object. This method does not function as a validator.
@@ -4354,13 +4403,18 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
4354
4403
  * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
4355
4404
  * Date.parse('20010203') #=> #<Date: 2001-02-03 ...>
4356
4405
  * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...>
4406
+ *
4407
+ * Raise an ArgumentError when the string length is longer than _limit_.
4408
+ * You can stop this check by passing `limit: nil`, but note that
4409
+ * it may take a long time to parse.
4357
4410
  */
4358
4411
  static VALUE
4359
4412
  date_s_parse(int argc, VALUE *argv, VALUE klass)
4360
4413
  {
4361
- VALUE str, comp, sg;
4414
+ VALUE str, comp, sg, opt;
4362
4415
 
4363
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
4416
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
4417
+ if (!NIL_P(opt)) argc--;
4364
4418
 
4365
4419
  switch (argc) {
4366
4420
  case 0:
@@ -4372,11 +4426,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass)
4372
4426
  }
4373
4427
 
4374
4428
  {
4375
- VALUE argv2[2], hash;
4376
-
4377
- argv2[0] = str;
4378
- argv2[1] = comp;
4379
- hash = date_s__parse(2, argv2, klass);
4429
+ int argc2 = 2;
4430
+ VALUE argv2[3];
4431
+ argv2[0] = str;
4432
+ argv2[1] = comp;
4433
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4434
+ VALUE hash = date_s__parse(argc2, argv2, klass);
4380
4435
  return d_new_by_frags(klass, hash, sg);
4381
4436
  }
4382
4437
  }
@@ -4390,19 +4445,28 @@ VALUE date__jisx0301(VALUE);
4390
4445
 
4391
4446
  /*
4392
4447
  * call-seq:
4393
- * Date._iso8601(string) -> hash
4448
+ * Date._iso8601(string, limit: 128) -> hash
4394
4449
  *
4395
4450
  * Returns a hash of parsed elements.
4451
+ *
4452
+ * Raise an ArgumentError when the string length is longer than _limit_.
4453
+ * You can stop this check by passing `limit: nil`, but note that
4454
+ * it may take a long time to parse.
4396
4455
  */
4397
4456
  static VALUE
4398
- date_s__iso8601(VALUE klass, VALUE str)
4457
+ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
4399
4458
  {
4459
+ VALUE str, opt;
4460
+
4461
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4462
+ check_limit(str, opt);
4463
+
4400
4464
  return date__iso8601(str);
4401
4465
  }
4402
4466
 
4403
4467
  /*
4404
4468
  * call-seq:
4405
- * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date
4469
+ * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4406
4470
  *
4407
4471
  * Creates a new Date object by parsing from a string according to
4408
4472
  * some typical ISO 8601 formats.
@@ -4410,13 +4474,18 @@ date_s__iso8601(VALUE klass, VALUE str)
4410
4474
  * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...>
4411
4475
  * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...>
4412
4476
  * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...>
4477
+ *
4478
+ * Raise an ArgumentError when the string length is longer than _limit_.
4479
+ * You can stop this check by passing `limit: nil`, but note that
4480
+ * it may take a long time to parse.
4413
4481
  */
4414
4482
  static VALUE
4415
4483
  date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4416
4484
  {
4417
- VALUE str, sg;
4485
+ VALUE str, sg, opt;
4418
4486
 
4419
- rb_scan_args(argc, argv, "02", &str, &sg);
4487
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4488
+ if (!NIL_P(opt)) argc--;
4420
4489
 
4421
4490
  switch (argc) {
4422
4491
  case 0:
@@ -4426,38 +4495,56 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4426
4495
  }
4427
4496
 
4428
4497
  {
4429
- VALUE hash = date_s__iso8601(klass, str);
4498
+ int argc2 = 1;
4499
+ VALUE argv2[2];
4500
+ argv2[0] = str;
4501
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4502
+ VALUE hash = date_s__iso8601(argc2, argv2, klass);
4430
4503
  return d_new_by_frags(klass, hash, sg);
4431
4504
  }
4432
4505
  }
4433
4506
 
4434
4507
  /*
4435
4508
  * call-seq:
4436
- * Date._rfc3339(string) -> hash
4509
+ * Date._rfc3339(string, limit: 128) -> hash
4437
4510
  *
4438
4511
  * Returns a hash of parsed elements.
4512
+ *
4513
+ * Raise an ArgumentError when the string length is longer than _limit_.
4514
+ * You can stop this check by passing `limit: nil`, but note that
4515
+ * it may take a long time to parse.
4439
4516
  */
4440
4517
  static VALUE
4441
- date_s__rfc3339(VALUE klass, VALUE str)
4518
+ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
4442
4519
  {
4520
+ VALUE str, opt;
4521
+
4522
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4523
+ check_limit(str, opt);
4524
+
4443
4525
  return date__rfc3339(str);
4444
4526
  }
4445
4527
 
4446
4528
  /*
4447
4529
  * call-seq:
4448
- * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date
4530
+ * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> date
4449
4531
  *
4450
4532
  * Creates a new Date object by parsing from a string according to
4451
4533
  * some typical RFC 3339 formats.
4452
4534
  *
4453
4535
  * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
4536
+ *
4537
+ * Raise an ArgumentError when the string length is longer than _limit_.
4538
+ * You can stop this check by passing `limit: nil`, but note that
4539
+ * it may take a long time to parse.
4454
4540
  */
4455
4541
  static VALUE
4456
4542
  date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4457
4543
  {
4458
- VALUE str, sg;
4544
+ VALUE str, sg, opt;
4459
4545
 
4460
- rb_scan_args(argc, argv, "02", &str, &sg);
4546
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4547
+ if (!NIL_P(opt)) argc--;
4461
4548
 
4462
4549
  switch (argc) {
4463
4550
  case 0:
@@ -4467,38 +4554,56 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4467
4554
  }
4468
4555
 
4469
4556
  {
4470
- VALUE hash = date_s__rfc3339(klass, str);
4557
+ int argc2 = 1;
4558
+ VALUE argv2[2];
4559
+ argv2[0] = str;
4560
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4561
+ VALUE hash = date_s__rfc3339(argc2, argv2, klass);
4471
4562
  return d_new_by_frags(klass, hash, sg);
4472
4563
  }
4473
4564
  }
4474
4565
 
4475
4566
  /*
4476
4567
  * call-seq:
4477
- * Date._xmlschema(string) -> hash
4568
+ * Date._xmlschema(string, limit: 128) -> hash
4478
4569
  *
4479
4570
  * Returns a hash of parsed elements.
4571
+ *
4572
+ * Raise an ArgumentError when the string length is longer than _limit_.
4573
+ * You can stop this check by passing `limit: nil`, but note that
4574
+ * it may take a long time to parse.
4480
4575
  */
4481
4576
  static VALUE
4482
- date_s__xmlschema(VALUE klass, VALUE str)
4577
+ date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
4483
4578
  {
4579
+ VALUE str, opt;
4580
+
4581
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4582
+ check_limit(str, opt);
4583
+
4484
4584
  return date__xmlschema(str);
4485
4585
  }
4486
4586
 
4487
4587
  /*
4488
4588
  * call-seq:
4489
- * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date
4589
+ * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4490
4590
  *
4491
4591
  * Creates a new Date object by parsing from a string according to
4492
4592
  * some typical XML Schema formats.
4493
4593
  *
4494
4594
  * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...>
4595
+ *
4596
+ * Raise an ArgumentError when the string length is longer than _limit_.
4597
+ * You can stop this check by passing `limit: nil`, but note that
4598
+ * it may take a long time to parse.
4495
4599
  */
4496
4600
  static VALUE
4497
4601
  date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4498
4602
  {
4499
- VALUE str, sg;
4603
+ VALUE str, sg, opt;
4500
4604
 
4501
- rb_scan_args(argc, argv, "02", &str, &sg);
4605
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4606
+ if (!NIL_P(opt)) argc--;
4502
4607
 
4503
4608
  switch (argc) {
4504
4609
  case 0:
@@ -4508,41 +4613,58 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4508
4613
  }
4509
4614
 
4510
4615
  {
4511
- VALUE hash = date_s__xmlschema(klass, str);
4616
+ int argc2 = 1;
4617
+ VALUE argv2[2];
4618
+ argv2[0] = str;
4619
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4620
+ VALUE hash = date_s__xmlschema(argc2, argv2, klass);
4512
4621
  return d_new_by_frags(klass, hash, sg);
4513
4622
  }
4514
4623
  }
4515
4624
 
4516
4625
  /*
4517
4626
  * call-seq:
4518
- * Date._rfc2822(string) -> hash
4519
- * Date._rfc822(string) -> hash
4627
+ * Date._rfc2822(string, limit: 128) -> hash
4628
+ * Date._rfc822(string, limit: 128) -> hash
4520
4629
  *
4521
4630
  * Returns a hash of parsed elements.
4631
+ *
4632
+ * Raise an ArgumentError when the string length is longer than _limit_.
4633
+ * You can stop this check by passing `limit: nil`, but note that
4634
+ * it may take a long time to parse.
4522
4635
  */
4523
4636
  static VALUE
4524
- date_s__rfc2822(VALUE klass, VALUE str)
4637
+ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
4525
4638
  {
4639
+ VALUE str, opt;
4640
+
4641
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4642
+ check_limit(str, opt);
4643
+
4526
4644
  return date__rfc2822(str);
4527
4645
  }
4528
4646
 
4529
4647
  /*
4530
4648
  * call-seq:
4531
- * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4532
- * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4649
+ * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
4650
+ * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
4533
4651
  *
4534
4652
  * Creates a new Date object by parsing from a string according to
4535
4653
  * some typical RFC 2822 formats.
4536
4654
  *
4537
4655
  * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
4538
4656
  * #=> #<Date: 2001-02-03 ...>
4657
+ *
4658
+ * Raise an ArgumentError when the string length is longer than _limit_.
4659
+ * You can stop this check by passing `limit: nil`, but note that
4660
+ * it may take a long time to parse.
4539
4661
  */
4540
4662
  static VALUE
4541
4663
  date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4542
4664
  {
4543
- VALUE str, sg;
4665
+ VALUE str, sg, opt;
4544
4666
 
4545
- rb_scan_args(argc, argv, "02", &str, &sg);
4667
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4546
4668
 
4547
4669
  switch (argc) {
4548
4670
  case 0:
@@ -4552,39 +4674,56 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4552
4674
  }
4553
4675
 
4554
4676
  {
4555
- VALUE hash = date_s__rfc2822(klass, str);
4677
+ int argc2 = 1;
4678
+ VALUE argv2[2];
4679
+ argv2[0] = str;
4680
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4681
+ VALUE hash = date_s__rfc2822(argc2, argv2, klass);
4556
4682
  return d_new_by_frags(klass, hash, sg);
4557
4683
  }
4558
4684
  }
4559
4685
 
4560
4686
  /*
4561
4687
  * call-seq:
4562
- * Date._httpdate(string) -> hash
4688
+ * Date._httpdate(string, limit: 128) -> hash
4563
4689
  *
4564
4690
  * Returns a hash of parsed elements.
4691
+ *
4692
+ * Raise an ArgumentError when the string length is longer than _limit_.
4693
+ * You can stop this check by passing `limit: nil`, but note that
4694
+ * it may take a long time to parse.
4565
4695
  */
4566
4696
  static VALUE
4567
- date_s__httpdate(VALUE klass, VALUE str)
4697
+ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
4568
4698
  {
4699
+ VALUE str, opt;
4700
+
4701
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4702
+ check_limit(str, opt);
4703
+
4569
4704
  return date__httpdate(str);
4570
4705
  }
4571
4706
 
4572
4707
  /*
4573
4708
  * call-seq:
4574
- * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date
4709
+ * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY], limit: 128) -> date
4575
4710
  *
4576
4711
  * Creates a new Date object by parsing from a string according to
4577
4712
  * some RFC 2616 format.
4578
4713
  *
4579
4714
  * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
4580
4715
  * #=> #<Date: 2001-02-03 ...>
4716
+ *
4717
+ * Raise an ArgumentError when the string length is longer than _limit_.
4718
+ * You can stop this check by passing `limit: nil`, but note that
4719
+ * it may take a long time to parse.
4581
4720
  */
4582
4721
  static VALUE
4583
4722
  date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4584
4723
  {
4585
- VALUE str, sg;
4724
+ VALUE str, sg, opt;
4586
4725
 
4587
- rb_scan_args(argc, argv, "02", &str, &sg);
4726
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4588
4727
 
4589
4728
  switch (argc) {
4590
4729
  case 0:
@@ -4594,38 +4733,60 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4594
4733
  }
4595
4734
 
4596
4735
  {
4597
- VALUE hash = date_s__httpdate(klass, str);
4736
+ int argc2 = 1;
4737
+ VALUE argv2[2];
4738
+ argv2[0] = str;
4739
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4740
+ VALUE hash = date_s__httpdate(argc2, argv2, klass);
4598
4741
  return d_new_by_frags(klass, hash, sg);
4599
4742
  }
4600
4743
  }
4601
4744
 
4602
4745
  /*
4603
4746
  * call-seq:
4604
- * Date._jisx0301(string) -> hash
4747
+ * Date._jisx0301(string, limit: 128) -> hash
4605
4748
  *
4606
4749
  * Returns a hash of parsed elements.
4750
+ *
4751
+ * Raise an ArgumentError when the string length is longer than _limit_.
4752
+ * You can stop this check by passing `limit: nil`, but note that
4753
+ * it may take a long time to parse.
4607
4754
  */
4608
4755
  static VALUE
4609
- date_s__jisx0301(VALUE klass, VALUE str)
4756
+ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
4610
4757
  {
4758
+ VALUE str, opt;
4759
+
4760
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4761
+ check_limit(str, opt);
4762
+
4611
4763
  return date__jisx0301(str);
4612
4764
  }
4613
4765
 
4614
4766
  /*
4615
4767
  * call-seq:
4616
- * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date
4768
+ * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4617
4769
  *
4618
4770
  * Creates a new Date object by parsing from a string according to
4619
4771
  * some typical JIS X 0301 formats.
4620
4772
  *
4621
4773
  * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
4774
+ *
4775
+ * For no-era year, legacy format, Heisei is assumed.
4776
+ *
4777
+ * Date.jisx0301('13.02.03') #=> #<Date: 2001-02-03 ...>
4778
+ *
4779
+ * Raise an ArgumentError when the string length is longer than _limit_.
4780
+ * You can stop this check by passing `limit: nil`, but note that
4781
+ * it may take a long time to parse.
4622
4782
  */
4623
4783
  static VALUE
4624
4784
  date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4625
4785
  {
4626
- VALUE str, sg;
4786
+ VALUE str, sg, opt;
4627
4787
 
4628
- rb_scan_args(argc, argv, "02", &str, &sg);
4788
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4789
+ if (!NIL_P(opt)) argc--;
4629
4790
 
4630
4791
  switch (argc) {
4631
4792
  case 0:
@@ -4635,7 +4796,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4635
4796
  }
4636
4797
 
4637
4798
  {
4638
- VALUE hash = date_s__jisx0301(klass, str);
4799
+ int argc2 = 1;
4800
+ VALUE argv2[2];
4801
+ argv2[0] = str;
4802
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4803
+ VALUE hash = date_s__jisx0301(argc2, argv2, klass);
4639
4804
  return d_new_by_frags(klass, hash, sg);
4640
4805
  }
4641
4806
  }
@@ -4709,7 +4874,6 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4709
4874
  double sg;
4710
4875
 
4711
4876
  rb_check_frozen(self);
4712
- rb_check_trusted(self);
4713
4877
 
4714
4878
  rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
4715
4879
 
@@ -4728,11 +4892,11 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4728
4892
  sf = vsf;
4729
4893
  if (f_lt_p(sf, INT2FIX(0)) ||
4730
4894
  f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
4731
- rb_raise(rb_eArgError, "invalid second fraction");
4895
+ rb_raise(eDateError, "invalid second fraction");
4732
4896
  case 2:
4733
4897
  df = NUM2INT(vdf);
4734
4898
  if (df < 0 || df >= DAY_IN_SECONDS)
4735
- rb_raise(rb_eArgError, "invalid day fraction");
4899
+ rb_raise(eDateError, "invalid day fraction");
4736
4900
  case 1:
4737
4901
  jd = vjd;
4738
4902
  }
@@ -4765,7 +4929,6 @@ static VALUE
4765
4929
  d_lite_initialize_copy(VALUE copy, VALUE date)
4766
4930
  {
4767
4931
  rb_check_frozen(copy);
4768
- rb_check_trusted(copy);
4769
4932
 
4770
4933
  if (copy == date)
4771
4934
  return copy;
@@ -6043,7 +6206,7 @@ d_lite_rshift(VALUE self, VALUE other)
6043
6206
  &rm, &rd, &rjd, &ns))
6044
6207
  break;
6045
6208
  if (--d < 1)
6046
- rb_raise(rb_eArgError, "invalid date");
6209
+ rb_raise(eDateError, "invalid date");
6047
6210
  }
6048
6211
  encode_jd(nth, rjd, &rjd2);
6049
6212
  return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
@@ -6567,9 +6730,9 @@ mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
6567
6730
  * Returns the value as a string for inspection.
6568
6731
  *
6569
6732
  * Date.new(2001,2,3).inspect
6570
- * #=> "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>"
6733
+ * #=> "#<Date: 2001-02-03>"
6571
6734
  * DateTime.new(2001,2,3,4,5,6,'-7').inspect
6572
- * #=> "#<DateTime: 2001-02-03T04:05:06-07:00 ((2451944j,39906s,0n),-25200s,2299161j)>"
6735
+ * #=> "#<DateTime: 2001-02-03T04:05:06-07:00>"
6573
6736
  */
6574
6737
  static VALUE
6575
6738
  d_lite_inspect(VALUE self)
@@ -6738,7 +6901,6 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6738
6901
  if (p > fmt) rb_str_cat(str, fmt, p - fmt);
6739
6902
  }
6740
6903
  rb_enc_copy(str, vfmt);
6741
- OBJ_INFECT(str, vfmt);
6742
6904
  return str;
6743
6905
  }
6744
6906
  else
@@ -6747,7 +6909,6 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6747
6909
  str = rb_str_new(buf, len);
6748
6910
  if (buf != buffer) xfree(buf);
6749
6911
  rb_enc_copy(str, vfmt);
6750
- OBJ_INFECT(str, vfmt);
6751
6912
  return str;
6752
6913
  }
6753
6914
 
@@ -7046,10 +7207,14 @@ jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
7046
7207
  c = 'S';
7047
7208
  s = 1925;
7048
7209
  }
7049
- else {
7210
+ else if (d < 2458605) {
7050
7211
  c = 'H';
7051
7212
  s = 1988;
7052
7213
  }
7214
+ else {
7215
+ c = 'R';
7216
+ s = 2018;
7217
+ }
7053
7218
  snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s);
7054
7219
  return fmt;
7055
7220
  }
@@ -7134,7 +7299,6 @@ d_lite_marshal_load(VALUE self, VALUE a)
7134
7299
  get_d1(self);
7135
7300
 
7136
7301
  rb_check_frozen(self);
7137
- rb_check_trusted(self);
7138
7302
 
7139
7303
  if (!RB_TYPE_P(a, T_ARRAY))
7140
7304
  rb_raise(rb_eTypeError, "expected an array");
@@ -7179,11 +7343,14 @@ d_lite_marshal_load(VALUE self, VALUE a)
7179
7343
 
7180
7344
  if (simple_dat_p(dat)) {
7181
7345
  if (df || !f_zero_p(sf) || of) {
7182
- rb_raise(rb_eArgError,
7183
- "cannot load complex into simple");
7346
+ /* loading a fractional date; promote to complex */
7347
+ dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
7348
+ RTYPEDDATA(self)->data = dat;
7349
+ goto complex_data;
7184
7350
  }
7185
7351
  set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7186
7352
  } else {
7353
+ complex_data:
7187
7354
  set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
7188
7355
  0, 0, 0, 0, 0, 0,
7189
7356
  HAVE_JD | HAVE_DF);
@@ -7244,12 +7411,16 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7244
7411
  case 5:
7245
7412
  val2off(vof, rof);
7246
7413
  case 4:
7414
+ check_numeric(vs, "second");
7247
7415
  num2int_with_frac(s, positive_inf);
7248
7416
  case 3:
7417
+ check_numeric(vmin, "minute");
7249
7418
  num2int_with_frac(min, 3);
7250
7419
  case 2:
7420
+ check_numeric(vh, "hour");
7251
7421
  num2int_with_frac(h, 2);
7252
7422
  case 1:
7423
+ check_numeric(vjd, "jd");
7253
7424
  num2num_with_frac(jd, 1);
7254
7425
  }
7255
7426
 
@@ -7258,7 +7429,7 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7258
7429
  int rh, rmin, rs, rjd, rjd2;
7259
7430
 
7260
7431
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7261
- rb_raise(rb_eArgError, "invalid date");
7432
+ rb_raise(eDateError, "invalid date");
7262
7433
  canon24oc();
7263
7434
 
7264
7435
  decode_jd(jd, &nth, &rjd);
@@ -7313,14 +7484,19 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7313
7484
  case 6:
7314
7485
  val2off(vof, rof);
7315
7486
  case 5:
7487
+ check_numeric(vs, "second");
7316
7488
  num2int_with_frac(s, positive_inf);
7317
7489
  case 4:
7490
+ check_numeric(vmin, "minute");
7318
7491
  num2int_with_frac(min, 4);
7319
7492
  case 3:
7493
+ check_numeric(vh, "hour");
7320
7494
  num2int_with_frac(h, 3);
7321
7495
  case 2:
7496
+ check_numeric(vd, "yday");
7322
7497
  num2int_with_frac(d, 2);
7323
7498
  case 1:
7499
+ check_numeric(vy, "year");
7324
7500
  y = vy;
7325
7501
  }
7326
7502
 
@@ -7332,9 +7508,9 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7332
7508
  &nth, &ry,
7333
7509
  &rd, &rjd,
7334
7510
  &ns))
7335
- rb_raise(rb_eArgError, "invalid date");
7511
+ rb_raise(eDateError, "invalid date");
7336
7512
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7337
- rb_raise(rb_eArgError, "invalid date");
7513
+ rb_raise(eDateError, "invalid date");
7338
7514
  canon24oc();
7339
7515
 
7340
7516
  rjd2 = jd_local_to_utc(rjd,
@@ -7401,16 +7577,22 @@ datetime_initialize(int argc, VALUE *argv, VALUE self)
7401
7577
  case 7:
7402
7578
  val2off(vof, rof);
7403
7579
  case 6:
7580
+ check_numeric(vs, "second");
7404
7581
  num2int_with_frac(s, positive_inf);
7405
7582
  case 5:
7583
+ check_numeric(vmin, "minute");
7406
7584
  num2int_with_frac(min, 5);
7407
7585
  case 4:
7586
+ check_numeric(vh, "hour");
7408
7587
  num2int_with_frac(h, 4);
7409
7588
  case 3:
7589
+ check_numeric(vd, "day");
7410
7590
  num2int_with_frac(d, 3);
7411
7591
  case 2:
7592
+ check_numeric(vm, "month");
7412
7593
  m = NUM2INT(vm);
7413
7594
  case 1:
7595
+ check_numeric(vy, "year");
7414
7596
  y = vy;
7415
7597
  }
7416
7598
 
@@ -7421,9 +7603,9 @@ datetime_initialize(int argc, VALUE *argv, VALUE self)
7421
7603
  if (!valid_gregorian_p(y, m, d,
7422
7604
  &nth, &ry,
7423
7605
  &rm, &rd))
7424
- rb_raise(rb_eArgError, "invalid date");
7606
+ rb_raise(eDateError, "invalid date");
7425
7607
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7426
- rb_raise(rb_eArgError, "invalid date");
7608
+ rb_raise(eDateError, "invalid date");
7427
7609
  canon24oc();
7428
7610
 
7429
7611
  set_to_complex(self, dat,
@@ -7442,9 +7624,9 @@ datetime_initialize(int argc, VALUE *argv, VALUE self)
7442
7624
  &nth, &ry,
7443
7625
  &rm, &rd, &rjd,
7444
7626
  &ns))
7445
- rb_raise(rb_eArgError, "invalid date");
7627
+ rb_raise(eDateError, "invalid date");
7446
7628
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7447
- rb_raise(rb_eArgError, "invalid date");
7629
+ rb_raise(eDateError, "invalid date");
7448
7630
  canon24oc();
7449
7631
 
7450
7632
  rjd2 = jd_local_to_utc(rjd,
@@ -7499,16 +7681,22 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7499
7681
  case 7:
7500
7682
  val2off(vof, rof);
7501
7683
  case 6:
7684
+ check_numeric(vs, "second");
7502
7685
  num2int_with_frac(s, positive_inf);
7503
7686
  case 5:
7687
+ check_numeric(vmin, "minute");
7504
7688
  num2int_with_frac(min, 5);
7505
7689
  case 4:
7690
+ check_numeric(vh, "hour");
7506
7691
  num2int_with_frac(h, 4);
7507
7692
  case 3:
7693
+ check_numeric(vd, "cwday");
7508
7694
  num2int_with_frac(d, 3);
7509
7695
  case 2:
7696
+ check_numeric(vw, "cweek");
7510
7697
  w = NUM2INT(vw);
7511
7698
  case 1:
7699
+ check_numeric(vy, "year");
7512
7700
  y = vy;
7513
7701
  }
7514
7702
 
@@ -7520,9 +7708,9 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7520
7708
  &nth, &ry,
7521
7709
  &rw, &rd, &rjd,
7522
7710
  &ns))
7523
- rb_raise(rb_eArgError, "invalid date");
7711
+ rb_raise(eDateError, "invalid date");
7524
7712
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7525
- rb_raise(rb_eArgError, "invalid date");
7713
+ rb_raise(eDateError, "invalid date");
7526
7714
  canon24oc();
7527
7715
 
7528
7716
  rjd2 = jd_local_to_utc(rjd,
@@ -7591,9 +7779,9 @@ datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
7591
7779
  &nth, &ry,
7592
7780
  &rw, &rd, &rjd,
7593
7781
  &ns))
7594
- rb_raise(rb_eArgError, "invalid date");
7782
+ rb_raise(eDateError, "invalid date");
7595
7783
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7596
- rb_raise(rb_eArgError, "invalid date");
7784
+ rb_raise(eDateError, "invalid date");
7597
7785
  canon24oc();
7598
7786
 
7599
7787
  rjd2 = jd_local_to_utc(rjd,
@@ -7660,9 +7848,9 @@ datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
7660
7848
  &nth, &ry,
7661
7849
  &rm, &rn, &rk, &rjd,
7662
7850
  &ns))
7663
- rb_raise(rb_eArgError, "invalid date");
7851
+ rb_raise(eDateError, "invalid date");
7664
7852
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7665
- rb_raise(rb_eArgError, "invalid date");
7853
+ rb_raise(eDateError, "invalid date");
7666
7854
  canon24oc();
7667
7855
 
7668
7856
  rjd2 = jd_local_to_utc(rjd,
@@ -7805,7 +7993,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7805
7993
  }
7806
7994
 
7807
7995
  if (NIL_P(hash))
7808
- rb_raise(rb_eArgError, "invalid date");
7996
+ rb_raise(eDateError, "invalid date");
7809
7997
 
7810
7998
  if (NIL_P(ref_hash("jd")) &&
7811
7999
  NIL_P(ref_hash("yday")) &&
@@ -7832,7 +8020,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7832
8020
  }
7833
8021
 
7834
8022
  if (NIL_P(jd))
7835
- rb_raise(rb_eArgError, "invalid date");
8023
+ rb_raise(eDateError, "invalid date");
7836
8024
 
7837
8025
  {
7838
8026
  int rh, rmin, rs;
@@ -7841,7 +8029,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7841
8029
  NUM2INT(ref_hash("min")),
7842
8030
  NUM2INT(ref_hash("sec")),
7843
8031
  &rh, &rmin, &rs))
7844
- rb_raise(rb_eArgError, "invalid date");
8032
+ rb_raise(eDateError, "invalid date");
7845
8033
 
7846
8034
  df = time_to_df(rh, rmin, rs);
7847
8035
  }
@@ -7951,7 +8139,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7951
8139
 
7952
8140
  /*
7953
8141
  * call-seq:
7954
- * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime
8142
+ * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime
7955
8143
  *
7956
8144
  * Parses the given representation of date and time, and creates a
7957
8145
  * DateTime object. This method does not function as a validator.
@@ -7965,13 +8153,18 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7965
8153
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7966
8154
  * DateTime.parse('3rd Feb 2001 04:05:06 PM')
7967
8155
  * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
8156
+ *
8157
+ * Raise an ArgumentError when the string length is longer than _limit_.
8158
+ * You can stop this check by passing `limit: nil`, but note that
8159
+ * it may take a long time to parse.
7968
8160
  */
7969
8161
  static VALUE
7970
8162
  datetime_s_parse(int argc, VALUE *argv, VALUE klass)
7971
8163
  {
7972
- VALUE str, comp, sg;
8164
+ VALUE str, comp, sg, opt;
7973
8165
 
7974
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
8166
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
8167
+ if (!NIL_P(opt)) argc--;
7975
8168
 
7976
8169
  switch (argc) {
7977
8170
  case 0:
@@ -7983,18 +8176,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
7983
8176
  }
7984
8177
 
7985
8178
  {
7986
- VALUE argv2[2], hash;
7987
-
7988
- argv2[0] = str;
7989
- argv2[1] = comp;
7990
- hash = date_s__parse(2, argv2, klass);
8179
+ int argc2 = 2;
8180
+ VALUE argv2[3];
8181
+ argv2[0] = str;
8182
+ argv2[1] = comp;
8183
+ argv2[2] = opt;
8184
+ if (!NIL_P(opt)) argc2++;
8185
+ VALUE hash = date_s__parse(argc2, argv2, klass);
7991
8186
  return dt_new_by_frags(klass, hash, sg);
7992
8187
  }
7993
8188
  }
7994
8189
 
7995
8190
  /*
7996
8191
  * call-seq:
7997
- * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8192
+ * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
7998
8193
  *
7999
8194
  * Creates a new DateTime object by parsing from a string according to
8000
8195
  * some typical ISO 8601 formats.
@@ -8005,13 +8200,18 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
8005
8200
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8006
8201
  * DateTime.iso8601('2001-W05-6T04:05:06+07:00')
8007
8202
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8203
+ *
8204
+ * Raise an ArgumentError when the string length is longer than _limit_.
8205
+ * You can stop this check by passing `limit: nil`, but note that
8206
+ * it may take a long time to parse.
8008
8207
  */
8009
8208
  static VALUE
8010
8209
  datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
8011
8210
  {
8012
- VALUE str, sg;
8211
+ VALUE str, sg, opt;
8013
8212
 
8014
- rb_scan_args(argc, argv, "02", &str, &sg);
8213
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8214
+ if (!NIL_P(opt)) argc--;
8015
8215
 
8016
8216
  switch (argc) {
8017
8217
  case 0:
@@ -8021,27 +8221,37 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
8021
8221
  }
8022
8222
 
8023
8223
  {
8024
- VALUE hash = date_s__iso8601(klass, str);
8224
+ int argc2 = 1;
8225
+ VALUE argv2[2];
8226
+ argv2[0] = str;
8227
+ argv2[1] = opt;
8228
+ if (!NIL_P(opt)) argc2--;
8229
+ VALUE hash = date_s__iso8601(argc2, argv2, klass);
8025
8230
  return dt_new_by_frags(klass, hash, sg);
8026
8231
  }
8027
8232
  }
8028
8233
 
8029
8234
  /*
8030
8235
  * call-seq:
8031
- * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8236
+ * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8032
8237
  *
8033
8238
  * Creates a new DateTime object by parsing from a string according to
8034
8239
  * some typical RFC 3339 formats.
8035
8240
  *
8036
8241
  * DateTime.rfc3339('2001-02-03T04:05:06+07:00')
8037
8242
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8243
+ *
8244
+ * Raise an ArgumentError when the string length is longer than _limit_.
8245
+ * You can stop this check by passing `limit: nil`, but note that
8246
+ * it may take a long time to parse.
8038
8247
  */
8039
8248
  static VALUE
8040
8249
  datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8041
8250
  {
8042
- VALUE str, sg;
8251
+ VALUE str, sg, opt;
8043
8252
 
8044
- rb_scan_args(argc, argv, "02", &str, &sg);
8253
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8254
+ if (!NIL_P(opt)) argc--;
8045
8255
 
8046
8256
  switch (argc) {
8047
8257
  case 0:
@@ -8051,27 +8261,37 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8051
8261
  }
8052
8262
 
8053
8263
  {
8054
- VALUE hash = date_s__rfc3339(klass, str);
8264
+ int argc2 = 1;
8265
+ VALUE argv2[2];
8266
+ argv2[0] = str;
8267
+ argv2[1] = opt;
8268
+ if (!NIL_P(opt)) argc2++;
8269
+ VALUE hash = date_s__rfc3339(argc2, argv2, klass);
8055
8270
  return dt_new_by_frags(klass, hash, sg);
8056
8271
  }
8057
8272
  }
8058
8273
 
8059
8274
  /*
8060
8275
  * call-seq:
8061
- * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8276
+ * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8062
8277
  *
8063
8278
  * Creates a new DateTime object by parsing from a string according to
8064
8279
  * some typical XML Schema formats.
8065
8280
  *
8066
8281
  * DateTime.xmlschema('2001-02-03T04:05:06+07:00')
8067
8282
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8283
+ *
8284
+ * Raise an ArgumentError when the string length is longer than _limit_.
8285
+ * You can stop this check by passing `limit: nil`, but note that
8286
+ * it may take a long time to parse.
8068
8287
  */
8069
8288
  static VALUE
8070
8289
  datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8071
8290
  {
8072
- VALUE str, sg;
8291
+ VALUE str, sg, opt;
8073
8292
 
8074
- rb_scan_args(argc, argv, "02", &str, &sg);
8293
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8294
+ if (!NIL_P(opt)) argc--;
8075
8295
 
8076
8296
  switch (argc) {
8077
8297
  case 0:
@@ -8081,28 +8301,38 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8081
8301
  }
8082
8302
 
8083
8303
  {
8084
- VALUE hash = date_s__xmlschema(klass, str);
8304
+ int argc2 = 1;
8305
+ VALUE argv2[2];
8306
+ argv2[0] = str;
8307
+ argv2[1] = opt;
8308
+ if (!NIL_P(opt)) argc2++;
8309
+ VALUE hash = date_s__xmlschema(argc2, argv2, klass);
8085
8310
  return dt_new_by_frags(klass, hash, sg);
8086
8311
  }
8087
8312
  }
8088
8313
 
8089
8314
  /*
8090
8315
  * call-seq:
8091
- * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8092
- * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8316
+ * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
8317
+ * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
8093
8318
  *
8094
8319
  * Creates a new DateTime object by parsing from a string according to
8095
8320
  * some typical RFC 2822 formats.
8096
8321
  *
8097
8322
  * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
8098
8323
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8324
+ *
8325
+ * Raise an ArgumentError when the string length is longer than _limit_.
8326
+ * You can stop this check by passing `limit: nil`, but note that
8327
+ * it may take a long time to parse.
8099
8328
  */
8100
8329
  static VALUE
8101
8330
  datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8102
8331
  {
8103
- VALUE str, sg;
8332
+ VALUE str, sg, opt;
8104
8333
 
8105
- rb_scan_args(argc, argv, "02", &str, &sg);
8334
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8335
+ if (!NIL_P(opt)) argc--;
8106
8336
 
8107
8337
  switch (argc) {
8108
8338
  case 0:
@@ -8112,7 +8342,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8112
8342
  }
8113
8343
 
8114
8344
  {
8115
- VALUE hash = date_s__rfc2822(klass, str);
8345
+ int argc2 = 1;
8346
+ VALUE argv2[2];
8347
+ argv2[0] = str;
8348
+ argv2[1] = opt;
8349
+ if (!NIL_P(opt)) argc2++;
8350
+ VALUE hash = date_s__rfc2822(argc2, argv2, klass);
8116
8351
  return dt_new_by_frags(klass, hash, sg);
8117
8352
  }
8118
8353
  }
@@ -8126,13 +8361,18 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8126
8361
  *
8127
8362
  * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
8128
8363
  * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
8364
+ *
8365
+ * Raise an ArgumentError when the string length is longer than _limit_.
8366
+ * You can stop this check by passing `limit: nil`, but note that
8367
+ * it may take a long time to parse.
8129
8368
  */
8130
8369
  static VALUE
8131
8370
  datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8132
8371
  {
8133
- VALUE str, sg;
8372
+ VALUE str, sg, opt;
8134
8373
 
8135
- rb_scan_args(argc, argv, "02", &str, &sg);
8374
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8375
+ if (!NIL_P(opt)) argc--;
8136
8376
 
8137
8377
  switch (argc) {
8138
8378
  case 0:
@@ -8142,27 +8382,42 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8142
8382
  }
8143
8383
 
8144
8384
  {
8145
- VALUE hash = date_s__httpdate(klass, str);
8385
+ int argc2 = 1;
8386
+ VALUE argv2[2];
8387
+ argv2[0] = str;
8388
+ argv2[1] = opt;
8389
+ if (!NIL_P(opt)) argc2++;
8390
+ VALUE hash = date_s__httpdate(argc2, argv2, klass);
8146
8391
  return dt_new_by_frags(klass, hash, sg);
8147
8392
  }
8148
8393
  }
8149
8394
 
8150
8395
  /*
8151
8396
  * call-seq:
8152
- * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8397
+ * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8153
8398
  *
8154
8399
  * Creates a new DateTime object by parsing from a string according to
8155
8400
  * some typical JIS X 0301 formats.
8156
8401
  *
8157
8402
  * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
8158
8403
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8404
+ *
8405
+ * For no-era year, legacy format, Heisei is assumed.
8406
+ *
8407
+ * DateTime.jisx0301('13.02.03T04:05:06+07:00')
8408
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8409
+ *
8410
+ * Raise an ArgumentError when the string length is longer than _limit_.
8411
+ * You can stop this check by passing `limit: nil`, but note that
8412
+ * it may take a long time to parse.
8159
8413
  */
8160
8414
  static VALUE
8161
8415
  datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8162
8416
  {
8163
- VALUE str, sg;
8417
+ VALUE str, sg, opt;
8164
8418
 
8165
- rb_scan_args(argc, argv, "02", &str, &sg);
8419
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8420
+ if (!NIL_P(opt)) argc--;
8166
8421
 
8167
8422
  switch (argc) {
8168
8423
  case 0:
@@ -8172,7 +8427,12 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8172
8427
  }
8173
8428
 
8174
8429
  {
8175
- VALUE hash = date_s__jisx0301(klass, str);
8430
+ int argc2 = 1;
8431
+ VALUE argv2[2];
8432
+ argv2[0] = str;
8433
+ argv2[1] = opt;
8434
+ if (!NIL_P(opt)) argc2++;
8435
+ VALUE hash = date_s__jisx0301(argc2, argv2, klass);
8176
8436
  return dt_new_by_frags(klass, hash, sg);
8177
8437
  }
8178
8438
  }
@@ -8550,17 +8810,24 @@ time_to_datetime(VALUE self)
8550
8810
  * call-seq:
8551
8811
  * d.to_time -> time
8552
8812
  *
8553
- * Returns a Time object which denotes self.
8813
+ * Returns a Time object which denotes self. If self is a julian date,
8814
+ * convert it to a gregorian date before converting it to Time.
8554
8815
  */
8555
8816
  static VALUE
8556
8817
  date_to_time(VALUE self)
8557
8818
  {
8558
- get_d1(self);
8819
+ get_d1a(self);
8820
+
8821
+ if (m_julian_p(adat)) {
8822
+ VALUE tmp = d_lite_gregorian(self);
8823
+ get_d1b(tmp);
8824
+ adat = bdat;
8825
+ }
8559
8826
 
8560
8827
  return f_local3(rb_cTime,
8561
- m_real_year(dat),
8562
- INT2FIX(m_mon(dat)),
8563
- INT2FIX(m_mday(dat)));
8828
+ m_real_year(adat),
8829
+ INT2FIX(m_mon(adat)),
8830
+ INT2FIX(m_mday(adat)));
8564
8831
  }
8565
8832
 
8566
8833
  /*
@@ -9217,6 +9484,7 @@ Init_date_core(void)
9217
9484
  *
9218
9485
  */
9219
9486
  cDate = rb_define_class("Date", rb_cObject);
9487
+ eDateError = rb_define_class_under(cDate, "Error", rb_eArgError);
9220
9488
 
9221
9489
  rb_include_module(cDate, rb_mComparable);
9222
9490
 
@@ -9323,19 +9591,19 @@ Init_date_core(void)
9323
9591
  rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
9324
9592
  rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
9325
9593
  rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
9326
- rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
9594
+ rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1);
9327
9595
  rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
9328
- rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
9596
+ rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1);
9329
9597
  rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
9330
- rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
9598
+ rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1);
9331
9599
  rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
9332
- rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
9333
- rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
9600
+ rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1);
9601
+ rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1);
9334
9602
  rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
9335
9603
  rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
9336
- rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
9604
+ rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1);
9337
9605
  rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
9338
- rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
9606
+ rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1);
9339
9607
  rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
9340
9608
 
9341
9609
  rb_define_method(cDate, "initialize", date_initialize, -1);