date 0.0.1 → 2.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
@@ -51,18 +51,21 @@ static double positive_inf, negative_inf;
51
51
  #define f_add3(x,y,z) f_add(f_add(x, y), z)
52
52
  #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
53
53
 
54
- inline static VALUE
54
+ static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
55
+ static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
56
+
57
+ inline static int
55
58
  f_cmp(VALUE x, VALUE y)
56
59
  {
57
60
  if (FIXNUM_P(x) && FIXNUM_P(y)) {
58
61
  long c = FIX2LONG(x) - FIX2LONG(y);
59
62
  if (c > 0)
60
- c = 1;
63
+ return 1;
61
64
  else if (c < 0)
62
- c = -1;
63
- return INT2FIX(c);
65
+ return -1;
66
+ return 0;
64
67
  }
65
- return rb_funcall(x, id_cmp, 1, y);
68
+ return rb_cmpint(rb_funcallv(x, id_cmp, 1, &y), x, y);
66
69
  }
67
70
 
68
71
  inline static VALUE
@@ -94,7 +97,7 @@ f_ge_p(VALUE x, VALUE y)
94
97
  {
95
98
  if (FIXNUM_P(x) && FIXNUM_P(y))
96
99
  return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
97
- return rb_funcall(x, rb_intern(">="), 1, y);
100
+ return rb_funcall(x, id_ge_p, 1, y);
98
101
  }
99
102
 
100
103
  inline static VALUE
@@ -102,7 +105,7 @@ f_eqeq_p(VALUE x, VALUE y)
102
105
  {
103
106
  if (FIXNUM_P(x) && FIXNUM_P(y))
104
107
  return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
105
- return rb_funcall(x, rb_intern("=="), 1, y);
108
+ return rb_funcall(x, id_eqeq_p, 1, y);
106
109
  }
107
110
 
108
111
  inline static VALUE
@@ -236,11 +239,8 @@ f_negative_p(VALUE x)
236
239
  struct SimpleDateData
237
240
  {
238
241
  unsigned flags;
239
- VALUE nth; /* not always canonicalized */
240
242
  int jd; /* as utc */
241
- /* df is zero */
242
- /* sf is zero */
243
- /* of is zero */
243
+ VALUE nth; /* not always canonicalized */
244
244
  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
245
245
  /* decoded as utc=local */
246
246
  int year; /* truncated */
@@ -259,11 +259,8 @@ struct SimpleDateData
259
259
  struct ComplexDateData
260
260
  {
261
261
  unsigned flags;
262
- VALUE nth; /* not always canonicalized */
263
262
  int jd; /* as utc */
264
- int df; /* as utc, in secs */
265
- VALUE sf; /* in nano secs */
266
- int of; /* in secs */
263
+ VALUE nth; /* not always canonicalized */
267
264
  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
268
265
  /* decoded as local */
269
266
  int year; /* truncated */
@@ -277,6 +274,9 @@ struct ComplexDateData
277
274
  /* packed civil */
278
275
  unsigned pc;
279
276
  #endif
277
+ int df; /* as utc, in secs */
278
+ int of; /* in secs */
279
+ VALUE sf; /* in nano secs */
280
280
  };
281
281
 
282
282
  union DateData {
@@ -315,31 +315,31 @@ canon(VALUE x)
315
315
 
316
316
  #ifndef USE_PACK
317
317
  #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
318
- {\
318
+ do {\
319
319
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
320
320
  (x)->jd = _jd;\
321
321
  (x)->sg = (date_sg_t)(_sg);\
322
322
  (x)->year = _year;\
323
323
  (x)->mon = _mon;\
324
324
  (x)->mday = _mday;\
325
- (x)->flags = _flags;\
326
- }
325
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
326
+ } while (0)
327
327
  #else
328
328
  #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
329
- {\
329
+ do {\
330
330
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
331
331
  (x)->jd = _jd;\
332
332
  (x)->sg = (date_sg_t)(_sg);\
333
333
  (x)->year = _year;\
334
334
  (x)->pc = PACK2(_mon, _mday);\
335
- (x)->flags = _flags;\
336
- }
335
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
336
+ } while (0)
337
337
  #endif
338
338
 
339
339
  #ifndef USE_PACK
340
340
  #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
341
341
  _year, _mon, _mday, _hour, _min, _sec, _flags) \
342
- {\
342
+ do {\
343
343
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
344
344
  (x)->jd = _jd;\
345
345
  (x)->df = _df;\
@@ -352,12 +352,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
352
352
  (x)->hour = _hour;\
353
353
  (x)->min = _min;\
354
354
  (x)->sec = _sec;\
355
- (x)->flags = _flags;\
356
- }
355
+ (x)->flags = (_flags) | COMPLEX_DAT;\
356
+ } while (0)
357
357
  #else
358
358
  #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
359
359
  _year, _mon, _mday, _hour, _min, _sec, _flags) \
360
- {\
360
+ do {\
361
361
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
362
362
  (x)->jd = _jd;\
363
363
  (x)->df = _df;\
@@ -366,13 +366,13 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
366
366
  (x)->sg = (date_sg_t)(_sg);\
367
367
  (x)->year = _year;\
368
368
  (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
369
- (x)->flags = _flags;\
370
- }
369
+ (x)->flags = (_flags) | COMPLEX_DAT;\
370
+ } while (0)
371
371
  #endif
372
372
 
373
373
  #ifndef USE_PACK
374
374
  #define copy_simple_to_complex(obj, x, y) \
375
- {\
375
+ do {\
376
376
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
377
377
  (x)->jd = (y)->jd;\
378
378
  (x)->df = 0;\
@@ -386,10 +386,10 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
386
386
  (x)->min = 0;\
387
387
  (x)->sec = 0;\
388
388
  (x)->flags = (y)->flags;\
389
- }
389
+ } while (0)
390
390
  #else
391
391
  #define copy_simple_to_complex(obj, x, y) \
392
- {\
392
+ do {\
393
393
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
394
394
  (x)->jd = (y)->jd;\
395
395
  (x)->df = 0;\
@@ -399,12 +399,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
399
399
  (x)->year = (y)->year;\
400
400
  (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
401
401
  (x)->flags = (y)->flags;\
402
- }
402
+ } while (0)
403
403
  #endif
404
404
 
405
405
  #ifndef USE_PACK
406
406
  #define copy_complex_to_simple(obj, x, y) \
407
- {\
407
+ do {\
408
408
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
409
409
  (x)->jd = (y)->jd;\
410
410
  (x)->sg = (date_sg_t)((y)->sg);\
@@ -412,17 +412,17 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
412
412
  (x)->mon = (y)->mon;\
413
413
  (x)->mday = (y)->mday;\
414
414
  (x)->flags = (y)->flags;\
415
- }
415
+ } while (0)
416
416
  #else
417
417
  #define copy_complex_to_simple(obj, x, y) \
418
- {\
418
+ do {\
419
419
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
420
420
  (x)->jd = (y)->jd;\
421
421
  (x)->sg = (date_sg_t)((y)->sg);\
422
422
  (x)->year = (y)->year;\
423
423
  (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
424
424
  (x)->flags = (y)->flags;\
425
- }
425
+ } while (0)
426
426
  #endif
427
427
 
428
428
  /* base */
@@ -1109,7 +1109,7 @@ m_virtual_sg(union DateData *x)
1109
1109
  }
1110
1110
 
1111
1111
  #define canonicalize_jd(_nth, _jd) \
1112
- {\
1112
+ do {\
1113
1113
  if (_jd < 0) {\
1114
1114
  _nth = f_sub(_nth, INT2FIX(1));\
1115
1115
  _jd += CM_PERIOD;\
@@ -1118,7 +1118,7 @@ m_virtual_sg(union DateData *x)
1118
1118
  _nth = f_add(_nth, INT2FIX(1));\
1119
1119
  _jd -= CM_PERIOD;\
1120
1120
  }\
1121
- }
1121
+ } while (0)
1122
1122
 
1123
1123
  inline static void
1124
1124
  canonicalize_s_jd(VALUE obj, union DateData *x)
@@ -1928,13 +1928,13 @@ m_sec(union DateData *x)
1928
1928
  }
1929
1929
 
1930
1930
  #define decode_offset(of,s,h,m)\
1931
- {\
1931
+ do {\
1932
1932
  int a;\
1933
1933
  s = (of < 0) ? '-' : '+';\
1934
1934
  a = (of < 0) ? -of : of;\
1935
1935
  h = a / HOUR_IN_SECONDS;\
1936
1936
  m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
1937
- }
1937
+ } while (0)
1938
1938
 
1939
1939
  static VALUE
1940
1940
  of2str(int of)
@@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE);
2333
2333
  static int
2334
2334
  offset_to_sec(VALUE vof, int *rof)
2335
2335
  {
2336
+ int try_rational = 1;
2337
+
2338
+ again:
2336
2339
  switch (TYPE(vof)) {
2337
2340
  case T_FIXNUM:
2338
2341
  {
@@ -2359,10 +2362,11 @@ offset_to_sec(VALUE vof, int *rof)
2359
2362
  default:
2360
2363
  expect_numeric(vof);
2361
2364
  vof = f_to_r(vof);
2362
- #ifdef CANONICALIZATION_FOR_MATHN
2363
- if (!k_rational_p(vof))
2364
- return offset_to_sec(vof, rof);
2365
- #endif
2365
+ if (!k_rational_p(vof)) {
2366
+ if (!try_rational) Check_Type(vof, T_RATIONAL);
2367
+ try_rational = 0;
2368
+ goto again;
2369
+ }
2366
2370
  /* fall through */
2367
2371
  case T_RATIONAL:
2368
2372
  {
@@ -2371,17 +2375,10 @@ offset_to_sec(VALUE vof, int *rof)
2371
2375
 
2372
2376
  vs = day_to_sec(vof);
2373
2377
 
2374
- #ifdef CANONICALIZATION_FOR_MATHN
2375
2378
  if (!k_rational_p(vs)) {
2376
- if (!FIXNUM_P(vs))
2377
- return 0;
2378
- n = FIX2LONG(vs);
2379
- if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2380
- return 0;
2381
- *rof = (int)n;
2382
- return 1;
2379
+ vn = vs;
2380
+ goto rounded;
2383
2381
  }
2384
- #endif
2385
2382
  vn = rb_rational_num(vs);
2386
2383
  vd = rb_rational_den(vs);
2387
2384
 
@@ -2391,6 +2388,7 @@ offset_to_sec(VALUE vof, int *rof)
2391
2388
  vn = f_round(vs);
2392
2389
  if (!f_eqeq_p(vn, vs))
2393
2390
  rb_warning("fraction of offset is ignored");
2391
+ rounded:
2394
2392
  if (!FIXNUM_P(vn))
2395
2393
  return 0;
2396
2394
  n = FIX2LONG(vn);
@@ -2420,12 +2418,12 @@ offset_to_sec(VALUE vof, int *rof)
2420
2418
  /* date */
2421
2419
 
2422
2420
  #define valid_sg(sg) \
2423
- {\
2421
+ do {\
2424
2422
  if (!c_valid_start_p(sg)) {\
2425
2423
  sg = 0;\
2426
2424
  rb_warning("invalid start is ignored");\
2427
2425
  }\
2428
- }
2426
+ } while (0)
2429
2427
 
2430
2428
  static VALUE
2431
2429
  valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
@@ -2968,7 +2966,7 @@ d_simple_new_internal(VALUE klass,
2968
2966
 
2969
2967
  obj = TypedData_Make_Struct(klass, struct SimpleDateData,
2970
2968
  &d_lite_type, dat);
2971
- set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
2969
+ set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
2972
2970
 
2973
2971
  assert(have_jd_p(dat) || have_civil_p(dat));
2974
2972
 
@@ -2990,7 +2988,7 @@ d_complex_new_internal(VALUE klass,
2990
2988
  obj = TypedData_Make_Struct(klass, struct ComplexDateData,
2991
2989
  &d_lite_type, dat);
2992
2990
  set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
2993
- y, m, d, h, min, s, flags | COMPLEX_DAT);
2991
+ y, m, d, h, min, s, flags);
2994
2992
 
2995
2993
  assert(have_jd_p(dat) || have_civil_p(dat));
2996
2994
  assert(have_df_p(dat) || have_time_p(dat));
@@ -3207,47 +3205,47 @@ s_trunc(VALUE s, VALUE *fr)
3207
3205
  }
3208
3206
 
3209
3207
  #define num2num_with_frac(s,n) \
3210
- {\
3208
+ do {\
3211
3209
  s = s##_trunc(v##s, &fr);\
3212
3210
  if (f_nonzero_p(fr)) {\
3213
3211
  if (argc > n)\
3214
3212
  rb_raise(rb_eArgError, "invalid fraction");\
3215
3213
  fr2 = fr;\
3216
3214
  }\
3217
- }
3215
+ } while (0)
3218
3216
 
3219
3217
  #define num2int_with_frac(s,n) \
3220
- {\
3218
+ do {\
3221
3219
  s = NUM2INT(s##_trunc(v##s, &fr));\
3222
3220
  if (f_nonzero_p(fr)) {\
3223
3221
  if (argc > n)\
3224
3222
  rb_raise(rb_eArgError, "invalid fraction");\
3225
3223
  fr2 = fr;\
3226
3224
  }\
3227
- }
3225
+ } while (0)
3228
3226
 
3229
3227
  #define canon24oc() \
3230
- {\
3228
+ do {\
3231
3229
  if (rh == 24) {\
3232
3230
  rh = 0;\
3233
3231
  fr2 = f_add(fr2, INT2FIX(1));\
3234
3232
  }\
3235
- }
3233
+ } while (0)
3236
3234
 
3237
3235
  #define add_frac() \
3238
- {\
3236
+ do {\
3239
3237
  if (f_nonzero_p(fr2))\
3240
3238
  ret = d_lite_plus(ret, fr2);\
3241
- }
3239
+ } while (0)
3242
3240
 
3243
3241
  #define val2sg(vsg,dsg) \
3244
- {\
3242
+ do {\
3245
3243
  dsg = NUM2DBL(vsg);\
3246
3244
  if (!c_valid_start_p(dsg)) {\
3247
3245
  dsg = DEFAULT_SG;\
3248
3246
  rb_warning("invalid start is ignored");\
3249
3247
  }\
3250
- }
3248
+ } while (0)
3251
3249
 
3252
3250
  static VALUE d_lite_plus(VALUE, VALUE);
3253
3251
 
@@ -3384,10 +3382,21 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3384
3382
  */
3385
3383
  static VALUE
3386
3384
  date_s_civil(int argc, VALUE *argv, VALUE klass)
3385
+ {
3386
+ return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
3387
+ }
3388
+
3389
+ static VALUE
3390
+ date_initialize(int argc, VALUE *argv, VALUE self)
3387
3391
  {
3388
3392
  VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
3389
3393
  int m, d;
3390
3394
  double sg;
3395
+ struct SimpleDateData *dat = rb_check_typeddata(self, &d_lite_type);
3396
+
3397
+ if (!simple_dat_p(dat)) {
3398
+ rb_raise(rb_eTypeError, "Date expected");
3399
+ }
3391
3400
 
3392
3401
  rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
3393
3402
 
@@ -3417,11 +3426,7 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
3417
3426
  &rm, &rd))
3418
3427
  rb_raise(rb_eArgError, "invalid date");
3419
3428
 
3420
- ret = d_simple_new_internal(klass,
3421
- nth, 0,
3422
- sg,
3423
- ry, rm, rd,
3424
- HAVE_CIVIL);
3429
+ set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
3425
3430
  }
3426
3431
  else {
3427
3432
  VALUE nth;
@@ -3433,12 +3438,9 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
3433
3438
  &ns))
3434
3439
  rb_raise(rb_eArgError, "invalid date");
3435
3440
 
3436
- ret = d_simple_new_internal(klass,
3437
- nth, rjd,
3438
- sg,
3439
- ry, rm, rd,
3440
- HAVE_JD | HAVE_CIVIL);
3441
+ set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
3441
3442
  }
3443
+ ret = self;
3442
3444
  add_frac();
3443
3445
  return ret;
3444
3446
  }
@@ -3679,9 +3681,11 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
3679
3681
  #define ref_hash0(k) rb_hash_aref(hash, k)
3680
3682
  #define del_hash0(k) rb_hash_delete(hash, k)
3681
3683
 
3682
- #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
3683
- #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
3684
- #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
3684
+ #define sym(x) ID2SYM(rb_intern(x""))
3685
+
3686
+ #define set_hash(k,v) set_hash0(sym(k), v)
3687
+ #define ref_hash(k) ref_hash0(sym(k))
3688
+ #define del_hash(k) del_hash0(sym(k))
3685
3689
 
3686
3690
  static VALUE
3687
3691
  rt_rewrite_frags(VALUE hash)
@@ -3718,8 +3722,6 @@ rt_rewrite_frags(VALUE hash)
3718
3722
  return hash;
3719
3723
  }
3720
3724
 
3721
- #define sym(x) ID2SYM(rb_intern(x))
3722
-
3723
3725
  static VALUE d_lite_year(VALUE);
3724
3726
  static VALUE d_lite_wday(VALUE);
3725
3727
  static VALUE d_lite_jd(VALUE);
@@ -4290,12 +4292,40 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass)
4290
4292
 
4291
4293
  VALUE date__parse(VALUE str, VALUE comp);
4292
4294
 
4295
+ static size_t
4296
+ get_limit(VALUE opt)
4297
+ {
4298
+ if (!NIL_P(opt)) {
4299
+ VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit")));
4300
+ if (NIL_P(limit)) return SIZE_MAX;
4301
+ return NUM2SIZET(limit);
4302
+ }
4303
+ return 128;
4304
+ }
4305
+
4306
+ static void
4307
+ check_limit(VALUE str, VALUE opt)
4308
+ {
4309
+ if (NIL_P(str)) return;
4310
+ if (SYMBOL_P(str)) str = rb_sym2str(str);
4311
+
4312
+ StringValue(str);
4313
+ size_t slen = RSTRING_LEN(str);
4314
+ size_t limit = get_limit(opt);
4315
+ if (slen > limit) {
4316
+ rb_raise(rb_eArgError,
4317
+ "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
4318
+ }
4319
+ }
4320
+
4293
4321
  static VALUE
4294
4322
  date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4295
4323
  {
4296
- VALUE vstr, vcomp, hash;
4324
+ VALUE vstr, vcomp, hash, opt;
4297
4325
 
4298
- rb_scan_args(argc, argv, "11", &vstr, &vcomp);
4326
+ rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
4327
+ if (!NIL_P(opt)) argc--;
4328
+ check_limit(vstr, opt);
4299
4329
  StringValue(vstr);
4300
4330
  if (!rb_enc_str_asciicompat_p(vstr))
4301
4331
  rb_raise(rb_eArgError,
@@ -4320,7 +4350,7 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4320
4350
 
4321
4351
  /*
4322
4352
  * call-seq:
4323
- * Date._parse(string[, comp=true]) -> hash
4353
+ * Date._parse(string[, comp=true], limit: 128) -> hash
4324
4354
  *
4325
4355
  * Parses the given representation of date and time, and returns a
4326
4356
  * hash of parsed elements. This method does not function as a
@@ -4331,6 +4361,10 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4331
4361
  * it full.
4332
4362
  *
4333
4363
  * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3}
4364
+ *
4365
+ * Raise an ArgumentError when the string length is longer than _limit_.
4366
+ * You can stop this check by passing `limit: nil`, but note that
4367
+ * it may take a long time to parse.
4334
4368
  */
4335
4369
  static VALUE
4336
4370
  date_s__parse(int argc, VALUE *argv, VALUE klass)
@@ -4340,7 +4374,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
4340
4374
 
4341
4375
  /*
4342
4376
  * call-seq:
4343
- * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date
4377
+ * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128) -> date
4344
4378
  *
4345
4379
  * Parses the given representation of date and time, and creates a
4346
4380
  * date object. This method does not function as a validator.
@@ -4352,13 +4386,18 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
4352
4386
  * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
4353
4387
  * Date.parse('20010203') #=> #<Date: 2001-02-03 ...>
4354
4388
  * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...>
4389
+ *
4390
+ * Raise an ArgumentError when the string length is longer than _limit_.
4391
+ * You can stop this check by passing `limit: nil`, but note that
4392
+ * it may take a long time to parse.
4355
4393
  */
4356
4394
  static VALUE
4357
4395
  date_s_parse(int argc, VALUE *argv, VALUE klass)
4358
4396
  {
4359
- VALUE str, comp, sg;
4397
+ VALUE str, comp, sg, opt;
4360
4398
 
4361
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
4399
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
4400
+ if (!NIL_P(opt)) argc--;
4362
4401
 
4363
4402
  switch (argc) {
4364
4403
  case 0:
@@ -4370,11 +4409,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass)
4370
4409
  }
4371
4410
 
4372
4411
  {
4373
- VALUE argv2[2], hash;
4374
-
4375
- argv2[0] = str;
4376
- argv2[1] = comp;
4377
- hash = date_s__parse(2, argv2, klass);
4412
+ int argc2 = 2;
4413
+ VALUE argv2[3];
4414
+ argv2[0] = str;
4415
+ argv2[1] = comp;
4416
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4417
+ VALUE hash = date_s__parse(argc2, argv2, klass);
4378
4418
  return d_new_by_frags(klass, hash, sg);
4379
4419
  }
4380
4420
  }
@@ -4388,19 +4428,28 @@ VALUE date__jisx0301(VALUE);
4388
4428
 
4389
4429
  /*
4390
4430
  * call-seq:
4391
- * Date._iso8601(string) -> hash
4431
+ * Date._iso8601(string, limit: 128) -> hash
4392
4432
  *
4393
4433
  * Returns a hash of parsed elements.
4434
+ *
4435
+ * Raise an ArgumentError when the string length is longer than _limit_.
4436
+ * You can stop this check by passing `limit: nil`, but note that
4437
+ * it may take a long time to parse.
4394
4438
  */
4395
4439
  static VALUE
4396
- date_s__iso8601(VALUE klass, VALUE str)
4440
+ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
4397
4441
  {
4442
+ VALUE str, opt;
4443
+
4444
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4445
+ check_limit(str, opt);
4446
+
4398
4447
  return date__iso8601(str);
4399
4448
  }
4400
4449
 
4401
4450
  /*
4402
4451
  * call-seq:
4403
- * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date
4452
+ * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4404
4453
  *
4405
4454
  * Creates a new Date object by parsing from a string according to
4406
4455
  * some typical ISO 8601 formats.
@@ -4408,13 +4457,18 @@ date_s__iso8601(VALUE klass, VALUE str)
4408
4457
  * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...>
4409
4458
  * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...>
4410
4459
  * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...>
4460
+ *
4461
+ * Raise an ArgumentError when the string length is longer than _limit_.
4462
+ * You can stop this check by passing `limit: nil`, but note that
4463
+ * it may take a long time to parse.
4411
4464
  */
4412
4465
  static VALUE
4413
4466
  date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4414
4467
  {
4415
- VALUE str, sg;
4468
+ VALUE str, sg, opt;
4416
4469
 
4417
- rb_scan_args(argc, argv, "02", &str, &sg);
4470
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4471
+ if (!NIL_P(opt)) argc--;
4418
4472
 
4419
4473
  switch (argc) {
4420
4474
  case 0:
@@ -4424,38 +4478,56 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4424
4478
  }
4425
4479
 
4426
4480
  {
4427
- VALUE hash = date_s__iso8601(klass, str);
4481
+ int argc2 = 1;
4482
+ VALUE argv2[2];
4483
+ argv2[0] = str;
4484
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4485
+ VALUE hash = date_s__iso8601(argc2, argv2, klass);
4428
4486
  return d_new_by_frags(klass, hash, sg);
4429
4487
  }
4430
4488
  }
4431
4489
 
4432
4490
  /*
4433
4491
  * call-seq:
4434
- * Date._rfc3339(string) -> hash
4492
+ * Date._rfc3339(string, limit: 128) -> hash
4435
4493
  *
4436
4494
  * Returns a hash of parsed elements.
4495
+ *
4496
+ * Raise an ArgumentError when the string length is longer than _limit_.
4497
+ * You can stop this check by passing `limit: nil`, but note that
4498
+ * it may take a long time to parse.
4437
4499
  */
4438
4500
  static VALUE
4439
- date_s__rfc3339(VALUE klass, VALUE str)
4501
+ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
4440
4502
  {
4503
+ VALUE str, opt;
4504
+
4505
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4506
+ check_limit(str, opt);
4507
+
4441
4508
  return date__rfc3339(str);
4442
4509
  }
4443
4510
 
4444
4511
  /*
4445
4512
  * call-seq:
4446
- * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date
4513
+ * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> date
4447
4514
  *
4448
4515
  * Creates a new Date object by parsing from a string according to
4449
4516
  * some typical RFC 3339 formats.
4450
4517
  *
4451
4518
  * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
4519
+ *
4520
+ * Raise an ArgumentError when the string length is longer than _limit_.
4521
+ * You can stop this check by passing `limit: nil`, but note that
4522
+ * it may take a long time to parse.
4452
4523
  */
4453
4524
  static VALUE
4454
4525
  date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4455
4526
  {
4456
- VALUE str, sg;
4527
+ VALUE str, sg, opt;
4457
4528
 
4458
- rb_scan_args(argc, argv, "02", &str, &sg);
4529
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4530
+ if (!NIL_P(opt)) argc--;
4459
4531
 
4460
4532
  switch (argc) {
4461
4533
  case 0:
@@ -4465,38 +4537,56 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4465
4537
  }
4466
4538
 
4467
4539
  {
4468
- VALUE hash = date_s__rfc3339(klass, str);
4540
+ int argc2 = 1;
4541
+ VALUE argv2[2];
4542
+ argv2[0] = str;
4543
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4544
+ VALUE hash = date_s__rfc3339(argc2, argv2, klass);
4469
4545
  return d_new_by_frags(klass, hash, sg);
4470
4546
  }
4471
4547
  }
4472
4548
 
4473
4549
  /*
4474
4550
  * call-seq:
4475
- * Date._xmlschema(string) -> hash
4551
+ * Date._xmlschema(string, limit: 128) -> hash
4476
4552
  *
4477
4553
  * Returns a hash of parsed elements.
4554
+ *
4555
+ * Raise an ArgumentError when the string length is longer than _limit_.
4556
+ * You can stop this check by passing `limit: nil`, but note that
4557
+ * it may take a long time to parse.
4478
4558
  */
4479
4559
  static VALUE
4480
- date_s__xmlschema(VALUE klass, VALUE str)
4560
+ date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
4481
4561
  {
4562
+ VALUE str, opt;
4563
+
4564
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4565
+ check_limit(str, opt);
4566
+
4482
4567
  return date__xmlschema(str);
4483
4568
  }
4484
4569
 
4485
4570
  /*
4486
4571
  * call-seq:
4487
- * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date
4572
+ * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4488
4573
  *
4489
4574
  * Creates a new Date object by parsing from a string according to
4490
4575
  * some typical XML Schema formats.
4491
4576
  *
4492
4577
  * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...>
4578
+ *
4579
+ * Raise an ArgumentError when the string length is longer than _limit_.
4580
+ * You can stop this check by passing `limit: nil`, but note that
4581
+ * it may take a long time to parse.
4493
4582
  */
4494
4583
  static VALUE
4495
4584
  date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4496
4585
  {
4497
- VALUE str, sg;
4586
+ VALUE str, sg, opt;
4498
4587
 
4499
- rb_scan_args(argc, argv, "02", &str, &sg);
4588
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4589
+ if (!NIL_P(opt)) argc--;
4500
4590
 
4501
4591
  switch (argc) {
4502
4592
  case 0:
@@ -4506,41 +4596,58 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4506
4596
  }
4507
4597
 
4508
4598
  {
4509
- VALUE hash = date_s__xmlschema(klass, str);
4599
+ int argc2 = 1;
4600
+ VALUE argv2[2];
4601
+ argv2[0] = str;
4602
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4603
+ VALUE hash = date_s__xmlschema(argc2, argv2, klass);
4510
4604
  return d_new_by_frags(klass, hash, sg);
4511
4605
  }
4512
4606
  }
4513
4607
 
4514
4608
  /*
4515
4609
  * call-seq:
4516
- * Date._rfc2822(string) -> hash
4517
- * Date._rfc822(string) -> hash
4610
+ * Date._rfc2822(string, limit: 128) -> hash
4611
+ * Date._rfc822(string, limit: 128) -> hash
4518
4612
  *
4519
4613
  * Returns a hash of parsed elements.
4614
+ *
4615
+ * Raise an ArgumentError when the string length is longer than _limit_.
4616
+ * You can stop this check by passing `limit: nil`, but note that
4617
+ * it may take a long time to parse.
4520
4618
  */
4521
4619
  static VALUE
4522
- date_s__rfc2822(VALUE klass, VALUE str)
4620
+ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
4523
4621
  {
4622
+ VALUE str, opt;
4623
+
4624
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4625
+ check_limit(str, opt);
4626
+
4524
4627
  return date__rfc2822(str);
4525
4628
  }
4526
4629
 
4527
4630
  /*
4528
4631
  * call-seq:
4529
- * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4530
- * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4632
+ * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
4633
+ * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
4531
4634
  *
4532
4635
  * Creates a new Date object by parsing from a string according to
4533
4636
  * some typical RFC 2822 formats.
4534
4637
  *
4535
4638
  * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
4536
4639
  * #=> #<Date: 2001-02-03 ...>
4640
+ *
4641
+ * Raise an ArgumentError when the string length is longer than _limit_.
4642
+ * You can stop this check by passing `limit: nil`, but note that
4643
+ * it may take a long time to parse.
4537
4644
  */
4538
4645
  static VALUE
4539
4646
  date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4540
4647
  {
4541
- VALUE str, sg;
4648
+ VALUE str, sg, opt;
4542
4649
 
4543
- rb_scan_args(argc, argv, "02", &str, &sg);
4650
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4544
4651
 
4545
4652
  switch (argc) {
4546
4653
  case 0:
@@ -4550,39 +4657,56 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4550
4657
  }
4551
4658
 
4552
4659
  {
4553
- VALUE hash = date_s__rfc2822(klass, str);
4660
+ int argc2 = 1;
4661
+ VALUE argv2[2];
4662
+ argv2[0] = str;
4663
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4664
+ VALUE hash = date_s__rfc2822(argc2, argv2, klass);
4554
4665
  return d_new_by_frags(klass, hash, sg);
4555
4666
  }
4556
4667
  }
4557
4668
 
4558
4669
  /*
4559
4670
  * call-seq:
4560
- * Date._httpdate(string) -> hash
4671
+ * Date._httpdate(string, limit: 128) -> hash
4561
4672
  *
4562
4673
  * Returns a hash of parsed elements.
4674
+ *
4675
+ * Raise an ArgumentError when the string length is longer than _limit_.
4676
+ * You can stop this check by passing `limit: nil`, but note that
4677
+ * it may take a long time to parse.
4563
4678
  */
4564
4679
  static VALUE
4565
- date_s__httpdate(VALUE klass, VALUE str)
4680
+ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
4566
4681
  {
4682
+ VALUE str, opt;
4683
+
4684
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4685
+ check_limit(str, opt);
4686
+
4567
4687
  return date__httpdate(str);
4568
4688
  }
4569
4689
 
4570
4690
  /*
4571
4691
  * call-seq:
4572
- * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date
4692
+ * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY], limit: 128) -> date
4573
4693
  *
4574
4694
  * Creates a new Date object by parsing from a string according to
4575
4695
  * some RFC 2616 format.
4576
4696
  *
4577
4697
  * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
4578
4698
  * #=> #<Date: 2001-02-03 ...>
4699
+ *
4700
+ * Raise an ArgumentError when the string length is longer than _limit_.
4701
+ * You can stop this check by passing `limit: nil`, but note that
4702
+ * it may take a long time to parse.
4579
4703
  */
4580
4704
  static VALUE
4581
4705
  date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4582
4706
  {
4583
- VALUE str, sg;
4707
+ VALUE str, sg, opt;
4584
4708
 
4585
- rb_scan_args(argc, argv, "02", &str, &sg);
4709
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4586
4710
 
4587
4711
  switch (argc) {
4588
4712
  case 0:
@@ -4592,38 +4716,56 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4592
4716
  }
4593
4717
 
4594
4718
  {
4595
- VALUE hash = date_s__httpdate(klass, str);
4719
+ int argc2 = 1;
4720
+ VALUE argv2[2];
4721
+ argv2[0] = str;
4722
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4723
+ VALUE hash = date_s__httpdate(argc2, argv2, klass);
4596
4724
  return d_new_by_frags(klass, hash, sg);
4597
4725
  }
4598
4726
  }
4599
4727
 
4600
4728
  /*
4601
4729
  * call-seq:
4602
- * Date._jisx0301(string) -> hash
4730
+ * Date._jisx0301(string, limit: 128) -> hash
4603
4731
  *
4604
4732
  * Returns a hash of parsed elements.
4733
+ *
4734
+ * Raise an ArgumentError when the string length is longer than _limit_.
4735
+ * You can stop this check by passing `limit: nil`, but note that
4736
+ * it may take a long time to parse.
4605
4737
  */
4606
4738
  static VALUE
4607
- date_s__jisx0301(VALUE klass, VALUE str)
4739
+ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
4608
4740
  {
4741
+ VALUE str, opt;
4742
+
4743
+ rb_scan_args(argc, argv, "1:", &str, &opt);
4744
+ check_limit(str, opt);
4745
+
4609
4746
  return date__jisx0301(str);
4610
4747
  }
4611
4748
 
4612
4749
  /*
4613
4750
  * call-seq:
4614
- * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date
4751
+ * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> date
4615
4752
  *
4616
4753
  * Creates a new Date object by parsing from a string according to
4617
4754
  * some typical JIS X 0301 formats.
4618
4755
  *
4619
4756
  * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
4757
+ *
4758
+ * Raise an ArgumentError when the string length is longer than _limit_.
4759
+ * You can stop this check by passing `limit: nil`, but note that
4760
+ * it may take a long time to parse.
4620
4761
  */
4621
4762
  static VALUE
4622
4763
  date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4623
4764
  {
4624
- VALUE str, sg;
4765
+ VALUE str, sg, opt;
4625
4766
 
4626
- rb_scan_args(argc, argv, "02", &str, &sg);
4767
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
4768
+ if (!NIL_P(opt)) argc--;
4627
4769
 
4628
4770
  switch (argc) {
4629
4771
  case 0:
@@ -4633,7 +4775,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4633
4775
  }
4634
4776
 
4635
4777
  {
4636
- VALUE hash = date_s__jisx0301(klass, str);
4778
+ int argc2 = 1;
4779
+ VALUE argv2[2];
4780
+ argv2[0] = str;
4781
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
4782
+ VALUE hash = date_s__jisx0301(argc2, argv2, klass);
4637
4783
  return d_new_by_frags(klass, hash, sg);
4638
4784
  }
4639
4785
  }
@@ -4691,14 +4837,14 @@ dup_obj_as_complex(VALUE self)
4691
4837
  }
4692
4838
 
4693
4839
  #define val2off(vof,iof) \
4694
- {\
4840
+ do {\
4695
4841
  if (!offset_to_sec(vof, &iof)) {\
4696
4842
  iof = 0;\
4697
4843
  rb_warning("invalid offset is ignored");\
4698
4844
  }\
4699
- }
4845
+ } while (0)
4700
4846
 
4701
- #ifndef NDEBUG
4847
+ #if 0
4702
4848
  static VALUE
4703
4849
  d_lite_initialize(int argc, VALUE *argv, VALUE self)
4704
4850
  {
@@ -4751,7 +4897,7 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4751
4897
  "cannot load complex into simple");
4752
4898
 
4753
4899
  set_to_complex(self, &dat->c, nth, rjd, df, sf, of, sg,
4754
- 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
4900
+ 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF);
4755
4901
  }
4756
4902
  }
4757
4903
  return self;
@@ -4770,8 +4916,28 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
4770
4916
  {
4771
4917
  get_d2(copy, date);
4772
4918
  if (simple_dat_p(bdat)) {
4773
- adat->s = bdat->s;
4774
- adat->s.flags &= ~COMPLEX_DAT;
4919
+ if (simple_dat_p(adat)) {
4920
+ adat->s = bdat->s;
4921
+ }
4922
+ else {
4923
+ adat->c.flags = bdat->s.flags | COMPLEX_DAT;
4924
+ adat->c.nth = bdat->s.nth;
4925
+ adat->c.jd = bdat->s.jd;
4926
+ adat->c.df = 0;
4927
+ adat->c.sf = INT2FIX(0);
4928
+ adat->c.of = 0;
4929
+ adat->c.sg = bdat->s.sg;
4930
+ adat->c.year = bdat->s.year;
4931
+ #ifndef USE_PACK
4932
+ adat->c.mon = bdat->s.mon;
4933
+ adat->c.mday = bdat->s.mday;
4934
+ adat->c.hour = bdat->s.hour;
4935
+ adat->c.min = bdat->s.min;
4936
+ adat->c.sec = bdat->s.sec;
4937
+ #else
4938
+ adat->c.pc = bdat->s.pc;
4939
+ #endif
4940
+ }
4775
4941
  }
4776
4942
  else {
4777
4943
  if (!complex_dat_p(adat))
@@ -4779,7 +4945,6 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
4779
4945
  "cannot load complex into simple");
4780
4946
 
4781
4947
  adat->c = bdat->c;
4782
- adat->c.flags |= COMPLEX_DAT;
4783
4948
  }
4784
4949
  }
4785
4950
  return copy;
@@ -5513,8 +5678,10 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self)
5513
5678
  static VALUE
5514
5679
  d_lite_plus(VALUE self, VALUE other)
5515
5680
  {
5681
+ int try_rational = 1;
5516
5682
  get_d1(self);
5517
5683
 
5684
+ again:
5518
5685
  switch (TYPE(other)) {
5519
5686
  case T_FIXNUM:
5520
5687
  {
@@ -5724,18 +5891,21 @@ d_lite_plus(VALUE self, VALUE other)
5724
5891
  default:
5725
5892
  expect_numeric(other);
5726
5893
  other = f_to_r(other);
5727
- #ifdef CANONICALIZATION_FOR_MATHN
5728
- if (!k_rational_p(other))
5729
- return d_lite_plus(self, other);
5730
- #endif
5894
+ if (!k_rational_p(other)) {
5895
+ if (!try_rational) Check_Type(other, T_RATIONAL);
5896
+ try_rational = 0;
5897
+ goto again;
5898
+ }
5731
5899
  /* fall through */
5732
5900
  case T_RATIONAL:
5733
5901
  {
5734
5902
  VALUE nth, sf, t;
5735
5903
  int jd, df, s;
5736
5904
 
5737
- if (wholenum_p(other))
5738
- return d_lite_plus(self, rb_rational_num(other));
5905
+ if (wholenum_p(other)) {
5906
+ other = rb_rational_num(other);
5907
+ goto again;
5908
+ }
5739
5909
 
5740
5910
  if (f_positive_p(other))
5741
5911
  s = +1;
@@ -6154,6 +6324,7 @@ static VALUE
6154
6324
  d_lite_step(int argc, VALUE *argv, VALUE self)
6155
6325
  {
6156
6326
  VALUE limit, step, date;
6327
+ int c;
6157
6328
 
6158
6329
  rb_scan_args(argc, argv, "11", &limit, &step);
6159
6330
 
@@ -6168,25 +6339,22 @@ d_lite_step(int argc, VALUE *argv, VALUE self)
6168
6339
  RETURN_ENUMERATOR(self, argc, argv);
6169
6340
 
6170
6341
  date = self;
6171
- switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
6172
- case -1:
6342
+ c = f_cmp(step, INT2FIX(0));
6343
+ if (c < 0) {
6173
6344
  while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
6174
6345
  rb_yield(date);
6175
6346
  date = d_lite_plus(date, step);
6176
6347
  }
6177
- break;
6178
- case 0:
6348
+ }
6349
+ else if (c == 0) {
6179
6350
  while (1)
6180
6351
  rb_yield(date);
6181
- break;
6182
- case 1:
6352
+ }
6353
+ else /* if (c > 0) */ {
6183
6354
  while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
6184
6355
  rb_yield(date);
6185
6356
  date = d_lite_plus(date, step);
6186
6357
  }
6187
- break;
6188
- default:
6189
- abort();
6190
6358
  }
6191
6359
  return self;
6192
6360
  }
@@ -6241,10 +6409,10 @@ cmp_gen(VALUE self, VALUE other)
6241
6409
  get_d1(self);
6242
6410
 
6243
6411
  if (k_numeric_p(other))
6244
- return f_cmp(m_ajd(dat), other);
6412
+ return INT2FIX(f_cmp(m_ajd(dat), other));
6245
6413
  else if (k_date_p(other))
6246
- return f_cmp(m_ajd(dat), f_ajd(other));
6247
- return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
6414
+ return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other)));
6415
+ return rb_num_coerce_cmp(self, other, id_cmp);
6248
6416
  }
6249
6417
 
6250
6418
  static VALUE
@@ -6373,7 +6541,7 @@ equal_gen(VALUE self, VALUE other)
6373
6541
  return f_eqeq_p(m_real_local_jd(dat), other);
6374
6542
  else if (k_date_p(other))
6375
6543
  return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
6376
- return rb_num_coerce_cmp(self, other, rb_intern("=="));
6544
+ return rb_num_coerce_cmp(self, other, id_eqeq_p);
6377
6545
  }
6378
6546
 
6379
6547
  /*
@@ -6444,7 +6612,7 @@ d_lite_hash(VALUE self)
6444
6612
  h[2] = m_df(dat);
6445
6613
  h[3] = m_sf(dat);
6446
6614
  v = rb_memhash(h, sizeof(h));
6447
- return LONG2FIX(v);
6615
+ return ST2FIX(v);
6448
6616
  }
6449
6617
 
6450
6618
  #include "date_tmx.h"
@@ -6471,7 +6639,7 @@ d_lite_to_s(VALUE self)
6471
6639
  static VALUE
6472
6640
  mk_inspect_raw(union DateData *x, VALUE klass)
6473
6641
  {
6474
- char flags[5];
6642
+ char flags[6];
6475
6643
 
6476
6644
  flags[0] = (x->flags & COMPLEX_DAT) ? 'C' : 'S';
6477
6645
  flags[1] = (x->flags & HAVE_JD) ? 'j' : '-';
@@ -6637,7 +6805,9 @@ tmx_m_of(union DateData *x)
6637
6805
  static char *
6638
6806
  tmx_m_zone(union DateData *x)
6639
6807
  {
6640
- return RSTRING_PTR(m_zone(x));
6808
+ VALUE zone = m_zone(x);
6809
+ /* TODO: fix potential dangling pointer */
6810
+ return RSTRING_PTR(zone);
6641
6811
  }
6642
6812
 
6643
6813
  static const struct tmx_funcs tmx_funcs = {
@@ -6787,7 +6957,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6787
6957
  *
6788
6958
  * %M - Minute of the hour (00..59)
6789
6959
  *
6790
- * %S - Second of the minute (00..59)
6960
+ * %S - Second of the minute (00..60)
6791
6961
  *
6792
6962
  * %L - Millisecond of the second (000..999)
6793
6963
  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -6802,7 +6972,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6802
6972
  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
6803
6973
  * %:::z - hour, minute and second offset from UTC
6804
6974
  * (e.g. +09, +09:30, +09:30:30)
6805
- * %Z - Time zone abbreviation name or something similar information.
6975
+ * %Z - Equivalent to %:z (e.g. +09:00)
6806
6976
  *
6807
6977
  * Weekday:
6808
6978
  * %A - The full weekday name (``Sunday'')
@@ -7101,6 +7271,10 @@ d_lite_marshal_dump(VALUE self)
7101
7271
  static VALUE
7102
7272
  d_lite_marshal_load(VALUE self, VALUE a)
7103
7273
  {
7274
+ VALUE nth, sf;
7275
+ int jd, df, of;
7276
+ double sg;
7277
+
7104
7278
  get_d1(self);
7105
7279
 
7106
7280
  rb_check_frozen(self);
@@ -7113,63 +7287,33 @@ d_lite_marshal_load(VALUE self, VALUE a)
7113
7287
  case 2: /* 1.6.x */
7114
7288
  case 3: /* 1.8.x, 1.9.2 */
7115
7289
  {
7116
- VALUE ajd, of, sg, nth, sf;
7117
- int jd, df, rof;
7118
- double rsg;
7119
-
7290
+ VALUE ajd, vof, vsg;
7120
7291
 
7121
7292
  if (RARRAY_LEN(a) == 2) {
7122
7293
  ajd = f_sub(RARRAY_AREF(a, 0), half_days_in_day);
7123
- of = INT2FIX(0);
7124
- sg = RARRAY_AREF(a, 1);
7125
- if (!k_numeric_p(sg))
7126
- sg = DBL2NUM(RTEST(sg) ? GREGORIAN : JULIAN);
7294
+ vof = INT2FIX(0);
7295
+ vsg = RARRAY_AREF(a, 1);
7296
+ if (!k_numeric_p(vsg))
7297
+ vsg = DBL2NUM(RTEST(vsg) ? GREGORIAN : JULIAN);
7127
7298
  }
7128
7299
  else {
7129
7300
  ajd = RARRAY_AREF(a, 0);
7130
- of = RARRAY_AREF(a, 1);
7131
- sg = RARRAY_AREF(a, 2);
7301
+ vof = RARRAY_AREF(a, 1);
7302
+ vsg = RARRAY_AREF(a, 2);
7132
7303
  }
7133
7304
 
7134
- old_to_new(ajd, of, sg,
7135
- &nth, &jd, &df, &sf, &rof, &rsg);
7136
-
7137
- if (!df && f_zero_p(sf) && !rof) {
7138
- set_to_simple(self, &dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD);
7139
- } else {
7140
- if (!complex_dat_p(dat))
7141
- rb_raise(rb_eArgError,
7142
- "cannot load complex into simple");
7143
-
7144
- set_to_complex(self, &dat->c, nth, jd, df, sf, rof, rsg,
7145
- 0, 0, 0, 0, 0, 0,
7146
- HAVE_JD | HAVE_DF | COMPLEX_DAT);
7147
- }
7305
+ old_to_new(ajd, vof, vsg,
7306
+ &nth, &jd, &df, &sf, &of, &sg);
7148
7307
  }
7149
7308
  break;
7150
7309
  case 6:
7151
7310
  {
7152
- VALUE nth, sf;
7153
- int jd, df, of;
7154
- double sg;
7155
-
7156
7311
  nth = RARRAY_AREF(a, 0);
7157
7312
  jd = NUM2INT(RARRAY_AREF(a, 1));
7158
7313
  df = NUM2INT(RARRAY_AREF(a, 2));
7159
7314
  sf = RARRAY_AREF(a, 3);
7160
7315
  of = NUM2INT(RARRAY_AREF(a, 4));
7161
7316
  sg = NUM2DBL(RARRAY_AREF(a, 5));
7162
- if (!df && f_zero_p(sf) && !of) {
7163
- set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7164
- } else {
7165
- if (!complex_dat_p(dat))
7166
- rb_raise(rb_eArgError,
7167
- "cannot load complex into simple");
7168
-
7169
- set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
7170
- 0, 0, 0, 0, 0, 0,
7171
- HAVE_JD | HAVE_DF | COMPLEX_DAT);
7172
- }
7173
7317
  }
7174
7318
  break;
7175
7319
  default:
@@ -7177,6 +7321,18 @@ d_lite_marshal_load(VALUE self, VALUE a)
7177
7321
  break;
7178
7322
  }
7179
7323
 
7324
+ if (simple_dat_p(dat)) {
7325
+ if (df || !f_zero_p(sf) || of) {
7326
+ rb_raise(rb_eArgError,
7327
+ "cannot load complex into simple");
7328
+ }
7329
+ set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7330
+ } else {
7331
+ set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
7332
+ 0, 0, 0, 0, 0, 0,
7333
+ HAVE_JD | HAVE_DF);
7334
+ }
7335
+
7180
7336
  if (FL_TEST(a, FL_EXIVAR)) {
7181
7337
  rb_copy_generic_ivar(self, a);
7182
7338
  FL_SET(self, FL_EXIVAR);
@@ -7356,10 +7512,21 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7356
7512
  */
7357
7513
  static VALUE
7358
7514
  datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7515
+ {
7516
+ return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
7517
+ }
7518
+
7519
+ static VALUE
7520
+ datetime_initialize(int argc, VALUE *argv, VALUE self)
7359
7521
  {
7360
7522
  VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7361
7523
  int m, d, h, min, s, rof;
7362
7524
  double sg;
7525
+ struct ComplexDateData *dat = rb_check_typeddata(self, &d_lite_type);
7526
+
7527
+ if (!complex_dat_p(dat)) {
7528
+ rb_raise(rb_eTypeError, "DateTime expected");
7529
+ }
7363
7530
 
7364
7531
  rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
7365
7532
 
@@ -7403,13 +7570,13 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7403
7570
  rb_raise(rb_eArgError, "invalid date");
7404
7571
  canon24oc();
7405
7572
 
7406
- ret = d_complex_new_internal(klass,
7407
- nth, 0,
7408
- 0, INT2FIX(0),
7409
- rof, sg,
7410
- ry, rm, rd,
7411
- rh, rmin, rs,
7412
- HAVE_CIVIL | HAVE_TIME);
7573
+ set_to_complex(self, dat,
7574
+ nth, 0,
7575
+ 0, INT2FIX(0),
7576
+ rof, sg,
7577
+ ry, rm, rd,
7578
+ rh, rmin, rs,
7579
+ HAVE_CIVIL | HAVE_TIME);
7413
7580
  }
7414
7581
  else {
7415
7582
  VALUE nth;
@@ -7428,14 +7595,15 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7428
7595
  time_to_df(rh, rmin, rs),
7429
7596
  rof);
7430
7597
 
7431
- ret = d_complex_new_internal(klass,
7432
- nth, rjd2,
7433
- 0, INT2FIX(0),
7434
- rof, sg,
7435
- ry, rm, rd,
7436
- rh, rmin, rs,
7437
- HAVE_JD | HAVE_CIVIL | HAVE_TIME);
7598
+ set_to_complex(self, dat,
7599
+ nth, rjd2,
7600
+ 0, INT2FIX(0),
7601
+ rof, sg,
7602
+ ry, rm, rd,
7603
+ rh, rmin, rs,
7604
+ HAVE_JD | HAVE_CIVIL | HAVE_TIME);
7438
7605
  }
7606
+ ret = self;
7439
7607
  add_frac();
7440
7608
  return ret;
7441
7609
  }
@@ -7710,8 +7878,8 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
7710
7878
  s = 59;
7711
7879
  #ifdef HAVE_STRUCT_TM_TM_GMTOFF
7712
7880
  of = tm.tm_gmtoff;
7713
- #elif defined(HAVE_VAR_TIMEZONE)
7714
- #ifdef HAVE_VAR_ALTZONE
7881
+ #elif defined(HAVE_TIMEZONE)
7882
+ #ifdef HAVE_ALTZONE
7715
7883
  of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
7716
7884
  #else
7717
7885
  of = (long)-timezone;
@@ -7927,7 +8095,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7927
8095
 
7928
8096
  /*
7929
8097
  * call-seq:
7930
- * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime
8098
+ * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime
7931
8099
  *
7932
8100
  * Parses the given representation of date and time, and creates a
7933
8101
  * DateTime object. This method does not function as a validator.
@@ -7941,13 +8109,18 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7941
8109
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7942
8110
  * DateTime.parse('3rd Feb 2001 04:05:06 PM')
7943
8111
  * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
8112
+ *
8113
+ * Raise an ArgumentError when the string length is longer than _limit_.
8114
+ * You can stop this check by passing `limit: nil`, but note that
8115
+ * it may take a long time to parse.
7944
8116
  */
7945
8117
  static VALUE
7946
8118
  datetime_s_parse(int argc, VALUE *argv, VALUE klass)
7947
8119
  {
7948
- VALUE str, comp, sg;
8120
+ VALUE str, comp, sg, opt;
7949
8121
 
7950
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
8122
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
8123
+ if (!NIL_P(opt)) argc--;
7951
8124
 
7952
8125
  switch (argc) {
7953
8126
  case 0:
@@ -7959,18 +8132,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
7959
8132
  }
7960
8133
 
7961
8134
  {
7962
- VALUE argv2[2], hash;
7963
-
7964
- argv2[0] = str;
7965
- argv2[1] = comp;
7966
- hash = date_s__parse(2, argv2, klass);
8135
+ int argc2 = 2;
8136
+ VALUE argv2[3];
8137
+ argv2[0] = str;
8138
+ argv2[1] = comp;
8139
+ argv2[2] = opt;
8140
+ if (!NIL_P(opt)) argc2++;
8141
+ VALUE hash = date_s__parse(argc2, argv2, klass);
7967
8142
  return dt_new_by_frags(klass, hash, sg);
7968
8143
  }
7969
8144
  }
7970
8145
 
7971
8146
  /*
7972
8147
  * call-seq:
7973
- * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8148
+ * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
7974
8149
  *
7975
8150
  * Creates a new DateTime object by parsing from a string according to
7976
8151
  * some typical ISO 8601 formats.
@@ -7981,13 +8156,18 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
7981
8156
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7982
8157
  * DateTime.iso8601('2001-W05-6T04:05:06+07:00')
7983
8158
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8159
+ *
8160
+ * Raise an ArgumentError when the string length is longer than _limit_.
8161
+ * You can stop this check by passing `limit: nil`, but note that
8162
+ * it may take a long time to parse.
7984
8163
  */
7985
8164
  static VALUE
7986
8165
  datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
7987
8166
  {
7988
- VALUE str, sg;
8167
+ VALUE str, sg, opt;
7989
8168
 
7990
- rb_scan_args(argc, argv, "02", &str, &sg);
8169
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8170
+ if (!NIL_P(opt)) argc--;
7991
8171
 
7992
8172
  switch (argc) {
7993
8173
  case 0:
@@ -7997,27 +8177,37 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
7997
8177
  }
7998
8178
 
7999
8179
  {
8000
- VALUE hash = date_s__iso8601(klass, str);
8180
+ int argc2 = 1;
8181
+ VALUE argv2[2];
8182
+ argv2[0] = str;
8183
+ argv2[1] = opt;
8184
+ if (!NIL_P(opt)) argc2--;
8185
+ VALUE hash = date_s__iso8601(argc2, argv2, klass);
8001
8186
  return dt_new_by_frags(klass, hash, sg);
8002
8187
  }
8003
8188
  }
8004
8189
 
8005
8190
  /*
8006
8191
  * call-seq:
8007
- * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8192
+ * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8008
8193
  *
8009
8194
  * Creates a new DateTime object by parsing from a string according to
8010
8195
  * some typical RFC 3339 formats.
8011
8196
  *
8012
8197
  * DateTime.rfc3339('2001-02-03T04:05:06+07:00')
8013
8198
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8199
+ *
8200
+ * Raise an ArgumentError when the string length is longer than _limit_.
8201
+ * You can stop this check by passing `limit: nil`, but note that
8202
+ * it may take a long time to parse.
8014
8203
  */
8015
8204
  static VALUE
8016
8205
  datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8017
8206
  {
8018
- VALUE str, sg;
8207
+ VALUE str, sg, opt;
8019
8208
 
8020
- rb_scan_args(argc, argv, "02", &str, &sg);
8209
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8210
+ if (!NIL_P(opt)) argc--;
8021
8211
 
8022
8212
  switch (argc) {
8023
8213
  case 0:
@@ -8027,27 +8217,37 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8027
8217
  }
8028
8218
 
8029
8219
  {
8030
- VALUE hash = date_s__rfc3339(klass, str);
8220
+ int argc2 = 1;
8221
+ VALUE argv2[2];
8222
+ argv2[0] = str;
8223
+ argv2[1] = opt;
8224
+ if (!NIL_P(opt)) argc2++;
8225
+ VALUE hash = date_s__rfc3339(argc2, argv2, klass);
8031
8226
  return dt_new_by_frags(klass, hash, sg);
8032
8227
  }
8033
8228
  }
8034
8229
 
8035
8230
  /*
8036
8231
  * call-seq:
8037
- * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8232
+ * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8038
8233
  *
8039
8234
  * Creates a new DateTime object by parsing from a string according to
8040
8235
  * some typical XML Schema formats.
8041
8236
  *
8042
8237
  * DateTime.xmlschema('2001-02-03T04:05:06+07:00')
8043
8238
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8239
+ *
8240
+ * Raise an ArgumentError when the string length is longer than _limit_.
8241
+ * You can stop this check by passing `limit: nil`, but note that
8242
+ * it may take a long time to parse.
8044
8243
  */
8045
8244
  static VALUE
8046
8245
  datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8047
8246
  {
8048
- VALUE str, sg;
8247
+ VALUE str, sg, opt;
8049
8248
 
8050
- rb_scan_args(argc, argv, "02", &str, &sg);
8249
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8250
+ if (!NIL_P(opt)) argc--;
8051
8251
 
8052
8252
  switch (argc) {
8053
8253
  case 0:
@@ -8057,28 +8257,38 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8057
8257
  }
8058
8258
 
8059
8259
  {
8060
- VALUE hash = date_s__xmlschema(klass, str);
8260
+ int argc2 = 1;
8261
+ VALUE argv2[2];
8262
+ argv2[0] = str;
8263
+ argv2[1] = opt;
8264
+ if (!NIL_P(opt)) argc2++;
8265
+ VALUE hash = date_s__xmlschema(argc2, argv2, klass);
8061
8266
  return dt_new_by_frags(klass, hash, sg);
8062
8267
  }
8063
8268
  }
8064
8269
 
8065
8270
  /*
8066
8271
  * call-seq:
8067
- * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8068
- * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8272
+ * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
8273
+ * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
8069
8274
  *
8070
8275
  * Creates a new DateTime object by parsing from a string according to
8071
8276
  * some typical RFC 2822 formats.
8072
8277
  *
8073
8278
  * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
8074
8279
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8280
+ *
8281
+ * Raise an ArgumentError when the string length is longer than _limit_.
8282
+ * You can stop this check by passing `limit: nil`, but note that
8283
+ * it may take a long time to parse.
8075
8284
  */
8076
8285
  static VALUE
8077
8286
  datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8078
8287
  {
8079
- VALUE str, sg;
8288
+ VALUE str, sg, opt;
8080
8289
 
8081
- rb_scan_args(argc, argv, "02", &str, &sg);
8290
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8291
+ if (!NIL_P(opt)) argc--;
8082
8292
 
8083
8293
  switch (argc) {
8084
8294
  case 0:
@@ -8088,7 +8298,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8088
8298
  }
8089
8299
 
8090
8300
  {
8091
- VALUE hash = date_s__rfc2822(klass, str);
8301
+ int argc2 = 1;
8302
+ VALUE argv2[2];
8303
+ argv2[0] = str;
8304
+ argv2[1] = opt;
8305
+ if (!NIL_P(opt)) argc2++;
8306
+ VALUE hash = date_s__rfc2822(argc2, argv2, klass);
8092
8307
  return dt_new_by_frags(klass, hash, sg);
8093
8308
  }
8094
8309
  }
@@ -8102,13 +8317,18 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8102
8317
  *
8103
8318
  * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
8104
8319
  * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
8320
+ *
8321
+ * Raise an ArgumentError when the string length is longer than _limit_.
8322
+ * You can stop this check by passing `limit: nil`, but note that
8323
+ * it may take a long time to parse.
8105
8324
  */
8106
8325
  static VALUE
8107
8326
  datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8108
8327
  {
8109
- VALUE str, sg;
8328
+ VALUE str, sg, opt;
8110
8329
 
8111
- rb_scan_args(argc, argv, "02", &str, &sg);
8330
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8331
+ if (!NIL_P(opt)) argc--;
8112
8332
 
8113
8333
  switch (argc) {
8114
8334
  case 0:
@@ -8118,27 +8338,37 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8118
8338
  }
8119
8339
 
8120
8340
  {
8121
- VALUE hash = date_s__httpdate(klass, str);
8341
+ int argc2 = 1;
8342
+ VALUE argv2[2];
8343
+ argv2[0] = str;
8344
+ argv2[1] = opt;
8345
+ if (!NIL_P(opt)) argc2++;
8346
+ VALUE hash = date_s__httpdate(argc2, argv2, klass);
8122
8347
  return dt_new_by_frags(klass, hash, sg);
8123
8348
  }
8124
8349
  }
8125
8350
 
8126
8351
  /*
8127
8352
  * call-seq:
8128
- * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8353
+ * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
8129
8354
  *
8130
8355
  * Creates a new DateTime object by parsing from a string according to
8131
8356
  * some typical JIS X 0301 formats.
8132
8357
  *
8133
8358
  * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
8134
8359
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8360
+ *
8361
+ * Raise an ArgumentError when the string length is longer than _limit_.
8362
+ * You can stop this check by passing `limit: nil`, but note that
8363
+ * it may take a long time to parse.
8135
8364
  */
8136
8365
  static VALUE
8137
8366
  datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8138
8367
  {
8139
- VALUE str, sg;
8368
+ VALUE str, sg, opt;
8140
8369
 
8141
- rb_scan_args(argc, argv, "02", &str, &sg);
8370
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
8371
+ if (!NIL_P(opt)) argc--;
8142
8372
 
8143
8373
  switch (argc) {
8144
8374
  case 0:
@@ -8148,7 +8378,12 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8148
8378
  }
8149
8379
 
8150
8380
  {
8151
- VALUE hash = date_s__jisx0301(klass, str);
8381
+ int argc2 = 1;
8382
+ VALUE argv2[2];
8383
+ argv2[0] = str;
8384
+ argv2[1] = opt;
8385
+ if (!NIL_P(opt)) argc2++;
8386
+ VALUE hash = date_s__jisx0301(argc2, argv2, klass);
8152
8387
  return dt_new_by_frags(klass, hash, sg);
8153
8388
  }
8154
8389
  }
@@ -8232,7 +8467,7 @@ dt_lite_to_s(VALUE self)
8232
8467
  *
8233
8468
  * %M - Minute of the hour (00..59)
8234
8469
  *
8235
- * %S - Second of the minute (00..59)
8470
+ * %S - Second of the minute (00..60)
8236
8471
  *
8237
8472
  * %L - Millisecond of the second (000..999)
8238
8473
  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -8247,7 +8482,7 @@ dt_lite_to_s(VALUE self)
8247
8482
  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
8248
8483
  * %:::z - hour, minute and second offset from UTC
8249
8484
  * (e.g. +09, +09:30, +09:30:30)
8250
- * %Z - Time zone abbreviation name or something similar information.
8485
+ * %Z - Equivalent to %:z (e.g. +09:00)
8251
8486
  *
8252
8487
  * Weekday:
8253
8488
  * %A - The full weekday name (``Sunday'')
@@ -8645,7 +8880,7 @@ datetime_to_date(VALUE self)
8645
8880
  VALUE new = d_lite_s_alloc_simple(cDate);
8646
8881
  {
8647
8882
  get_d1b(new);
8648
- copy_complex_to_simple(new, &bdat->s, &adat->c)
8883
+ copy_complex_to_simple(new, &bdat->s, &adat->c);
8649
8884
  bdat->s.jd = m_local_jd(adat);
8650
8885
  bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
8651
8886
  return new;
@@ -9010,14 +9245,18 @@ mk_ary_of_str(long len, const char *a[])
9010
9245
  return o;
9011
9246
  }
9012
9247
 
9248
+ static VALUE
9249
+ d_lite_zero(VALUE x)
9250
+ {
9251
+ return INT2FIX(0);
9252
+ }
9253
+
9013
9254
  void
9014
9255
  Init_date_core(void)
9015
9256
  {
9016
9257
  #undef rb_intern
9017
9258
  #define rb_intern(str) rb_intern_const(str)
9018
9259
 
9019
- assert(fprintf(stderr, "assert() is now active\n"));
9020
-
9021
9260
  id_cmp = rb_intern("<=>");
9022
9261
  id_le_p = rb_intern("<=");
9023
9262
  id_ge_p = rb_intern(">=");
@@ -9233,23 +9472,22 @@ Init_date_core(void)
9233
9472
  */
9234
9473
  rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
9235
9474
 
9236
- rb_define_alloc_func(cDate, d_lite_s_alloc);
9475
+ rb_define_alloc_func(cDate, d_lite_s_alloc_simple);
9237
9476
 
9238
9477
  #ifndef NDEBUG
9239
- #define de_define_private_method rb_define_private_method
9240
- de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9478
+ rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9241
9479
  date_s__valid_jd_p, -1);
9242
- de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9480
+ rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9243
9481
  date_s__valid_ordinal_p, -1);
9244
- de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9482
+ rb_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9245
9483
  date_s__valid_civil_p, -1);
9246
- de_define_private_method(CLASS_OF(cDate), "_valid_date?",
9484
+ rb_define_private_method(CLASS_OF(cDate), "_valid_date?",
9247
9485
  date_s__valid_civil_p, -1);
9248
- de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9486
+ rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9249
9487
  date_s__valid_commercial_p, -1);
9250
- de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9488
+ rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9251
9489
  date_s__valid_weeknum_p, -1);
9252
- de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9490
+ rb_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9253
9491
  date_s__valid_nth_kday_p, -1);
9254
9492
  #endif
9255
9493
 
@@ -9262,11 +9500,11 @@ Init_date_core(void)
9262
9500
  date_s_valid_commercial_p, -1);
9263
9501
 
9264
9502
  #ifndef NDEBUG
9265
- de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9503
+ rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9266
9504
  date_s_valid_weeknum_p, -1);
9267
- de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9505
+ rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9268
9506
  date_s_valid_nth_kday_p, -1);
9269
- de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9507
+ rb_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9270
9508
  date_s_zone_to_diff, 1);
9271
9509
  #endif
9272
9510
 
@@ -9277,21 +9515,18 @@ Init_date_core(void)
9277
9515
  date_s_gregorian_leap_p, 1);
9278
9516
 
9279
9517
  #ifndef NDEBUG
9280
- #define de_define_singleton_method rb_define_singleton_method
9281
- #define de_define_alias rb_define_alias
9282
- de_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
9283
- de_define_alias(rb_singleton_class(cDate), "new_l!", "new");
9518
+ rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
9519
+ rb_define_alias(rb_singleton_class(cDate), "new_l!", "new");
9284
9520
  #endif
9285
9521
 
9286
9522
  rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
9287
9523
  rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
9288
9524
  rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
9289
- rb_define_singleton_method(cDate, "new", date_s_civil, -1);
9290
9525
  rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
9291
9526
 
9292
9527
  #ifndef NDEBUG
9293
- de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
9294
- de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
9528
+ rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
9529
+ rb_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
9295
9530
  #endif
9296
9531
 
9297
9532
  rb_define_singleton_method(cDate, "today", date_s_today, -1);
@@ -9299,29 +9534,26 @@ Init_date_core(void)
9299
9534
  rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
9300
9535
  rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
9301
9536
  rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
9302
- rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
9537
+ rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1);
9303
9538
  rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
9304
- rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
9539
+ rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1);
9305
9540
  rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
9306
- rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
9541
+ rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1);
9307
9542
  rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
9308
- rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
9309
- rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
9543
+ rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1);
9544
+ rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1);
9310
9545
  rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
9311
9546
  rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
9312
- rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
9547
+ rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1);
9313
9548
  rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
9314
- rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
9549
+ rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1);
9315
9550
  rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
9316
9551
 
9317
- #ifndef NDEBUG
9318
- #define de_define_method rb_define_method
9319
- de_define_method(cDate, "initialize", d_lite_initialize, -1);
9320
- #endif
9552
+ rb_define_method(cDate, "initialize", date_initialize, -1);
9321
9553
  rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
9322
9554
 
9323
9555
  #ifndef NDEBUG
9324
- de_define_method(cDate, "fill", d_lite_fill, 0);
9556
+ rb_define_method(cDate, "fill", d_lite_fill, 0);
9325
9557
  #endif
9326
9558
 
9327
9559
  rb_define_method(cDate, "ajd", d_lite_ajd, 0);
@@ -9343,8 +9575,8 @@ Init_date_core(void)
9343
9575
  rb_define_method(cDate, "cwday", d_lite_cwday, 0);
9344
9576
 
9345
9577
  #ifndef NDEBUG
9346
- de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9347
- de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9578
+ rb_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9579
+ rb_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9348
9580
  #endif
9349
9581
 
9350
9582
  rb_define_method(cDate, "wday", d_lite_wday, 0);
@@ -9358,18 +9590,14 @@ Init_date_core(void)
9358
9590
  rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
9359
9591
 
9360
9592
  #ifndef NDEBUG
9361
- de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9593
+ rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9362
9594
  #endif
9363
9595
 
9364
- rb_define_private_method(cDate, "hour", d_lite_hour, 0);
9365
- rb_define_private_method(cDate, "min", d_lite_min, 0);
9366
- rb_define_private_method(cDate, "minute", d_lite_min, 0);
9367
- rb_define_private_method(cDate, "sec", d_lite_sec, 0);
9368
- rb_define_private_method(cDate, "second", d_lite_sec, 0);
9369
- rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0);
9370
- rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0);
9371
- rb_define_private_method(cDate, "offset", d_lite_offset, 0);
9372
- rb_define_private_method(cDate, "zone", d_lite_zone, 0);
9596
+ rb_define_private_method(cDate, "hour", d_lite_zero, 0);
9597
+ rb_define_private_method(cDate, "min", d_lite_zero, 0);
9598
+ rb_define_private_method(cDate, "minute", d_lite_zero, 0);
9599
+ rb_define_private_method(cDate, "sec", d_lite_zero, 0);
9600
+ rb_define_private_method(cDate, "second", d_lite_zero, 0);
9373
9601
 
9374
9602
  rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
9375
9603
  rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
@@ -9382,8 +9610,6 @@ Init_date_core(void)
9382
9610
  rb_define_method(cDate, "julian", d_lite_julian, 0);
9383
9611
  rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
9384
9612
 
9385
- rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1);
9386
-
9387
9613
  rb_define_method(cDate, "+", d_lite_plus, 1);
9388
9614
  rb_define_method(cDate, "-", d_lite_minus, 1);
9389
9615
 
@@ -9411,7 +9637,7 @@ Init_date_core(void)
9411
9637
 
9412
9638
  rb_define_method(cDate, "to_s", d_lite_to_s, 0);
9413
9639
  #ifndef NDEBUG
9414
- de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9640
+ rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9415
9641
  #endif
9416
9642
  rb_define_method(cDate, "inspect", d_lite_inspect, 0);
9417
9643
 
@@ -9428,7 +9654,7 @@ Init_date_core(void)
9428
9654
  rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
9429
9655
 
9430
9656
  #ifndef NDEBUG
9431
- de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9657
+ rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9432
9658
  #endif
9433
9659
  rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
9434
9660
  rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
@@ -9575,6 +9801,7 @@ Init_date_core(void)
9575
9801
  */
9576
9802
 
9577
9803
  cDateTime = rb_define_class("DateTime", cDate);
9804
+ rb_define_alloc_func(cDateTime, d_lite_s_alloc_complex);
9578
9805
 
9579
9806
  rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
9580
9807
  rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
@@ -9584,9 +9811,9 @@ Init_date_core(void)
9584
9811
  datetime_s_commercial, -1);
9585
9812
 
9586
9813
  #ifndef NDEBUG
9587
- de_define_singleton_method(cDateTime, "weeknum",
9814
+ rb_define_singleton_method(cDateTime, "weeknum",
9588
9815
  datetime_s_weeknum, -1);
9589
- de_define_singleton_method(cDateTime, "nth_kday",
9816
+ rb_define_singleton_method(cDateTime, "nth_kday",
9590
9817
  datetime_s_nth_kday, -1);
9591
9818
  #endif
9592
9819
 
@@ -9614,19 +9841,16 @@ Init_date_core(void)
9614
9841
  rb_define_singleton_method(cDateTime, "jisx0301",
9615
9842
  datetime_s_jisx0301, -1);
9616
9843
 
9617
- #define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\
9618
- ID2SYM(rb_intern(s)))
9619
-
9620
- f_public(cDateTime, "hour");
9621
- f_public(cDateTime, "min");
9622
- f_public(cDateTime, "minute");
9623
- f_public(cDateTime, "sec");
9624
- f_public(cDateTime, "second");
9625
- f_public(cDateTime, "sec_fraction");
9626
- f_public(cDateTime, "second_fraction");
9627
- f_public(cDateTime, "offset");
9628
- f_public(cDateTime, "zone");
9629
- f_public(cDateTime, "new_offset");
9844
+ rb_define_method(cDateTime, "hour", d_lite_hour, 0);
9845
+ rb_define_method(cDateTime, "min", d_lite_min, 0);
9846
+ rb_define_method(cDateTime, "minute", d_lite_min, 0);
9847
+ rb_define_method(cDateTime, "sec", d_lite_sec, 0);
9848
+ rb_define_method(cDateTime, "second", d_lite_sec, 0);
9849
+ rb_define_method(cDateTime, "sec_fraction", d_lite_sec_fraction, 0);
9850
+ rb_define_method(cDateTime, "second_fraction", d_lite_sec_fraction, 0);
9851
+ rb_define_method(cDateTime, "offset", d_lite_offset, 0);
9852
+ rb_define_method(cDateTime, "zone", d_lite_zone, 0);
9853
+ rb_define_method(cDateTime, "new_offset", d_lite_new_offset, -1);
9630
9854
 
9631
9855
  rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
9632
9856
 
@@ -9654,15 +9878,15 @@ Init_date_core(void)
9654
9878
  #ifndef NDEBUG
9655
9879
  /* tests */
9656
9880
 
9657
- de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
9658
- de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
9659
- de_define_singleton_method(cDate, "test_commercial",
9881
+ rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
9882
+ rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
9883
+ rb_define_singleton_method(cDate, "test_commercial",
9660
9884
  date_s_test_commercial, 0);
9661
- de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
9662
- de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
9663
- de_define_singleton_method(cDate, "test_unit_conv",
9885
+ rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
9886
+ rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
9887
+ rb_define_singleton_method(cDate, "test_unit_conv",
9664
9888
  date_s_test_unit_conv, 0);
9665
- de_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9889
+ rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9666
9890
  #endif
9667
9891
  }
9668
9892