date 2.0.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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);