date 0.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of date might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 76c531a81a5aaf0597367d8eaea3e7b2a7dd7847
4
- data.tar.gz: 384e9b0231e7888d79df4f3e85c1165bd4419563
2
+ SHA256:
3
+ metadata.gz: d4caa8f18343ab584fcbd5be80672d95d6b72574cc75690e2f591fc671f611aa
4
+ data.tar.gz: 0d70fbd67392cfdfa0d080d5626808a1c7fc4f834117da812369bf2910c90317
5
5
  SHA512:
6
- metadata.gz: c9ea63e7c2271aef8be4cb3846beac070911af8a5e5c985932c7f415af23a08b70a878fee239a5cf09406e18749ca4ad1804c14ac420883ea3048620e54c5aff
7
- data.tar.gz: 89542c8337ab2b99f7aec9b51210149684501cf1021e875e32d292f7fd6fa756e773f947dc2018d721042f15fdfd74713e6ed395eee5bb6ee3990301633b896b
6
+ metadata.gz: 3b36c300a66f6dc671293c647e73014dff9c0460216c177a4cff0977973ca62029b3b9053b87d135a50d3885832edbbc36f0f37280008dca39da711d8070f5c6
7
+ data.tar.gz: a18e531345a4da23054d03e8480d76afdba97f97a12e56ca840a0dafd6467a1a5d1f9ec9b7e04b0fe6d9e088c1fec078042508aa9cd09e78d4941dc41701662d
@@ -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
 
@@ -51,18 +53,31 @@ static double positive_inf, negative_inf;
51
53
  #define f_add3(x,y,z) f_add(f_add(x, y), z)
52
54
  #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
53
55
 
54
- inline static VALUE
56
+ #define f_frozen_ary(...) rb_obj_freeze(rb_ary_new3(__VA_ARGS__))
57
+
58
+ static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
59
+ static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
60
+
61
+ #define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse
62
+ inline static void
63
+ check_numeric(VALUE obj, const char* field) {
64
+ if(!RTEST(rb_obj_is_kind_of(obj, rb_cNumeric))) {
65
+ rb_raise(rb_eTypeError, "invalid %s (not numeric)", field);
66
+ }
67
+ }
68
+
69
+ inline static int
55
70
  f_cmp(VALUE x, VALUE y)
56
71
  {
57
72
  if (FIXNUM_P(x) && FIXNUM_P(y)) {
58
73
  long c = FIX2LONG(x) - FIX2LONG(y);
59
74
  if (c > 0)
60
- c = 1;
75
+ return 1;
61
76
  else if (c < 0)
62
- c = -1;
63
- return INT2FIX(c);
77
+ return -1;
78
+ return 0;
64
79
  }
65
- return rb_funcall(x, id_cmp, 1, y);
80
+ return rb_cmpint(rb_funcallv(x, id_cmp, 1, &y), x, y);
66
81
  }
67
82
 
68
83
  inline static VALUE
@@ -94,7 +109,7 @@ f_ge_p(VALUE x, VALUE y)
94
109
  {
95
110
  if (FIXNUM_P(x) && FIXNUM_P(y))
96
111
  return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
97
- return rb_funcall(x, rb_intern(">="), 1, y);
112
+ return rb_funcall(x, id_ge_p, 1, y);
98
113
  }
99
114
 
100
115
  inline static VALUE
@@ -102,7 +117,7 @@ f_eqeq_p(VALUE x, VALUE y)
102
117
  {
103
118
  if (FIXNUM_P(x) && FIXNUM_P(y))
104
119
  return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
105
- return rb_funcall(x, rb_intern("=="), 1, y);
120
+ return rb_funcall(x, id_eqeq_p, 1, y);
106
121
  }
107
122
 
108
123
  inline static VALUE
@@ -236,11 +251,8 @@ f_negative_p(VALUE x)
236
251
  struct SimpleDateData
237
252
  {
238
253
  unsigned flags;
239
- VALUE nth; /* not always canonicalized */
240
254
  int jd; /* as utc */
241
- /* df is zero */
242
- /* sf is zero */
243
- /* of is zero */
255
+ VALUE nth; /* not always canonicalized */
244
256
  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
245
257
  /* decoded as utc=local */
246
258
  int year; /* truncated */
@@ -259,11 +271,8 @@ struct SimpleDateData
259
271
  struct ComplexDateData
260
272
  {
261
273
  unsigned flags;
262
- VALUE nth; /* not always canonicalized */
263
274
  int jd; /* as utc */
264
- int df; /* as utc, in secs */
265
- VALUE sf; /* in nano secs */
266
- int of; /* in secs */
275
+ VALUE nth; /* not always canonicalized */
267
276
  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
268
277
  /* decoded as local */
269
278
  int year; /* truncated */
@@ -277,6 +286,9 @@ struct ComplexDateData
277
286
  /* packed civil */
278
287
  unsigned pc;
279
288
  #endif
289
+ int df; /* as utc, in secs */
290
+ int of; /* in secs */
291
+ VALUE sf; /* in nano secs */
280
292
  };
281
293
 
282
294
  union DateData {
@@ -315,31 +327,31 @@ canon(VALUE x)
315
327
 
316
328
  #ifndef USE_PACK
317
329
  #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
318
- {\
330
+ do {\
319
331
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
320
332
  (x)->jd = _jd;\
321
333
  (x)->sg = (date_sg_t)(_sg);\
322
334
  (x)->year = _year;\
323
335
  (x)->mon = _mon;\
324
336
  (x)->mday = _mday;\
325
- (x)->flags = _flags;\
326
- }
337
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
338
+ } while (0)
327
339
  #else
328
340
  #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
329
- {\
341
+ do {\
330
342
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
331
343
  (x)->jd = _jd;\
332
344
  (x)->sg = (date_sg_t)(_sg);\
333
345
  (x)->year = _year;\
334
346
  (x)->pc = PACK2(_mon, _mday);\
335
- (x)->flags = _flags;\
336
- }
347
+ (x)->flags = (_flags) & ~COMPLEX_DAT;\
348
+ } while (0)
337
349
  #endif
338
350
 
339
351
  #ifndef USE_PACK
340
352
  #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
341
353
  _year, _mon, _mday, _hour, _min, _sec, _flags) \
342
- {\
354
+ do {\
343
355
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
344
356
  (x)->jd = _jd;\
345
357
  (x)->df = _df;\
@@ -352,12 +364,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
352
364
  (x)->hour = _hour;\
353
365
  (x)->min = _min;\
354
366
  (x)->sec = _sec;\
355
- (x)->flags = _flags;\
356
- }
367
+ (x)->flags = (_flags) | COMPLEX_DAT;\
368
+ } while (0)
357
369
  #else
358
370
  #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
359
371
  _year, _mon, _mday, _hour, _min, _sec, _flags) \
360
- {\
372
+ do {\
361
373
  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
362
374
  (x)->jd = _jd;\
363
375
  (x)->df = _df;\
@@ -366,13 +378,13 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
366
378
  (x)->sg = (date_sg_t)(_sg);\
367
379
  (x)->year = _year;\
368
380
  (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
369
- (x)->flags = _flags;\
370
- }
381
+ (x)->flags = (_flags) | COMPLEX_DAT;\
382
+ } while (0)
371
383
  #endif
372
384
 
373
385
  #ifndef USE_PACK
374
386
  #define copy_simple_to_complex(obj, x, y) \
375
- {\
387
+ do {\
376
388
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
377
389
  (x)->jd = (y)->jd;\
378
390
  (x)->df = 0;\
@@ -386,10 +398,10 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
386
398
  (x)->min = 0;\
387
399
  (x)->sec = 0;\
388
400
  (x)->flags = (y)->flags;\
389
- }
401
+ } while (0)
390
402
  #else
391
403
  #define copy_simple_to_complex(obj, x, y) \
392
- {\
404
+ do {\
393
405
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
394
406
  (x)->jd = (y)->jd;\
395
407
  (x)->df = 0;\
@@ -399,12 +411,12 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
399
411
  (x)->year = (y)->year;\
400
412
  (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
401
413
  (x)->flags = (y)->flags;\
402
- }
414
+ } while (0)
403
415
  #endif
404
416
 
405
417
  #ifndef USE_PACK
406
418
  #define copy_complex_to_simple(obj, x, y) \
407
- {\
419
+ do {\
408
420
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
409
421
  (x)->jd = (y)->jd;\
410
422
  (x)->sg = (date_sg_t)((y)->sg);\
@@ -412,17 +424,17 @@ _year, _mon, _mday, _hour, _min, _sec, _flags) \
412
424
  (x)->mon = (y)->mon;\
413
425
  (x)->mday = (y)->mday;\
414
426
  (x)->flags = (y)->flags;\
415
- }
427
+ } while (0)
416
428
  #else
417
429
  #define copy_complex_to_simple(obj, x, y) \
418
- {\
430
+ do {\
419
431
  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
420
432
  (x)->jd = (y)->jd;\
421
433
  (x)->sg = (date_sg_t)((y)->sg);\
422
434
  (x)->year = (y)->year;\
423
435
  (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
424
436
  (x)->flags = (y)->flags;\
425
- }
437
+ } while (0)
426
438
  #endif
427
439
 
428
440
  /* base */
@@ -1109,7 +1121,7 @@ m_virtual_sg(union DateData *x)
1109
1121
  }
1110
1122
 
1111
1123
  #define canonicalize_jd(_nth, _jd) \
1112
- {\
1124
+ do {\
1113
1125
  if (_jd < 0) {\
1114
1126
  _nth = f_sub(_nth, INT2FIX(1));\
1115
1127
  _jd += CM_PERIOD;\
@@ -1118,7 +1130,7 @@ m_virtual_sg(union DateData *x)
1118
1130
  _nth = f_add(_nth, INT2FIX(1));\
1119
1131
  _jd -= CM_PERIOD;\
1120
1132
  }\
1121
- }
1133
+ } while (0)
1122
1134
 
1123
1135
  inline static void
1124
1136
  canonicalize_s_jd(VALUE obj, union DateData *x)
@@ -1928,13 +1940,13 @@ m_sec(union DateData *x)
1928
1940
  }
1929
1941
 
1930
1942
  #define decode_offset(of,s,h,m)\
1931
- {\
1943
+ do {\
1932
1944
  int a;\
1933
1945
  s = (of < 0) ? '-' : '+';\
1934
1946
  a = (of < 0) ? -of : of;\
1935
1947
  h = a / HOUR_IN_SECONDS;\
1936
1948
  m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
1937
- }
1949
+ } while (0)
1938
1950
 
1939
1951
  static VALUE
1940
1952
  of2str(int of)
@@ -2333,6 +2345,9 @@ VALUE date_zone_to_diff(VALUE);
2333
2345
  static int
2334
2346
  offset_to_sec(VALUE vof, int *rof)
2335
2347
  {
2348
+ int try_rational = 1;
2349
+
2350
+ again:
2336
2351
  switch (TYPE(vof)) {
2337
2352
  case T_FIXNUM:
2338
2353
  {
@@ -2359,10 +2374,11 @@ offset_to_sec(VALUE vof, int *rof)
2359
2374
  default:
2360
2375
  expect_numeric(vof);
2361
2376
  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
2377
+ if (!k_rational_p(vof)) {
2378
+ if (!try_rational) Check_Type(vof, T_RATIONAL);
2379
+ try_rational = 0;
2380
+ goto again;
2381
+ }
2366
2382
  /* fall through */
2367
2383
  case T_RATIONAL:
2368
2384
  {
@@ -2371,17 +2387,10 @@ offset_to_sec(VALUE vof, int *rof)
2371
2387
 
2372
2388
  vs = day_to_sec(vof);
2373
2389
 
2374
- #ifdef CANONICALIZATION_FOR_MATHN
2375
2390
  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;
2391
+ vn = vs;
2392
+ goto rounded;
2383
2393
  }
2384
- #endif
2385
2394
  vn = rb_rational_num(vs);
2386
2395
  vd = rb_rational_den(vs);
2387
2396
 
@@ -2391,6 +2400,7 @@ offset_to_sec(VALUE vof, int *rof)
2391
2400
  vn = f_round(vs);
2392
2401
  if (!f_eqeq_p(vn, vs))
2393
2402
  rb_warning("fraction of offset is ignored");
2403
+ rounded:
2394
2404
  if (!FIXNUM_P(vn))
2395
2405
  return 0;
2396
2406
  n = FIX2LONG(vn);
@@ -2420,12 +2430,12 @@ offset_to_sec(VALUE vof, int *rof)
2420
2430
  /* date */
2421
2431
 
2422
2432
  #define valid_sg(sg) \
2423
- {\
2433
+ do {\
2424
2434
  if (!c_valid_start_p(sg)) {\
2425
2435
  sg = 0;\
2426
2436
  rb_warning("invalid start is ignored");\
2427
2437
  }\
2428
- }
2438
+ } while (0)
2429
2439
 
2430
2440
  static VALUE
2431
2441
  valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
@@ -2472,6 +2482,7 @@ date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
2472
2482
 
2473
2483
  rb_scan_args(argc, argv, "11", &vjd, &vsg);
2474
2484
 
2485
+ RETURN_FALSE_UNLESS_NUMERIC(vjd);
2475
2486
  argv2[0] = vjd;
2476
2487
  if (argc < 2)
2477
2488
  argv2[1] = INT2FIX(DEFAULT_SG);
@@ -2547,9 +2558,12 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
2547
2558
  * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool
2548
2559
  *
2549
2560
  * Returns true if the given calendar date is valid, and false if not.
2561
+ * Valid in this context is whether the arguments passed to this
2562
+ * method would be accepted by ::new.
2550
2563
  *
2551
2564
  * Date.valid_date?(2001,2,3) #=> true
2552
2565
  * Date.valid_date?(2001,2,29) #=> false
2566
+ * Date.valid_date?(2001,2,-1) #=> true
2553
2567
  *
2554
2568
  * See also ::jd and ::civil.
2555
2569
  */
@@ -2561,6 +2575,9 @@ date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
2561
2575
 
2562
2576
  rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2563
2577
 
2578
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2579
+ RETURN_FALSE_UNLESS_NUMERIC(vm);
2580
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2564
2581
  argv2[0] = vy;
2565
2582
  argv2[1] = vm;
2566
2583
  argv2[2] = vd;
@@ -2642,6 +2659,8 @@ date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2642
2659
 
2643
2660
  rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2644
2661
 
2662
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2663
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2645
2664
  argv2[0] = vy;
2646
2665
  argv2[1] = vd;
2647
2666
  if (argc < 3)
@@ -2724,6 +2743,9 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2724
2743
 
2725
2744
  rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2726
2745
 
2746
+ RETURN_FALSE_UNLESS_NUMERIC(vy);
2747
+ RETURN_FALSE_UNLESS_NUMERIC(vw);
2748
+ RETURN_FALSE_UNLESS_NUMERIC(vd);
2727
2749
  argv2[0] = vy;
2728
2750
  argv2[1] = vw;
2729
2751
  argv2[2] = vd;
@@ -2905,6 +2927,7 @@ date_s_julian_leap_p(VALUE klass, VALUE y)
2905
2927
  VALUE nth;
2906
2928
  int ry;
2907
2929
 
2930
+ check_numeric(y, "year");
2908
2931
  decode_year(y, +1, &nth, &ry);
2909
2932
  return f_boolcast(c_julian_leap_p(ry));
2910
2933
  }
@@ -2926,6 +2949,7 @@ date_s_gregorian_leap_p(VALUE klass, VALUE y)
2926
2949
  VALUE nth;
2927
2950
  int ry;
2928
2951
 
2952
+ check_numeric(y, "year");
2929
2953
  decode_year(y, -1, &nth, &ry);
2930
2954
  return f_boolcast(c_gregorian_leap_p(ry));
2931
2955
  }
@@ -2953,7 +2977,7 @@ static const rb_data_type_t d_lite_type = {
2953
2977
  "Date",
2954
2978
  {d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
2955
2979
  0, 0,
2956
- RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED,
2980
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
2957
2981
  };
2958
2982
 
2959
2983
  inline static VALUE
@@ -2968,7 +2992,7 @@ d_simple_new_internal(VALUE klass,
2968
2992
 
2969
2993
  obj = TypedData_Make_Struct(klass, struct SimpleDateData,
2970
2994
  &d_lite_type, dat);
2971
- set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
2995
+ set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
2972
2996
 
2973
2997
  assert(have_jd_p(dat) || have_civil_p(dat));
2974
2998
 
@@ -2990,7 +3014,7 @@ d_complex_new_internal(VALUE klass,
2990
3014
  obj = TypedData_Make_Struct(klass, struct ComplexDateData,
2991
3015
  &d_lite_type, dat);
2992
3016
  set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
2993
- y, m, d, h, min, s, flags | COMPLEX_DAT);
3017
+ y, m, d, h, min, s, flags);
2994
3018
 
2995
3019
  assert(have_jd_p(dat) || have_civil_p(dat));
2996
3020
  assert(have_df_p(dat) || have_time_p(dat));
@@ -3049,7 +3073,7 @@ old_to_new(VALUE ajd, VALUE of, VALUE sg,
3049
3073
  *rsg = NUM2DBL(sg);
3050
3074
 
3051
3075
  if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
3052
- rb_raise(rb_eArgError, "invalid day fraction");
3076
+ rb_raise(eDateError, "invalid day fraction");
3053
3077
 
3054
3078
  if (f_lt_p(*rsf, INT2FIX(0)) ||
3055
3079
  f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
@@ -3207,47 +3231,47 @@ s_trunc(VALUE s, VALUE *fr)
3207
3231
  }
3208
3232
 
3209
3233
  #define num2num_with_frac(s,n) \
3210
- {\
3234
+ do {\
3211
3235
  s = s##_trunc(v##s, &fr);\
3212
3236
  if (f_nonzero_p(fr)) {\
3213
3237
  if (argc > n)\
3214
- rb_raise(rb_eArgError, "invalid fraction");\
3238
+ rb_raise(eDateError, "invalid fraction");\
3215
3239
  fr2 = fr;\
3216
3240
  }\
3217
- }
3241
+ } while (0)
3218
3242
 
3219
3243
  #define num2int_with_frac(s,n) \
3220
- {\
3244
+ do {\
3221
3245
  s = NUM2INT(s##_trunc(v##s, &fr));\
3222
3246
  if (f_nonzero_p(fr)) {\
3223
3247
  if (argc > n)\
3224
- rb_raise(rb_eArgError, "invalid fraction");\
3248
+ rb_raise(eDateError, "invalid fraction");\
3225
3249
  fr2 = fr;\
3226
3250
  }\
3227
- }
3251
+ } while (0)
3228
3252
 
3229
3253
  #define canon24oc() \
3230
- {\
3254
+ do {\
3231
3255
  if (rh == 24) {\
3232
3256
  rh = 0;\
3233
3257
  fr2 = f_add(fr2, INT2FIX(1));\
3234
3258
  }\
3235
- }
3259
+ } while (0)
3236
3260
 
3237
3261
  #define add_frac() \
3238
- {\
3262
+ do {\
3239
3263
  if (f_nonzero_p(fr2))\
3240
3264
  ret = d_lite_plus(ret, fr2);\
3241
- }
3265
+ } while (0)
3242
3266
 
3243
3267
  #define val2sg(vsg,dsg) \
3244
- {\
3268
+ do {\
3245
3269
  dsg = NUM2DBL(vsg);\
3246
3270
  if (!c_valid_start_p(dsg)) {\
3247
3271
  dsg = DEFAULT_SG;\
3248
3272
  rb_warning("invalid start is ignored");\
3249
3273
  }\
3250
- }
3274
+ } while (0)
3251
3275
 
3252
3276
  static VALUE d_lite_plus(VALUE, VALUE);
3253
3277
 
@@ -3280,6 +3304,7 @@ date_s_jd(int argc, VALUE *argv, VALUE klass)
3280
3304
  case 2:
3281
3305
  val2sg(vsg, sg);
3282
3306
  case 1:
3307
+ check_numeric(vjd, "jd");
3283
3308
  num2num_with_frac(jd, positive_inf);
3284
3309
  }
3285
3310
 
@@ -3332,8 +3357,10 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3332
3357
  case 3:
3333
3358
  val2sg(vsg, sg);
3334
3359
  case 2:
3360
+ check_numeric(vd, "yday");
3335
3361
  num2int_with_frac(d, positive_inf);
3336
3362
  case 1:
3363
+ check_numeric(vy, "year");
3337
3364
  y = vy;
3338
3365
  }
3339
3366
 
@@ -3345,7 +3372,7 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3345
3372
  &nth, &ry,
3346
3373
  &rd, &rjd,
3347
3374
  &ns))
3348
- rb_raise(rb_eArgError, "invalid date");
3375
+ rb_raise(eDateError, "invalid date");
3349
3376
 
3350
3377
  ret = d_simple_new_internal(klass,
3351
3378
  nth, rjd,
@@ -3384,10 +3411,21 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3384
3411
  */
3385
3412
  static VALUE
3386
3413
  date_s_civil(int argc, VALUE *argv, VALUE klass)
3414
+ {
3415
+ return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
3416
+ }
3417
+
3418
+ static VALUE
3419
+ date_initialize(int argc, VALUE *argv, VALUE self)
3387
3420
  {
3388
3421
  VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
3389
3422
  int m, d;
3390
3423
  double sg;
3424
+ struct SimpleDateData *dat = rb_check_typeddata(self, &d_lite_type);
3425
+
3426
+ if (!simple_dat_p(dat)) {
3427
+ rb_raise(rb_eTypeError, "Date expected");
3428
+ }
3391
3429
 
3392
3430
  rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
3393
3431
 
@@ -3401,10 +3439,13 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
3401
3439
  case 4:
3402
3440
  val2sg(vsg, sg);
3403
3441
  case 3:
3442
+ check_numeric(vd, "day");
3404
3443
  num2int_with_frac(d, positive_inf);
3405
3444
  case 2:
3445
+ check_numeric(vm, "month");
3406
3446
  m = NUM2INT(vm);
3407
3447
  case 1:
3448
+ check_numeric(vy, "year");
3408
3449
  y = vy;
3409
3450
  }
3410
3451
 
@@ -3415,13 +3456,9 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
3415
3456
  if (!valid_gregorian_p(y, m, d,
3416
3457
  &nth, &ry,
3417
3458
  &rm, &rd))
3418
- rb_raise(rb_eArgError, "invalid date");
3459
+ rb_raise(eDateError, "invalid date");
3419
3460
 
3420
- ret = d_simple_new_internal(klass,
3421
- nth, 0,
3422
- sg,
3423
- ry, rm, rd,
3424
- HAVE_CIVIL);
3461
+ set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
3425
3462
  }
3426
3463
  else {
3427
3464
  VALUE nth;
@@ -3431,14 +3468,11 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
3431
3468
  &nth, &ry,
3432
3469
  &rm, &rd, &rjd,
3433
3470
  &ns))
3434
- rb_raise(rb_eArgError, "invalid date");
3471
+ rb_raise(eDateError, "invalid date");
3435
3472
 
3436
- ret = d_simple_new_internal(klass,
3437
- nth, rjd,
3438
- sg,
3439
- ry, rm, rd,
3440
- HAVE_JD | HAVE_CIVIL);
3473
+ set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
3441
3474
  }
3475
+ ret = self;
3442
3476
  add_frac();
3443
3477
  return ret;
3444
3478
  }
@@ -3478,10 +3512,13 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
3478
3512
  case 4:
3479
3513
  val2sg(vsg, sg);
3480
3514
  case 3:
3515
+ check_numeric(vd, "cwday");
3481
3516
  num2int_with_frac(d, positive_inf);
3482
3517
  case 2:
3518
+ check_numeric(vw, "cweek");
3483
3519
  w = NUM2INT(vw);
3484
3520
  case 1:
3521
+ check_numeric(vy, "year");
3485
3522
  y = vy;
3486
3523
  }
3487
3524
 
@@ -3493,7 +3530,7 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
3493
3530
  &nth, &ry,
3494
3531
  &rw, &rd, &rjd,
3495
3532
  &ns))
3496
- rb_raise(rb_eArgError, "invalid date");
3533
+ rb_raise(eDateError, "invalid date");
3497
3534
 
3498
3535
  ret = d_simple_new_internal(klass,
3499
3536
  nth, rjd,
@@ -3543,7 +3580,7 @@ date_s_weeknum(int argc, VALUE *argv, VALUE klass)
3543
3580
  &nth, &ry,
3544
3581
  &rw, &rd, &rjd,
3545
3582
  &ns))
3546
- rb_raise(rb_eArgError, "invalid date");
3583
+ rb_raise(eDateError, "invalid date");
3547
3584
 
3548
3585
  ret = d_simple_new_internal(klass,
3549
3586
  nth, rjd,
@@ -3592,7 +3629,7 @@ date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
3592
3629
  &nth, &ry,
3593
3630
  &rm, &rn, &rk, &rjd,
3594
3631
  &ns))
3595
- rb_raise(rb_eArgError, "invalid date");
3632
+ rb_raise(eDateError, "invalid date");
3596
3633
 
3597
3634
  ret = d_simple_new_internal(klass,
3598
3635
  nth, rjd,
@@ -3679,16 +3716,18 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
3679
3716
  #define ref_hash0(k) rb_hash_aref(hash, k)
3680
3717
  #define del_hash0(k) rb_hash_delete(hash, k)
3681
3718
 
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)))
3719
+ #define sym(x) ID2SYM(rb_intern(x""))
3720
+
3721
+ #define set_hash(k,v) set_hash0(sym(k), v)
3722
+ #define ref_hash(k) ref_hash0(sym(k))
3723
+ #define del_hash(k) del_hash0(sym(k))
3685
3724
 
3686
3725
  static VALUE
3687
3726
  rt_rewrite_frags(VALUE hash)
3688
3727
  {
3689
3728
  VALUE seconds;
3690
3729
 
3691
- seconds = ref_hash("seconds");
3730
+ seconds = del_hash("seconds");
3692
3731
  if (!NIL_P(seconds)) {
3693
3732
  VALUE offset, d, h, min, s, fr;
3694
3733
 
@@ -3713,13 +3752,10 @@ rt_rewrite_frags(VALUE hash)
3713
3752
  set_hash("min", min);
3714
3753
  set_hash("sec", s);
3715
3754
  set_hash("sec_fraction", fr);
3716
- del_hash("seconds");
3717
3755
  }
3718
3756
  return hash;
3719
3757
  }
3720
3758
 
3721
- #define sym(x) ID2SYM(rb_intern(x))
3722
-
3723
3759
  static VALUE d_lite_year(VALUE);
3724
3760
  static VALUE d_lite_wday(VALUE);
3725
3761
  static VALUE d_lite_jd(VALUE);
@@ -3733,89 +3769,89 @@ rt_complete_frags(VALUE klass, VALUE hash)
3733
3769
  VALUE k, a, d;
3734
3770
 
3735
3771
  if (NIL_P(tab)) {
3736
- tab = rb_ary_new3(11,
3737
- rb_ary_new3(2,
3772
+ tab = f_frozen_ary(11,
3773
+ f_frozen_ary(2,
3738
3774
  sym("time"),
3739
- rb_ary_new3(3,
3775
+ f_frozen_ary(3,
3740
3776
  sym("hour"),
3741
3777
  sym("min"),
3742
3778
  sym("sec"))),
3743
- rb_ary_new3(2,
3779
+ f_frozen_ary(2,
3744
3780
  Qnil,
3745
- rb_ary_new3(1,
3781
+ f_frozen_ary(1,
3746
3782
  sym("jd"))),
3747
- rb_ary_new3(2,
3783
+ f_frozen_ary(2,
3748
3784
  sym("ordinal"),
3749
- rb_ary_new3(5,
3785
+ f_frozen_ary(5,
3750
3786
  sym("year"),
3751
3787
  sym("yday"),
3752
3788
  sym("hour"),
3753
3789
  sym("min"),
3754
3790
  sym("sec"))),
3755
- rb_ary_new3(2,
3791
+ f_frozen_ary(2,
3756
3792
  sym("civil"),
3757
- rb_ary_new3(6,
3793
+ f_frozen_ary(6,
3758
3794
  sym("year"),
3759
3795
  sym("mon"),
3760
3796
  sym("mday"),
3761
3797
  sym("hour"),
3762
3798
  sym("min"),
3763
3799
  sym("sec"))),
3764
- rb_ary_new3(2,
3800
+ f_frozen_ary(2,
3765
3801
  sym("commercial"),
3766
- rb_ary_new3(6,
3802
+ f_frozen_ary(6,
3767
3803
  sym("cwyear"),
3768
3804
  sym("cweek"),
3769
3805
  sym("cwday"),
3770
3806
  sym("hour"),
3771
3807
  sym("min"),
3772
3808
  sym("sec"))),
3773
- rb_ary_new3(2,
3809
+ f_frozen_ary(2,
3774
3810
  sym("wday"),
3775
- rb_ary_new3(4,
3811
+ f_frozen_ary(4,
3776
3812
  sym("wday"),
3777
3813
  sym("hour"),
3778
3814
  sym("min"),
3779
3815
  sym("sec"))),
3780
- rb_ary_new3(2,
3816
+ f_frozen_ary(2,
3781
3817
  sym("wnum0"),
3782
- rb_ary_new3(6,
3818
+ f_frozen_ary(6,
3783
3819
  sym("year"),
3784
3820
  sym("wnum0"),
3785
3821
  sym("wday"),
3786
3822
  sym("hour"),
3787
3823
  sym("min"),
3788
3824
  sym("sec"))),
3789
- rb_ary_new3(2,
3825
+ f_frozen_ary(2,
3790
3826
  sym("wnum1"),
3791
- rb_ary_new3(6,
3827
+ f_frozen_ary(6,
3792
3828
  sym("year"),
3793
3829
  sym("wnum1"),
3794
3830
  sym("wday"),
3795
3831
  sym("hour"),
3796
3832
  sym("min"),
3797
3833
  sym("sec"))),
3798
- rb_ary_new3(2,
3834
+ f_frozen_ary(2,
3799
3835
  Qnil,
3800
- rb_ary_new3(6,
3836
+ f_frozen_ary(6,
3801
3837
  sym("cwyear"),
3802
3838
  sym("cweek"),
3803
3839
  sym("wday"),
3804
3840
  sym("hour"),
3805
3841
  sym("min"),
3806
3842
  sym("sec"))),
3807
- rb_ary_new3(2,
3843
+ f_frozen_ary(2,
3808
3844
  Qnil,
3809
- rb_ary_new3(6,
3845
+ f_frozen_ary(6,
3810
3846
  sym("year"),
3811
3847
  sym("wnum0"),
3812
3848
  sym("cwday"),
3813
3849
  sym("hour"),
3814
3850
  sym("min"),
3815
3851
  sym("sec"))),
3816
- rb_ary_new3(2,
3852
+ f_frozen_ary(2,
3817
3853
  Qnil,
3818
- rb_ary_new3(6,
3854
+ f_frozen_ary(6,
3819
3855
  sym("year"),
3820
3856
  sym("wnum1"),
3821
3857
  sym("cwday"),
@@ -4140,7 +4176,7 @@ d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4140
4176
  }
4141
4177
 
4142
4178
  if (NIL_P(hash))
4143
- rb_raise(rb_eArgError, "invalid date");
4179
+ rb_raise(eDateError, "invalid date");
4144
4180
 
4145
4181
  if (NIL_P(ref_hash("jd")) &&
4146
4182
  NIL_P(ref_hash("yday")) &&
@@ -4157,7 +4193,7 @@ d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4157
4193
  }
4158
4194
 
4159
4195
  if (NIL_P(jd))
4160
- rb_raise(rb_eArgError, "invalid date");
4196
+ rb_raise(eDateError, "invalid date");
4161
4197
  {
4162
4198
  VALUE nth;
4163
4199
  int rjd;
@@ -4212,12 +4248,10 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
4212
4248
 
4213
4249
  if (!NIL_P(zone)) {
4214
4250
  rb_enc_copy(zone, vstr);
4215
- OBJ_INFECT(zone, vstr);
4216
4251
  set_hash("zone", zone);
4217
4252
  }
4218
4253
  if (!NIL_P(left)) {
4219
4254
  rb_enc_copy(left, vstr);
4220
- OBJ_INFECT(left, vstr);
4221
4255
  set_hash("leftover", left);
4222
4256
  }
4223
4257
  }
@@ -4305,16 +4339,6 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4305
4339
 
4306
4340
  hash = date__parse(vstr, vcomp);
4307
4341
 
4308
- {
4309
- VALUE zone = ref_hash("zone");
4310
-
4311
- if (!NIL_P(zone)) {
4312
- rb_enc_copy(zone, vstr);
4313
- OBJ_INFECT(zone, vstr);
4314
- set_hash("zone", zone);
4315
- }
4316
- }
4317
-
4318
4342
  return hash;
4319
4343
  }
4320
4344
 
@@ -4323,8 +4347,12 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4323
4347
  * Date._parse(string[, comp=true]) -> hash
4324
4348
  *
4325
4349
  * Parses the given representation of date and time, and returns a
4326
- * hash of parsed elements. This method does not function as a
4327
- * validator.
4350
+ * hash of parsed elements.
4351
+ *
4352
+ * This method **does not** function as a validator. If the input
4353
+ * string does not match valid formats strictly, you may get a cryptic
4354
+ * result. Should consider to use `Date._strptime` or
4355
+ * `DateTime._strptime` instead of this method as possible.
4328
4356
  *
4329
4357
  * If the optional second argument is true and the detected year is in
4330
4358
  * the range "00" to "99", considers the year a 2-digit form and makes
@@ -4343,7 +4371,12 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
4343
4371
  * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date
4344
4372
  *
4345
4373
  * Parses the given representation of date and time, and creates a
4346
- * date object. This method does not function as a validator.
4374
+ * date object.
4375
+ *
4376
+ * This method **does not** function as a validator. If the input
4377
+ * string does not match valid formats strictly, you may get a cryptic
4378
+ * result. Should consider to use `Date.strptime` instead of this
4379
+ * method as possible.
4347
4380
  *
4348
4381
  * If the optional second argument is true and the detected year is in
4349
4382
  * the range "00" to "99", considers the year a 2-digit form and makes
@@ -4617,6 +4650,10 @@ date_s__jisx0301(VALUE klass, VALUE str)
4617
4650
  * some typical JIS X 0301 formats.
4618
4651
  *
4619
4652
  * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
4653
+ *
4654
+ * For no-era year, legacy format, Heisei is assumed.
4655
+ *
4656
+ * Date.jisx0301('13.02.03') #=> #<Date: 2001-02-03 ...>
4620
4657
  */
4621
4658
  static VALUE
4622
4659
  date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
@@ -4691,14 +4728,14 @@ dup_obj_as_complex(VALUE self)
4691
4728
  }
4692
4729
 
4693
4730
  #define val2off(vof,iof) \
4694
- {\
4731
+ do {\
4695
4732
  if (!offset_to_sec(vof, &iof)) {\
4696
4733
  iof = 0;\
4697
4734
  rb_warning("invalid offset is ignored");\
4698
4735
  }\
4699
- }
4736
+ } while (0)
4700
4737
 
4701
- #ifndef NDEBUG
4738
+ #if 0
4702
4739
  static VALUE
4703
4740
  d_lite_initialize(int argc, VALUE *argv, VALUE self)
4704
4741
  {
@@ -4707,7 +4744,6 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4707
4744
  double sg;
4708
4745
 
4709
4746
  rb_check_frozen(self);
4710
- rb_check_trusted(self);
4711
4747
 
4712
4748
  rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
4713
4749
 
@@ -4726,11 +4762,11 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4726
4762
  sf = vsf;
4727
4763
  if (f_lt_p(sf, INT2FIX(0)) ||
4728
4764
  f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
4729
- rb_raise(rb_eArgError, "invalid second fraction");
4765
+ rb_raise(eDateError, "invalid second fraction");
4730
4766
  case 2:
4731
4767
  df = NUM2INT(vdf);
4732
4768
  if (df < 0 || df >= DAY_IN_SECONDS)
4733
- rb_raise(rb_eArgError, "invalid day fraction");
4769
+ rb_raise(eDateError, "invalid day fraction");
4734
4770
  case 1:
4735
4771
  jd = vjd;
4736
4772
  }
@@ -4751,7 +4787,7 @@ d_lite_initialize(int argc, VALUE *argv, VALUE self)
4751
4787
  "cannot load complex into simple");
4752
4788
 
4753
4789
  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);
4790
+ 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF);
4755
4791
  }
4756
4792
  }
4757
4793
  return self;
@@ -4763,15 +4799,34 @@ static VALUE
4763
4799
  d_lite_initialize_copy(VALUE copy, VALUE date)
4764
4800
  {
4765
4801
  rb_check_frozen(copy);
4766
- rb_check_trusted(copy);
4767
4802
 
4768
4803
  if (copy == date)
4769
4804
  return copy;
4770
4805
  {
4771
4806
  get_d2(copy, date);
4772
4807
  if (simple_dat_p(bdat)) {
4773
- adat->s = bdat->s;
4774
- adat->s.flags &= ~COMPLEX_DAT;
4808
+ if (simple_dat_p(adat)) {
4809
+ adat->s = bdat->s;
4810
+ }
4811
+ else {
4812
+ adat->c.flags = bdat->s.flags | COMPLEX_DAT;
4813
+ adat->c.nth = bdat->s.nth;
4814
+ adat->c.jd = bdat->s.jd;
4815
+ adat->c.df = 0;
4816
+ adat->c.sf = INT2FIX(0);
4817
+ adat->c.of = 0;
4818
+ adat->c.sg = bdat->s.sg;
4819
+ adat->c.year = bdat->s.year;
4820
+ #ifndef USE_PACK
4821
+ adat->c.mon = bdat->s.mon;
4822
+ adat->c.mday = bdat->s.mday;
4823
+ adat->c.hour = bdat->s.hour;
4824
+ adat->c.min = bdat->s.min;
4825
+ adat->c.sec = bdat->s.sec;
4826
+ #else
4827
+ adat->c.pc = bdat->s.pc;
4828
+ #endif
4829
+ }
4775
4830
  }
4776
4831
  else {
4777
4832
  if (!complex_dat_p(adat))
@@ -4779,7 +4834,6 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
4779
4834
  "cannot load complex into simple");
4780
4835
 
4781
4836
  adat->c = bdat->c;
4782
- adat->c.flags |= COMPLEX_DAT;
4783
4837
  }
4784
4838
  }
4785
4839
  return copy;
@@ -5513,8 +5567,10 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self)
5513
5567
  static VALUE
5514
5568
  d_lite_plus(VALUE self, VALUE other)
5515
5569
  {
5570
+ int try_rational = 1;
5516
5571
  get_d1(self);
5517
5572
 
5573
+ again:
5518
5574
  switch (TYPE(other)) {
5519
5575
  case T_FIXNUM:
5520
5576
  {
@@ -5724,18 +5780,21 @@ d_lite_plus(VALUE self, VALUE other)
5724
5780
  default:
5725
5781
  expect_numeric(other);
5726
5782
  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
5783
+ if (!k_rational_p(other)) {
5784
+ if (!try_rational) Check_Type(other, T_RATIONAL);
5785
+ try_rational = 0;
5786
+ goto again;
5787
+ }
5731
5788
  /* fall through */
5732
5789
  case T_RATIONAL:
5733
5790
  {
5734
5791
  VALUE nth, sf, t;
5735
5792
  int jd, df, s;
5736
5793
 
5737
- if (wholenum_p(other))
5738
- return d_lite_plus(self, rb_rational_num(other));
5794
+ if (wholenum_p(other)) {
5795
+ other = rb_rational_num(other);
5796
+ goto again;
5797
+ }
5739
5798
 
5740
5799
  if (f_positive_p(other))
5741
5800
  s = +1;
@@ -6017,7 +6076,7 @@ d_lite_rshift(VALUE self, VALUE other)
6017
6076
  &rm, &rd, &rjd, &ns))
6018
6077
  break;
6019
6078
  if (--d < 1)
6020
- rb_raise(rb_eArgError, "invalid date");
6079
+ rb_raise(eDateError, "invalid date");
6021
6080
  }
6022
6081
  encode_jd(nth, rjd, &rjd2);
6023
6082
  return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
@@ -6154,6 +6213,7 @@ static VALUE
6154
6213
  d_lite_step(int argc, VALUE *argv, VALUE self)
6155
6214
  {
6156
6215
  VALUE limit, step, date;
6216
+ int c;
6157
6217
 
6158
6218
  rb_scan_args(argc, argv, "11", &limit, &step);
6159
6219
 
@@ -6168,25 +6228,22 @@ d_lite_step(int argc, VALUE *argv, VALUE self)
6168
6228
  RETURN_ENUMERATOR(self, argc, argv);
6169
6229
 
6170
6230
  date = self;
6171
- switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
6172
- case -1:
6231
+ c = f_cmp(step, INT2FIX(0));
6232
+ if (c < 0) {
6173
6233
  while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
6174
6234
  rb_yield(date);
6175
6235
  date = d_lite_plus(date, step);
6176
6236
  }
6177
- break;
6178
- case 0:
6237
+ }
6238
+ else if (c == 0) {
6179
6239
  while (1)
6180
6240
  rb_yield(date);
6181
- break;
6182
- case 1:
6241
+ }
6242
+ else /* if (c > 0) */ {
6183
6243
  while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
6184
6244
  rb_yield(date);
6185
6245
  date = d_lite_plus(date, step);
6186
6246
  }
6187
- break;
6188
- default:
6189
- abort();
6190
6247
  }
6191
6248
  return self;
6192
6249
  }
@@ -6241,10 +6298,10 @@ cmp_gen(VALUE self, VALUE other)
6241
6298
  get_d1(self);
6242
6299
 
6243
6300
  if (k_numeric_p(other))
6244
- return f_cmp(m_ajd(dat), other);
6301
+ return INT2FIX(f_cmp(m_ajd(dat), other));
6245
6302
  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("<=>"));
6303
+ return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other)));
6304
+ return rb_num_coerce_cmp(self, other, id_cmp);
6248
6305
  }
6249
6306
 
6250
6307
  static VALUE
@@ -6373,7 +6430,7 @@ equal_gen(VALUE self, VALUE other)
6373
6430
  return f_eqeq_p(m_real_local_jd(dat), other);
6374
6431
  else if (k_date_p(other))
6375
6432
  return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
6376
- return rb_num_coerce_cmp(self, other, rb_intern("=="));
6433
+ return rb_num_coerce_cmp(self, other, id_eqeq_p);
6377
6434
  }
6378
6435
 
6379
6436
  /*
@@ -6444,7 +6501,7 @@ d_lite_hash(VALUE self)
6444
6501
  h[2] = m_df(dat);
6445
6502
  h[3] = m_sf(dat);
6446
6503
  v = rb_memhash(h, sizeof(h));
6447
- return LONG2FIX(v);
6504
+ return ST2FIX(v);
6448
6505
  }
6449
6506
 
6450
6507
  #include "date_tmx.h"
@@ -6471,7 +6528,7 @@ d_lite_to_s(VALUE self)
6471
6528
  static VALUE
6472
6529
  mk_inspect_raw(union DateData *x, VALUE klass)
6473
6530
  {
6474
- char flags[5];
6531
+ char flags[6];
6475
6532
 
6476
6533
  flags[0] = (x->flags & COMPLEX_DAT) ? 'C' : 'S';
6477
6534
  flags[1] = (x->flags & HAVE_JD) ? 'j' : '-';
@@ -6543,9 +6600,9 @@ mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
6543
6600
  * Returns the value as a string for inspection.
6544
6601
  *
6545
6602
  * Date.new(2001,2,3).inspect
6546
- * #=> "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>"
6603
+ * #=> "#<Date: 2001-02-03>"
6547
6604
  * DateTime.new(2001,2,3,4,5,6,'-7').inspect
6548
- * #=> "#<DateTime: 2001-02-03T04:05:06-07:00 ((2451944j,39906s,0n),-25200s,2299161j)>"
6605
+ * #=> "#<DateTime: 2001-02-03T04:05:06-07:00>"
6549
6606
  */
6550
6607
  static VALUE
6551
6608
  d_lite_inspect(VALUE self)
@@ -6637,7 +6694,9 @@ tmx_m_of(union DateData *x)
6637
6694
  static char *
6638
6695
  tmx_m_zone(union DateData *x)
6639
6696
  {
6640
- return RSTRING_PTR(m_zone(x));
6697
+ VALUE zone = m_zone(x);
6698
+ /* TODO: fix potential dangling pointer */
6699
+ return RSTRING_PTR(zone);
6641
6700
  }
6642
6701
 
6643
6702
  static const struct tmx_funcs tmx_funcs = {
@@ -6712,7 +6771,6 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6712
6771
  if (p > fmt) rb_str_cat(str, fmt, p - fmt);
6713
6772
  }
6714
6773
  rb_enc_copy(str, vfmt);
6715
- OBJ_INFECT(str, vfmt);
6716
6774
  return str;
6717
6775
  }
6718
6776
  else
@@ -6721,7 +6779,6 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6721
6779
  str = rb_str_new(buf, len);
6722
6780
  if (buf != buffer) xfree(buf);
6723
6781
  rb_enc_copy(str, vfmt);
6724
- OBJ_INFECT(str, vfmt);
6725
6782
  return str;
6726
6783
  }
6727
6784
 
@@ -6787,7 +6844,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6787
6844
  *
6788
6845
  * %M - Minute of the hour (00..59)
6789
6846
  *
6790
- * %S - Second of the minute (00..59)
6847
+ * %S - Second of the minute (00..60)
6791
6848
  *
6792
6849
  * %L - Millisecond of the second (000..999)
6793
6850
  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -6802,7 +6859,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
6802
6859
  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
6803
6860
  * %:::z - hour, minute and second offset from UTC
6804
6861
  * (e.g. +09, +09:30, +09:30:30)
6805
- * %Z - Time zone abbreviation name or something similar information.
6862
+ * %Z - Equivalent to %:z (e.g. +09:00)
6806
6863
  *
6807
6864
  * Weekday:
6808
6865
  * %A - The full weekday name (``Sunday'')
@@ -7020,10 +7077,14 @@ jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
7020
7077
  c = 'S';
7021
7078
  s = 1925;
7022
7079
  }
7023
- else {
7080
+ else if (d < 2458605) {
7024
7081
  c = 'H';
7025
7082
  s = 1988;
7026
7083
  }
7084
+ else {
7085
+ c = 'R';
7086
+ s = 2018;
7087
+ }
7027
7088
  snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s);
7028
7089
  return fmt;
7029
7090
  }
@@ -7101,10 +7162,13 @@ d_lite_marshal_dump(VALUE self)
7101
7162
  static VALUE
7102
7163
  d_lite_marshal_load(VALUE self, VALUE a)
7103
7164
  {
7165
+ VALUE nth, sf;
7166
+ int jd, df, of;
7167
+ double sg;
7168
+
7104
7169
  get_d1(self);
7105
7170
 
7106
7171
  rb_check_frozen(self);
7107
- rb_check_trusted(self);
7108
7172
 
7109
7173
  if (!RB_TYPE_P(a, T_ARRAY))
7110
7174
  rb_raise(rb_eTypeError, "expected an array");
@@ -7113,63 +7177,33 @@ d_lite_marshal_load(VALUE self, VALUE a)
7113
7177
  case 2: /* 1.6.x */
7114
7178
  case 3: /* 1.8.x, 1.9.2 */
7115
7179
  {
7116
- VALUE ajd, of, sg, nth, sf;
7117
- int jd, df, rof;
7118
- double rsg;
7119
-
7180
+ VALUE ajd, vof, vsg;
7120
7181
 
7121
7182
  if (RARRAY_LEN(a) == 2) {
7122
7183
  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);
7184
+ vof = INT2FIX(0);
7185
+ vsg = RARRAY_AREF(a, 1);
7186
+ if (!k_numeric_p(vsg))
7187
+ vsg = DBL2NUM(RTEST(vsg) ? GREGORIAN : JULIAN);
7127
7188
  }
7128
7189
  else {
7129
7190
  ajd = RARRAY_AREF(a, 0);
7130
- of = RARRAY_AREF(a, 1);
7131
- sg = RARRAY_AREF(a, 2);
7191
+ vof = RARRAY_AREF(a, 1);
7192
+ vsg = RARRAY_AREF(a, 2);
7132
7193
  }
7133
7194
 
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
- }
7195
+ old_to_new(ajd, vof, vsg,
7196
+ &nth, &jd, &df, &sf, &of, &sg);
7148
7197
  }
7149
7198
  break;
7150
7199
  case 6:
7151
7200
  {
7152
- VALUE nth, sf;
7153
- int jd, df, of;
7154
- double sg;
7155
-
7156
7201
  nth = RARRAY_AREF(a, 0);
7157
7202
  jd = NUM2INT(RARRAY_AREF(a, 1));
7158
7203
  df = NUM2INT(RARRAY_AREF(a, 2));
7159
7204
  sf = RARRAY_AREF(a, 3);
7160
7205
  of = NUM2INT(RARRAY_AREF(a, 4));
7161
7206
  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
7207
  }
7174
7208
  break;
7175
7209
  default:
@@ -7177,6 +7211,21 @@ d_lite_marshal_load(VALUE self, VALUE a)
7177
7211
  break;
7178
7212
  }
7179
7213
 
7214
+ if (simple_dat_p(dat)) {
7215
+ if (df || !f_zero_p(sf) || of) {
7216
+ /* loading a fractional date; promote to complex */
7217
+ dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
7218
+ RTYPEDDATA(self)->data = dat;
7219
+ goto complex_data;
7220
+ }
7221
+ set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7222
+ } else {
7223
+ complex_data:
7224
+ set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
7225
+ 0, 0, 0, 0, 0, 0,
7226
+ HAVE_JD | HAVE_DF);
7227
+ }
7228
+
7180
7229
  if (FL_TEST(a, FL_EXIVAR)) {
7181
7230
  rb_copy_generic_ivar(self, a);
7182
7231
  FL_SET(self, FL_EXIVAR);
@@ -7232,12 +7281,16 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7232
7281
  case 5:
7233
7282
  val2off(vof, rof);
7234
7283
  case 4:
7284
+ check_numeric(vs, "second");
7235
7285
  num2int_with_frac(s, positive_inf);
7236
7286
  case 3:
7287
+ check_numeric(vmin, "minute");
7237
7288
  num2int_with_frac(min, 3);
7238
7289
  case 2:
7290
+ check_numeric(vh, "hour");
7239
7291
  num2int_with_frac(h, 2);
7240
7292
  case 1:
7293
+ check_numeric(vjd, "jd");
7241
7294
  num2num_with_frac(jd, 1);
7242
7295
  }
7243
7296
 
@@ -7246,7 +7299,7 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7246
7299
  int rh, rmin, rs, rjd, rjd2;
7247
7300
 
7248
7301
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7249
- rb_raise(rb_eArgError, "invalid date");
7302
+ rb_raise(eDateError, "invalid date");
7250
7303
  canon24oc();
7251
7304
 
7252
7305
  decode_jd(jd, &nth, &rjd);
@@ -7301,14 +7354,19 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7301
7354
  case 6:
7302
7355
  val2off(vof, rof);
7303
7356
  case 5:
7357
+ check_numeric(vs, "second");
7304
7358
  num2int_with_frac(s, positive_inf);
7305
7359
  case 4:
7360
+ check_numeric(vmin, "minute");
7306
7361
  num2int_with_frac(min, 4);
7307
7362
  case 3:
7363
+ check_numeric(vh, "hour");
7308
7364
  num2int_with_frac(h, 3);
7309
7365
  case 2:
7366
+ check_numeric(vd, "yday");
7310
7367
  num2int_with_frac(d, 2);
7311
7368
  case 1:
7369
+ check_numeric(vy, "year");
7312
7370
  y = vy;
7313
7371
  }
7314
7372
 
@@ -7320,9 +7378,9 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7320
7378
  &nth, &ry,
7321
7379
  &rd, &rjd,
7322
7380
  &ns))
7323
- rb_raise(rb_eArgError, "invalid date");
7381
+ rb_raise(eDateError, "invalid date");
7324
7382
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7325
- rb_raise(rb_eArgError, "invalid date");
7383
+ rb_raise(eDateError, "invalid date");
7326
7384
  canon24oc();
7327
7385
 
7328
7386
  rjd2 = jd_local_to_utc(rjd,
@@ -7356,10 +7414,21 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7356
7414
  */
7357
7415
  static VALUE
7358
7416
  datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7417
+ {
7418
+ return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
7419
+ }
7420
+
7421
+ static VALUE
7422
+ datetime_initialize(int argc, VALUE *argv, VALUE self)
7359
7423
  {
7360
7424
  VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7361
7425
  int m, d, h, min, s, rof;
7362
7426
  double sg;
7427
+ struct ComplexDateData *dat = rb_check_typeddata(self, &d_lite_type);
7428
+
7429
+ if (!complex_dat_p(dat)) {
7430
+ rb_raise(rb_eTypeError, "DateTime expected");
7431
+ }
7363
7432
 
7364
7433
  rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
7365
7434
 
@@ -7378,16 +7447,22 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7378
7447
  case 7:
7379
7448
  val2off(vof, rof);
7380
7449
  case 6:
7450
+ check_numeric(vs, "second");
7381
7451
  num2int_with_frac(s, positive_inf);
7382
7452
  case 5:
7453
+ check_numeric(vmin, "minute");
7383
7454
  num2int_with_frac(min, 5);
7384
7455
  case 4:
7456
+ check_numeric(vh, "hour");
7385
7457
  num2int_with_frac(h, 4);
7386
7458
  case 3:
7459
+ check_numeric(vd, "day");
7387
7460
  num2int_with_frac(d, 3);
7388
7461
  case 2:
7462
+ check_numeric(vm, "month");
7389
7463
  m = NUM2INT(vm);
7390
7464
  case 1:
7465
+ check_numeric(vy, "year");
7391
7466
  y = vy;
7392
7467
  }
7393
7468
 
@@ -7398,18 +7473,18 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7398
7473
  if (!valid_gregorian_p(y, m, d,
7399
7474
  &nth, &ry,
7400
7475
  &rm, &rd))
7401
- rb_raise(rb_eArgError, "invalid date");
7476
+ rb_raise(eDateError, "invalid date");
7402
7477
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7403
- rb_raise(rb_eArgError, "invalid date");
7478
+ rb_raise(eDateError, "invalid date");
7404
7479
  canon24oc();
7405
7480
 
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);
7481
+ set_to_complex(self, dat,
7482
+ nth, 0,
7483
+ 0, INT2FIX(0),
7484
+ rof, sg,
7485
+ ry, rm, rd,
7486
+ rh, rmin, rs,
7487
+ HAVE_CIVIL | HAVE_TIME);
7413
7488
  }
7414
7489
  else {
7415
7490
  VALUE nth;
@@ -7419,23 +7494,24 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7419
7494
  &nth, &ry,
7420
7495
  &rm, &rd, &rjd,
7421
7496
  &ns))
7422
- rb_raise(rb_eArgError, "invalid date");
7497
+ rb_raise(eDateError, "invalid date");
7423
7498
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7424
- rb_raise(rb_eArgError, "invalid date");
7499
+ rb_raise(eDateError, "invalid date");
7425
7500
  canon24oc();
7426
7501
 
7427
7502
  rjd2 = jd_local_to_utc(rjd,
7428
7503
  time_to_df(rh, rmin, rs),
7429
7504
  rof);
7430
7505
 
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);
7506
+ set_to_complex(self, dat,
7507
+ nth, rjd2,
7508
+ 0, INT2FIX(0),
7509
+ rof, sg,
7510
+ ry, rm, rd,
7511
+ rh, rmin, rs,
7512
+ HAVE_JD | HAVE_CIVIL | HAVE_TIME);
7438
7513
  }
7514
+ ret = self;
7439
7515
  add_frac();
7440
7516
  return ret;
7441
7517
  }
@@ -7475,16 +7551,22 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7475
7551
  case 7:
7476
7552
  val2off(vof, rof);
7477
7553
  case 6:
7554
+ check_numeric(vs, "second");
7478
7555
  num2int_with_frac(s, positive_inf);
7479
7556
  case 5:
7557
+ check_numeric(vmin, "minute");
7480
7558
  num2int_with_frac(min, 5);
7481
7559
  case 4:
7560
+ check_numeric(vh, "hour");
7482
7561
  num2int_with_frac(h, 4);
7483
7562
  case 3:
7563
+ check_numeric(vd, "cwday");
7484
7564
  num2int_with_frac(d, 3);
7485
7565
  case 2:
7566
+ check_numeric(vw, "cweek");
7486
7567
  w = NUM2INT(vw);
7487
7568
  case 1:
7569
+ check_numeric(vy, "year");
7488
7570
  y = vy;
7489
7571
  }
7490
7572
 
@@ -7496,9 +7578,9 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7496
7578
  &nth, &ry,
7497
7579
  &rw, &rd, &rjd,
7498
7580
  &ns))
7499
- rb_raise(rb_eArgError, "invalid date");
7581
+ rb_raise(eDateError, "invalid date");
7500
7582
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7501
- rb_raise(rb_eArgError, "invalid date");
7583
+ rb_raise(eDateError, "invalid date");
7502
7584
  canon24oc();
7503
7585
 
7504
7586
  rjd2 = jd_local_to_utc(rjd,
@@ -7567,9 +7649,9 @@ datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
7567
7649
  &nth, &ry,
7568
7650
  &rw, &rd, &rjd,
7569
7651
  &ns))
7570
- rb_raise(rb_eArgError, "invalid date");
7652
+ rb_raise(eDateError, "invalid date");
7571
7653
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7572
- rb_raise(rb_eArgError, "invalid date");
7654
+ rb_raise(eDateError, "invalid date");
7573
7655
  canon24oc();
7574
7656
 
7575
7657
  rjd2 = jd_local_to_utc(rjd,
@@ -7636,9 +7718,9 @@ datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
7636
7718
  &nth, &ry,
7637
7719
  &rm, &rn, &rk, &rjd,
7638
7720
  &ns))
7639
- rb_raise(rb_eArgError, "invalid date");
7721
+ rb_raise(eDateError, "invalid date");
7640
7722
  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7641
- rb_raise(rb_eArgError, "invalid date");
7723
+ rb_raise(eDateError, "invalid date");
7642
7724
  canon24oc();
7643
7725
 
7644
7726
  rjd2 = jd_local_to_utc(rjd,
@@ -7710,8 +7792,8 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
7710
7792
  s = 59;
7711
7793
  #ifdef HAVE_STRUCT_TM_TM_GMTOFF
7712
7794
  of = tm.tm_gmtoff;
7713
- #elif defined(HAVE_VAR_TIMEZONE)
7714
- #ifdef HAVE_VAR_ALTZONE
7795
+ #elif defined(HAVE_TIMEZONE)
7796
+ #ifdef HAVE_ALTZONE
7715
7797
  of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
7716
7798
  #else
7717
7799
  of = (long)-timezone;
@@ -7781,7 +7863,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7781
7863
  }
7782
7864
 
7783
7865
  if (NIL_P(hash))
7784
- rb_raise(rb_eArgError, "invalid date");
7866
+ rb_raise(eDateError, "invalid date");
7785
7867
 
7786
7868
  if (NIL_P(ref_hash("jd")) &&
7787
7869
  NIL_P(ref_hash("yday")) &&
@@ -7808,7 +7890,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7808
7890
  }
7809
7891
 
7810
7892
  if (NIL_P(jd))
7811
- rb_raise(rb_eArgError, "invalid date");
7893
+ rb_raise(eDateError, "invalid date");
7812
7894
 
7813
7895
  {
7814
7896
  int rh, rmin, rs;
@@ -7817,7 +7899,7 @@ dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7817
7899
  NUM2INT(ref_hash("min")),
7818
7900
  NUM2INT(ref_hash("sec")),
7819
7901
  &rh, &rmin, &rs))
7820
- rb_raise(rb_eArgError, "invalid date");
7902
+ rb_raise(eDateError, "invalid date");
7821
7903
 
7822
7904
  df = time_to_df(rh, rmin, rs);
7823
7905
  }
@@ -7930,7 +8012,12 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7930
8012
  * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime
7931
8013
  *
7932
8014
  * Parses the given representation of date and time, and creates a
7933
- * DateTime object. This method does not function as a validator.
8015
+ * DateTime object.
8016
+ *
8017
+ * This method **does not** function as a validator. If the input
8018
+ * string does not match valid formats strictly, you may get a cryptic
8019
+ * result. Should consider to use `DateTime.strptime` instead of this
8020
+ * method as possible.
7934
8021
  *
7935
8022
  * If the optional second argument is true and the detected year is in
7936
8023
  * the range "00" to "99", makes it full.
@@ -8132,6 +8219,11 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8132
8219
  *
8133
8220
  * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
8134
8221
  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8222
+ *
8223
+ * For no-era year, legacy format, Heisei is assumed.
8224
+ *
8225
+ * DateTime.jisx0301('13.02.03T04:05:06+07:00')
8226
+ * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8135
8227
  */
8136
8228
  static VALUE
8137
8229
  datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
@@ -8232,7 +8324,7 @@ dt_lite_to_s(VALUE self)
8232
8324
  *
8233
8325
  * %M - Minute of the hour (00..59)
8234
8326
  *
8235
- * %S - Second of the minute (00..59)
8327
+ * %S - Second of the minute (00..60)
8236
8328
  *
8237
8329
  * %L - Millisecond of the second (000..999)
8238
8330
  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
@@ -8247,7 +8339,7 @@ dt_lite_to_s(VALUE self)
8247
8339
  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
8248
8340
  * %:::z - hour, minute and second offset from UTC
8249
8341
  * (e.g. +09, +09:30, +09:30:30)
8250
- * %Z - Time zone abbreviation name or something similar information.
8342
+ * %Z - Equivalent to %:z (e.g. +09:00)
8251
8343
  *
8252
8344
  * Weekday:
8253
8345
  * %A - The full weekday name (``Sunday'')
@@ -8526,17 +8618,24 @@ time_to_datetime(VALUE self)
8526
8618
  * call-seq:
8527
8619
  * d.to_time -> time
8528
8620
  *
8529
- * Returns a Time object which denotes self.
8621
+ * Returns a Time object which denotes self. If self is a julian date,
8622
+ * convert it to a gregorian date before converting it to Time.
8530
8623
  */
8531
8624
  static VALUE
8532
8625
  date_to_time(VALUE self)
8533
8626
  {
8534
- get_d1(self);
8627
+ get_d1a(self);
8628
+
8629
+ if (m_julian_p(adat)) {
8630
+ VALUE tmp = d_lite_gregorian(self);
8631
+ get_d1b(tmp);
8632
+ adat = bdat;
8633
+ }
8535
8634
 
8536
8635
  return f_local3(rb_cTime,
8537
- m_real_year(dat),
8538
- INT2FIX(m_mon(dat)),
8539
- INT2FIX(m_mday(dat)));
8636
+ m_real_year(adat),
8637
+ INT2FIX(m_mon(adat)),
8638
+ INT2FIX(m_mday(adat)));
8540
8639
  }
8541
8640
 
8542
8641
  /*
@@ -8645,7 +8744,7 @@ datetime_to_date(VALUE self)
8645
8744
  VALUE new = d_lite_s_alloc_simple(cDate);
8646
8745
  {
8647
8746
  get_d1b(new);
8648
- copy_complex_to_simple(new, &bdat->s, &adat->c)
8747
+ copy_complex_to_simple(new, &bdat->s, &adat->c);
8649
8748
  bdat->s.jd = m_local_jd(adat);
8650
8749
  bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
8651
8750
  return new;
@@ -9010,18 +9109,22 @@ mk_ary_of_str(long len, const char *a[])
9010
9109
  return o;
9011
9110
  }
9012
9111
 
9112
+ static VALUE
9113
+ d_lite_zero(VALUE x)
9114
+ {
9115
+ return INT2FIX(0);
9116
+ }
9117
+
9013
9118
  void
9014
9119
  Init_date_core(void)
9015
9120
  {
9016
- #undef rb_intern
9017
- #define rb_intern(str) rb_intern_const(str)
9018
-
9019
- assert(fprintf(stderr, "assert() is now active\n"));
9020
-
9021
- id_cmp = rb_intern("<=>");
9022
- id_le_p = rb_intern("<=");
9023
- id_ge_p = rb_intern(">=");
9024
- id_eqeq_p = rb_intern("==");
9121
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
9122
+ RB_EXT_RACTOR_SAFE(true);
9123
+ #endif
9124
+ id_cmp = rb_intern_const("<=>");
9125
+ id_le_p = rb_intern_const("<=");
9126
+ id_ge_p = rb_intern_const(">=");
9127
+ id_eqeq_p = rb_intern_const("==");
9025
9128
 
9026
9129
  half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
9027
9130
 
@@ -9189,6 +9292,7 @@ Init_date_core(void)
9189
9292
  *
9190
9293
  */
9191
9294
  cDate = rb_define_class("Date", rb_cObject);
9295
+ eDateError = rb_define_class_under(cDate, "Error", rb_eArgError);
9192
9296
 
9193
9297
  rb_include_module(cDate, rb_mComparable);
9194
9298
 
@@ -9233,23 +9337,22 @@ Init_date_core(void)
9233
9337
  */
9234
9338
  rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
9235
9339
 
9236
- rb_define_alloc_func(cDate, d_lite_s_alloc);
9340
+ rb_define_alloc_func(cDate, d_lite_s_alloc_simple);
9237
9341
 
9238
9342
  #ifndef NDEBUG
9239
- #define de_define_private_method rb_define_private_method
9240
- de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9343
+ rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9241
9344
  date_s__valid_jd_p, -1);
9242
- de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9345
+ rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9243
9346
  date_s__valid_ordinal_p, -1);
9244
- de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9347
+ rb_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9245
9348
  date_s__valid_civil_p, -1);
9246
- de_define_private_method(CLASS_OF(cDate), "_valid_date?",
9349
+ rb_define_private_method(CLASS_OF(cDate), "_valid_date?",
9247
9350
  date_s__valid_civil_p, -1);
9248
- de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9351
+ rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9249
9352
  date_s__valid_commercial_p, -1);
9250
- de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9353
+ rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9251
9354
  date_s__valid_weeknum_p, -1);
9252
- de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9355
+ rb_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9253
9356
  date_s__valid_nth_kday_p, -1);
9254
9357
  #endif
9255
9358
 
@@ -9262,11 +9365,11 @@ Init_date_core(void)
9262
9365
  date_s_valid_commercial_p, -1);
9263
9366
 
9264
9367
  #ifndef NDEBUG
9265
- de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9368
+ rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9266
9369
  date_s_valid_weeknum_p, -1);
9267
- de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9370
+ rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9268
9371
  date_s_valid_nth_kday_p, -1);
9269
- de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9372
+ rb_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9270
9373
  date_s_zone_to_diff, 1);
9271
9374
  #endif
9272
9375
 
@@ -9277,21 +9380,18 @@ Init_date_core(void)
9277
9380
  date_s_gregorian_leap_p, 1);
9278
9381
 
9279
9382
  #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");
9383
+ rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
9384
+ rb_define_alias(rb_singleton_class(cDate), "new_l!", "new");
9284
9385
  #endif
9285
9386
 
9286
9387
  rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
9287
9388
  rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
9288
9389
  rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
9289
- rb_define_singleton_method(cDate, "new", date_s_civil, -1);
9290
9390
  rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
9291
9391
 
9292
9392
  #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);
9393
+ rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
9394
+ rb_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
9295
9395
  #endif
9296
9396
 
9297
9397
  rb_define_singleton_method(cDate, "today", date_s_today, -1);
@@ -9314,14 +9414,11 @@ Init_date_core(void)
9314
9414
  rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
9315
9415
  rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
9316
9416
 
9317
- #ifndef NDEBUG
9318
- #define de_define_method rb_define_method
9319
- de_define_method(cDate, "initialize", d_lite_initialize, -1);
9320
- #endif
9417
+ rb_define_method(cDate, "initialize", date_initialize, -1);
9321
9418
  rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
9322
9419
 
9323
9420
  #ifndef NDEBUG
9324
- de_define_method(cDate, "fill", d_lite_fill, 0);
9421
+ rb_define_method(cDate, "fill", d_lite_fill, 0);
9325
9422
  #endif
9326
9423
 
9327
9424
  rb_define_method(cDate, "ajd", d_lite_ajd, 0);
@@ -9343,8 +9440,8 @@ Init_date_core(void)
9343
9440
  rb_define_method(cDate, "cwday", d_lite_cwday, 0);
9344
9441
 
9345
9442
  #ifndef NDEBUG
9346
- de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9347
- de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9443
+ rb_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9444
+ rb_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9348
9445
  #endif
9349
9446
 
9350
9447
  rb_define_method(cDate, "wday", d_lite_wday, 0);
@@ -9358,18 +9455,14 @@ Init_date_core(void)
9358
9455
  rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
9359
9456
 
9360
9457
  #ifndef NDEBUG
9361
- de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9458
+ rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9362
9459
  #endif
9363
9460
 
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);
9461
+ rb_define_private_method(cDate, "hour", d_lite_zero, 0);
9462
+ rb_define_private_method(cDate, "min", d_lite_zero, 0);
9463
+ rb_define_private_method(cDate, "minute", d_lite_zero, 0);
9464
+ rb_define_private_method(cDate, "sec", d_lite_zero, 0);
9465
+ rb_define_private_method(cDate, "second", d_lite_zero, 0);
9373
9466
 
9374
9467
  rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
9375
9468
  rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
@@ -9382,8 +9475,6 @@ Init_date_core(void)
9382
9475
  rb_define_method(cDate, "julian", d_lite_julian, 0);
9383
9476
  rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
9384
9477
 
9385
- rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1);
9386
-
9387
9478
  rb_define_method(cDate, "+", d_lite_plus, 1);
9388
9479
  rb_define_method(cDate, "-", d_lite_minus, 1);
9389
9480
 
@@ -9411,7 +9502,7 @@ Init_date_core(void)
9411
9502
 
9412
9503
  rb_define_method(cDate, "to_s", d_lite_to_s, 0);
9413
9504
  #ifndef NDEBUG
9414
- de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9505
+ rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9415
9506
  #endif
9416
9507
  rb_define_method(cDate, "inspect", d_lite_inspect, 0);
9417
9508
 
@@ -9428,7 +9519,7 @@ Init_date_core(void)
9428
9519
  rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
9429
9520
 
9430
9521
  #ifndef NDEBUG
9431
- de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9522
+ rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9432
9523
  #endif
9433
9524
  rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
9434
9525
  rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
@@ -9440,6 +9531,8 @@ Init_date_core(void)
9440
9531
  * A subclass of Date that easily handles date, hour, minute, second,
9441
9532
  * and offset.
9442
9533
  *
9534
+ * DateTime class is considered deprecated. Use Time class.
9535
+ *
9443
9536
  * DateTime does not consider any leap seconds, does not track
9444
9537
  * any summer time rules.
9445
9538
  *
@@ -9500,18 +9593,18 @@ Init_date_core(void)
9500
9593
  * === When should you use DateTime and when should you use Time?
9501
9594
  *
9502
9595
  * It's a common misconception that
9503
- * {William Shakespeare}[http://en.wikipedia.org/wiki/William_Shakespeare]
9596
+ * {William Shakespeare}[https://en.wikipedia.org/wiki/William_Shakespeare]
9504
9597
  * and
9505
- * {Miguel de Cervantes}[http://en.wikipedia.org/wiki/Miguel_de_Cervantes]
9598
+ * {Miguel de Cervantes}[https://en.wikipedia.org/wiki/Miguel_de_Cervantes]
9506
9599
  * died on the same day in history -
9507
9600
  * so much so that UNESCO named April 23 as
9508
- * {World Book Day because of this fact}[http://en.wikipedia.org/wiki/World_Book_Day].
9601
+ * {World Book Day because of this fact}[https://en.wikipedia.org/wiki/World_Book_Day].
9509
9602
  * However, because England hadn't yet adopted the
9510
- * {Gregorian Calendar Reform}[http://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
9511
- * (and wouldn't until {1752}[http://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
9603
+ * {Gregorian Calendar Reform}[https://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
9604
+ * (and wouldn't until {1752}[https://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
9512
9605
  * their deaths are actually 10 days apart.
9513
9606
  * Since Ruby's Time class implements a
9514
- * {proleptic Gregorian calendar}[http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
9607
+ * {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
9515
9608
  * and has no concept of calendar reform there's no way
9516
9609
  * to express this with Time objects. This is where DateTime steps in:
9517
9610
  *
@@ -9555,7 +9648,7 @@ Init_date_core(void)
9555
9648
  * #=> Fri, 04 May 1753 00:00:00 +0000
9556
9649
  *
9557
9650
  * As you can see, if we're accurately tracking the number of
9558
- * {solar years}[http://en.wikipedia.org/wiki/Tropical_year]
9651
+ * {solar years}[https://en.wikipedia.org/wiki/Tropical_year]
9559
9652
  * since Shakespeare's birthday then the correct anniversary date
9560
9653
  * would be the 4th May and not the 23rd April.
9561
9654
  *
@@ -9567,14 +9660,15 @@ Init_date_core(void)
9567
9660
  * making the same mistakes as UNESCO. If you also have to deal
9568
9661
  * with timezones then best of luck - just bear in mind that
9569
9662
  * you'll probably be dealing with
9570
- * {local solar times}[http://en.wikipedia.org/wiki/Solar_time],
9663
+ * {local solar times}[https://en.wikipedia.org/wiki/Solar_time],
9571
9664
  * since it wasn't until the 19th century that the introduction
9572
9665
  * of the railways necessitated the need for
9573
- * {Standard Time}[http://en.wikipedia.org/wiki/Standard_time#Great_Britain]
9666
+ * {Standard Time}[https://en.wikipedia.org/wiki/Standard_time#Great_Britain]
9574
9667
  * and eventually timezones.
9575
9668
  */
9576
9669
 
9577
9670
  cDateTime = rb_define_class("DateTime", cDate);
9671
+ rb_define_alloc_func(cDateTime, d_lite_s_alloc_complex);
9578
9672
 
9579
9673
  rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
9580
9674
  rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
@@ -9584,9 +9678,9 @@ Init_date_core(void)
9584
9678
  datetime_s_commercial, -1);
9585
9679
 
9586
9680
  #ifndef NDEBUG
9587
- de_define_singleton_method(cDateTime, "weeknum",
9681
+ rb_define_singleton_method(cDateTime, "weeknum",
9588
9682
  datetime_s_weeknum, -1);
9589
- de_define_singleton_method(cDateTime, "nth_kday",
9683
+ rb_define_singleton_method(cDateTime, "nth_kday",
9590
9684
  datetime_s_nth_kday, -1);
9591
9685
  #endif
9592
9686
 
@@ -9614,19 +9708,16 @@ Init_date_core(void)
9614
9708
  rb_define_singleton_method(cDateTime, "jisx0301",
9615
9709
  datetime_s_jisx0301, -1);
9616
9710
 
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");
9711
+ rb_define_method(cDateTime, "hour", d_lite_hour, 0);
9712
+ rb_define_method(cDateTime, "min", d_lite_min, 0);
9713
+ rb_define_method(cDateTime, "minute", d_lite_min, 0);
9714
+ rb_define_method(cDateTime, "sec", d_lite_sec, 0);
9715
+ rb_define_method(cDateTime, "second", d_lite_sec, 0);
9716
+ rb_define_method(cDateTime, "sec_fraction", d_lite_sec_fraction, 0);
9717
+ rb_define_method(cDateTime, "second_fraction", d_lite_sec_fraction, 0);
9718
+ rb_define_method(cDateTime, "offset", d_lite_offset, 0);
9719
+ rb_define_method(cDateTime, "zone", d_lite_zone, 0);
9720
+ rb_define_method(cDateTime, "new_offset", d_lite_new_offset, -1);
9630
9721
 
9631
9722
  rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
9632
9723
 
@@ -9654,15 +9745,15 @@ Init_date_core(void)
9654
9745
  #ifndef NDEBUG
9655
9746
  /* tests */
9656
9747
 
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",
9748
+ rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
9749
+ rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
9750
+ rb_define_singleton_method(cDate, "test_commercial",
9660
9751
  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",
9752
+ rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
9753
+ rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
9754
+ rb_define_singleton_method(cDate, "test_unit_conv",
9664
9755
  date_s_test_unit_conv, 0);
9665
- de_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9756
+ rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9666
9757
  #endif
9667
9758
  }
9668
9759