Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
date_core.c
Go to the documentation of this file.
1 /*
2  date_core.c: Coded by Tadayoshi Funaba 2010-2014
3 */
4 
5 #include "ruby.h"
6 #include "ruby/encoding.h"
7 #include "ruby/util.h"
8 #include <math.h>
9 #include <time.h>
10 #if defined(HAVE_SYS_TIME_H)
11 #include <sys/time.h>
12 #endif
13 
14 #define NDEBUG
15 #include <assert.h>
16 
17 #ifdef RUBY_EXTCONF_H
18 #include RUBY_EXTCONF_H
19 #endif
20 
21 #define USE_PACK
22 
23 static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
24 static VALUE cDate, cDateTime;
25 static VALUE eDateError;
26 static VALUE half_days_in_day, day_in_nanoseconds;
27 static double positive_inf, negative_inf;
28 
29 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
30 
31 #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
32 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
33 #define f_add(x,y) rb_funcall(x, '+', 1, y)
34 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
35 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
36 #define f_div(x,y) rb_funcall(x, '/', 1, y)
37 #define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y)
38 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
39 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
40 #define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y)
41 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
42 #define f_floor(x) rb_funcall(x, rb_intern("floor"), 0)
43 #define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0)
44 #define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0)
45 #define f_round(x) rb_funcall(x, rb_intern("round"), 0)
46 
47 #define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0)
48 #define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0)
49 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
50 #define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0)
51 
52 #define f_add3(x,y,z) f_add(f_add(x, y), z)
53 #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
54 
55 static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
56 static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
57 
58 #define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse
59 inline static void
60 check_numeric(VALUE obj, const char* field) {
62  rb_raise(rb_eTypeError, "invalid %s (not numeric)", field);
63  }
64 }
65 
66 inline static int
67 f_cmp(VALUE x, VALUE y)
68 {
69  if (FIXNUM_P(x) && FIXNUM_P(y)) {
70  long c = FIX2LONG(x) - FIX2LONG(y);
71  if (c > 0)
72  return 1;
73  else if (c < 0)
74  return -1;
75  return 0;
76  }
77  return rb_cmpint(rb_funcallv(x, id_cmp, 1, &y), x, y);
78 }
79 
80 inline static VALUE
81 f_lt_p(VALUE x, VALUE y)
82 {
83  if (FIXNUM_P(x) && FIXNUM_P(y))
84  return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
85  return rb_funcall(x, '<', 1, y);
86 }
87 
88 inline static VALUE
89 f_gt_p(VALUE x, VALUE y)
90 {
91  if (FIXNUM_P(x) && FIXNUM_P(y))
92  return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
93  return rb_funcall(x, '>', 1, y);
94 }
95 
96 inline static VALUE
97 f_le_p(VALUE x, VALUE y)
98 {
99  if (FIXNUM_P(x) && FIXNUM_P(y))
100  return f_boolcast(FIX2LONG(x) <= FIX2LONG(y));
101  return rb_funcall(x, id_le_p, 1, y);
102 }
103 
104 inline static VALUE
105 f_ge_p(VALUE x, VALUE y)
106 {
107  if (FIXNUM_P(x) && FIXNUM_P(y))
108  return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
109  return rb_funcall(x, id_ge_p, 1, y);
110 }
111 
112 inline static VALUE
113 f_eqeq_p(VALUE x, VALUE y)
114 {
115  if (FIXNUM_P(x) && FIXNUM_P(y))
116  return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
117  return rb_funcall(x, id_eqeq_p, 1, y);
118 }
119 
120 inline static VALUE
121 f_zero_p(VALUE x)
122 {
123  switch (TYPE(x)) {
124  case T_FIXNUM:
125  return f_boolcast(FIX2LONG(x) == 0);
126  case T_BIGNUM:
127  return Qfalse;
128  case T_RATIONAL:
129  {
130  VALUE num = rb_rational_num(x);
131  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
132  }
133  }
134  return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0));
135 }
136 
137 #define f_nonzero_p(x) (!f_zero_p(x))
138 
139 inline static VALUE
140 f_negative_p(VALUE x)
141 {
142  if (FIXNUM_P(x))
143  return f_boolcast(FIX2LONG(x) < 0);
144  return rb_funcall(x, '<', 1, INT2FIX(0));
145 }
146 
147 #define f_positive_p(x) (!f_negative_p(x))
148 
149 #define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0)
150 #define f_jd(x) rb_funcall(x, rb_intern("jd"), 0)
151 #define f_year(x) rb_funcall(x, rb_intern("year"), 0)
152 #define f_mon(x) rb_funcall(x, rb_intern("mon"), 0)
153 #define f_mday(x) rb_funcall(x, rb_intern("mday"), 0)
154 #define f_wday(x) rb_funcall(x, rb_intern("wday"), 0)
155 #define f_hour(x) rb_funcall(x, rb_intern("hour"), 0)
156 #define f_min(x) rb_funcall(x, rb_intern("min"), 0)
157 #define f_sec(x) rb_funcall(x, rb_intern("sec"), 0)
158 
159 /* copied from time.c */
160 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
161 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
162 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
163 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
164 
165 #define HAVE_JD (1 << 0)
166 #define HAVE_DF (1 << 1)
167 #define HAVE_CIVIL (1 << 2)
168 #define HAVE_TIME (1 << 3)
169 #define COMPLEX_DAT (1 << 7)
170 
171 #define have_jd_p(x) ((x)->flags & HAVE_JD)
172 #define have_df_p(x) ((x)->flags & HAVE_DF)
173 #define have_civil_p(x) ((x)->flags & HAVE_CIVIL)
174 #define have_time_p(x) ((x)->flags & HAVE_TIME)
175 #define complex_dat_p(x) ((x)->flags & COMPLEX_DAT)
176 #define simple_dat_p(x) (!complex_dat_p(x))
177 
178 #define ITALY 2299161 /* 1582-10-15 */
179 #define ENGLAND 2361222 /* 1752-09-14 */
180 #define JULIAN positive_inf
181 #define GREGORIAN negative_inf
182 #define DEFAULT_SG ITALY
183 
184 #define UNIX_EPOCH_IN_CJD INT2FIX(2440588) /* 1970-01-01 */
185 
186 #define MINUTE_IN_SECONDS 60
187 #define HOUR_IN_SECONDS 3600
188 #define DAY_IN_SECONDS 86400
189 #define SECOND_IN_MILLISECONDS 1000
190 #define SECOND_IN_NANOSECONDS 1000000000
191 
192 #define JC_PERIOD0 1461 /* 365.25 * 4 */
193 #define GC_PERIOD0 146097 /* 365.2425 * 400 */
194 #define CM_PERIOD0 71149239 /* (lcm 7 1461 146097) */
195 #define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0)
196 #define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4)
197 #define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400)
198 
199 #define REFORM_BEGIN_YEAR 1582
200 #define REFORM_END_YEAR 1930
201 #define REFORM_BEGIN_JD 2298874 /* ns 1582-01-01 */
202 #define REFORM_END_JD 2426355 /* os 1930-12-31 */
203 
204 #ifdef USE_PACK
205 #define SEC_WIDTH 6
206 #define MIN_WIDTH 6
207 #define HOUR_WIDTH 5
208 #define MDAY_WIDTH 5
209 #define MON_WIDTH 4
210 
211 #define SEC_SHIFT 0
212 #define MIN_SHIFT SEC_WIDTH
213 #define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH)
214 #define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
215 #define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
216 
217 #define PK_MASK(x) ((1 << (x)) - 1)
218 
219 #define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH))
220 #define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH))
221 #define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH))
222 #define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH))
223 #define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH))
224 
225 #define PACK5(m,d,h,min,s) \
226  (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\
227  ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT))
228 
229 #define PACK2(m,d) \
230  (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT))
231 #endif
232 
233 #ifdef HAVE_FLOAT_H
234 #include <float.h>
235 #endif
236 
237 #if defined(FLT_RADIX) && defined(FLT_MANT_DIG) && FLT_RADIX == 2 && FLT_MANT_DIG > 22
238 #define date_sg_t float
239 #else
240 #define date_sg_t double
241 #endif
242 
243 /* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at
244  * noon of GMT (assume equal to UTC). However, this begins at
245  * midnight.
246  */
247 
249 {
250  unsigned flags;
251  int jd; /* as utc */
252  VALUE nth; /* not always canonicalized */
253  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
254  /* decoded as utc=local */
255  int year; /* truncated */
256 #ifndef USE_PACK
257  int mon;
258  int mday;
259  /* hour is zero */
260  /* min is zero */
261  /* sec is zero */
262 #else
263  /* packed civil */
264  unsigned pc;
265 #endif
266 };
267 
269 {
270  unsigned flags;
271  int jd; /* as utc */
272  VALUE nth; /* not always canonicalized */
273  date_sg_t sg; /* 2298874..2426355 or -/+oo -- at most 22 bits */
274  /* decoded as local */
275  int year; /* truncated */
276 #ifndef USE_PACK
277  int mon;
278  int mday;
279  int hour;
280  int min;
281  int sec;
282 #else
283  /* packed civil */
284  unsigned pc;
285 #endif
286  int df; /* as utc, in secs */
287  int of; /* in secs */
288  VALUE sf; /* in nano secs */
289 };
290 
291 union DateData {
292  unsigned flags;
295 };
296 
297 #define get_d1(x)\
298  union DateData *dat;\
299  TypedData_Get_Struct(x, union DateData, &d_lite_type, dat);
300 
301 #define get_d1a(x)\
302  union DateData *adat;\
303  TypedData_Get_Struct(x, union DateData, &d_lite_type, adat);
304 
305 #define get_d1b(x)\
306  union DateData *bdat;\
307  TypedData_Get_Struct(x, union DateData, &d_lite_type, bdat);
308 
309 #define get_d2(x,y)\
310  union DateData *adat, *bdat;\
311  TypedData_Get_Struct(x, union DateData, &d_lite_type, adat);\
312  TypedData_Get_Struct(y, union DateData, &d_lite_type, bdat);
313 
314 inline static VALUE
315 canon(VALUE x)
316 {
317  if (RB_TYPE_P(x, T_RATIONAL)) {
318  VALUE den = rb_rational_den(x);
319  if (FIXNUM_P(den) && FIX2LONG(den) == 1)
320  return rb_rational_num(x);
321  }
322  return x;
323 }
324 
325 #ifndef USE_PACK
326 #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
327 do {\
328  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
329  (x)->jd = _jd;\
330  (x)->sg = (date_sg_t)(_sg);\
331  (x)->year = _year;\
332  (x)->mon = _mon;\
333  (x)->mday = _mday;\
334  (x)->flags = (_flags) & ~COMPLEX_DAT;\
335 } while (0)
336 #else
337 #define set_to_simple(obj, x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
338 do {\
339  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth)); \
340  (x)->jd = _jd;\
341  (x)->sg = (date_sg_t)(_sg);\
342  (x)->year = _year;\
343  (x)->pc = PACK2(_mon, _mday);\
344  (x)->flags = (_flags) & ~COMPLEX_DAT;\
345 } while (0)
346 #endif
347 
348 #ifndef USE_PACK
349 #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
350 _year, _mon, _mday, _hour, _min, _sec, _flags) \
351 do {\
352  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
353  (x)->jd = _jd;\
354  (x)->df = _df;\
355  RB_OBJ_WRITE((obj), &(x)->sf, canon(_sf));\
356  (x)->of = _of;\
357  (x)->sg = (date_sg_t)(_sg);\
358  (x)->year = _year;\
359  (x)->mon = _mon;\
360  (x)->mday = _mday;\
361  (x)->hour = _hour;\
362  (x)->min = _min;\
363  (x)->sec = _sec;\
364  (x)->flags = (_flags) | COMPLEX_DAT;\
365 } while (0)
366 #else
367 #define set_to_complex(obj, x, _nth, _jd ,_df, _sf, _of, _sg,\
368 _year, _mon, _mday, _hour, _min, _sec, _flags) \
369 do {\
370  RB_OBJ_WRITE((obj), &(x)->nth, canon(_nth));\
371  (x)->jd = _jd;\
372  (x)->df = _df;\
373  RB_OBJ_WRITE((obj), &(x)->sf, canon(_sf));\
374  (x)->of = _of;\
375  (x)->sg = (date_sg_t)(_sg);\
376  (x)->year = _year;\
377  (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
378  (x)->flags = (_flags) | COMPLEX_DAT;\
379 } while (0)
380 #endif
381 
382 #ifndef USE_PACK
383 #define copy_simple_to_complex(obj, x, y) \
384 do {\
385  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
386  (x)->jd = (y)->jd;\
387  (x)->df = 0;\
388  (x)->sf = INT2FIX(0);\
389  (x)->of = 0;\
390  (x)->sg = (date_sg_t)((y)->sg);\
391  (x)->year = (y)->year;\
392  (x)->mon = (y)->mon;\
393  (x)->mday = (y)->mday;\
394  (x)->hour = 0;\
395  (x)->min = 0;\
396  (x)->sec = 0;\
397  (x)->flags = (y)->flags;\
398 } while (0)
399 #else
400 #define copy_simple_to_complex(obj, x, y) \
401 do {\
402  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
403  (x)->jd = (y)->jd;\
404  (x)->df = 0;\
405  RB_OBJ_WRITE((obj), &(x)->sf, INT2FIX(0));\
406  (x)->of = 0;\
407  (x)->sg = (date_sg_t)((y)->sg);\
408  (x)->year = (y)->year;\
409  (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
410  (x)->flags = (y)->flags;\
411 } while (0)
412 #endif
413 
414 #ifndef USE_PACK
415 #define copy_complex_to_simple(obj, x, y) \
416 do {\
417  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
418  (x)->jd = (y)->jd;\
419  (x)->sg = (date_sg_t)((y)->sg);\
420  (x)->year = (y)->year;\
421  (x)->mon = (y)->mon;\
422  (x)->mday = (y)->mday;\
423  (x)->flags = (y)->flags;\
424 } while (0)
425 #else
426 #define copy_complex_to_simple(obj, x, y) \
427 do {\
428  RB_OBJ_WRITE((obj), &(x)->nth, (y)->nth);\
429  (x)->jd = (y)->jd;\
430  (x)->sg = (date_sg_t)((y)->sg);\
431  (x)->year = (y)->year;\
432  (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
433  (x)->flags = (y)->flags;\
434 } while (0)
435 #endif
436 
437 /* base */
438 
439 static int c_valid_civil_p(int, int, int, double,
440  int *, int *, int *, int *);
441 
442 static int
443 c_find_fdoy(int y, double sg, int *rjd, int *ns)
444 {
445  int d, rm, rd;
446 
447  for (d = 1; d < 31; d++)
448  if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
449  return 1;
450  return 0;
451 }
452 
453 static int
454 c_find_ldoy(int y, double sg, int *rjd, int *ns)
455 {
456  int i, rm, rd;
457 
458  for (i = 0; i < 30; i++)
459  if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
460  return 1;
461  return 0;
462 }
463 
464 #ifndef NDEBUG
465 static int
466 c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
467 {
468  int d, rm, rd;
469 
470  for (d = 1; d < 31; d++)
471  if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns))
472  return 1;
473  return 0;
474 }
475 #endif
476 
477 static int
478 c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
479 {
480  int i, rm, rd;
481 
482  for (i = 0; i < 30; i++)
483  if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
484  return 1;
485  return 0;
486 }
487 
488 static void
489 c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
490 {
491  double a, b, jd;
492 
493  if (m <= 2) {
494  y -= 1;
495  m += 12;
496  }
497  a = floor(y / 100.0);
498  b = 2 - a + floor(a / 4.0);
499  jd = floor(365.25 * (y + 4716)) +
500  floor(30.6001 * (m + 1)) +
501  d + b - 1524;
502  if (jd < sg) {
503  jd -= b;
504  *ns = 0;
505  }
506  else
507  *ns = 1;
508 
509  *rjd = (int)jd;
510 }
511 
512 static void
513 c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
514 {
515  double x, a, b, c, d, e, y, m, dom;
516 
517  if (jd < sg)
518  a = jd;
519  else {
520  x = floor((jd - 1867216.25) / 36524.25);
521  a = jd + 1 + x - floor(x / 4.0);
522  }
523  b = a + 1524;
524  c = floor((b - 122.1) / 365.25);
525  d = floor(365.25 * c);
526  e = floor((b - d) / 30.6001);
527  dom = b - d - floor(30.6001 * e);
528  if (e <= 13) {
529  m = e - 1;
530  y = c - 4716;
531  }
532  else {
533  m = e - 13;
534  y = c - 4715;
535  }
536 
537  *ry = (int)y;
538  *rm = (int)m;
539  *rdom = (int)dom;
540 }
541 
542 static void
543 c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
544 {
545  int ns2;
546 
547  c_find_fdoy(y, sg, rjd, &ns2);
548  *rjd += d - 1;
549  *ns = (*rjd < sg) ? 0 : 1;
550 }
551 
552 static void
553 c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
554 {
555  int rm2, rd2, rjd, ns;
556 
557  c_jd_to_civil(jd, sg, ry, &rm2, &rd2);
558  c_find_fdoy(*ry, sg, &rjd, &ns);
559  *rd = (jd - rjd) + 1;
560 }
561 
562 static void
563 c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
564 {
565  int rjd2, ns2;
566 
567  c_find_fdoy(y, sg, &rjd2, &ns2);
568  rjd2 += 3;
569  *rjd =
570  (rjd2 - MOD((rjd2 - 1) + 1, 7)) +
571  7 * (w - 1) +
572  (d - 1);
573  *ns = (*rjd < sg) ? 0 : 1;
574 }
575 
576 static void
577 c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
578 {
579  int ry2, rm2, rd2, a, rjd2, ns2;
580 
581  c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2);
582  a = ry2;
583  c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2);
584  if (jd >= rjd2)
585  *ry = a + 1;
586  else {
587  c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2);
588  *ry = a;
589  }
590  *rw = 1 + DIV(jd - rjd2, 7);
591  *rd = MOD(jd + 1, 7);
592  if (*rd == 0)
593  *rd = 7;
594 }
595 
596 static void
597 c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
598 {
599  int rjd2, ns2;
600 
601  c_find_fdoy(y, sg, &rjd2, &ns2);
602  rjd2 += 6;
603  *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d;
604  *ns = (*rjd < sg) ? 0 : 1;
605 }
606 
607 static void
608 c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
609 {
610  int rm, rd2, rjd, ns, j;
611 
612  c_jd_to_civil(jd, sg, ry, &rm, &rd2);
613  c_find_fdoy(*ry, sg, &rjd, &ns);
614  rjd += 6;
615  j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7;
616  *rw = (int)DIV(j, 7);
617  *rd = (int)MOD(j, 7);
618 }
619 
620 #ifndef NDEBUG
621 static void
622 c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
623 {
624  int rjd2, ns2;
625 
626  if (n > 0) {
627  c_find_fdom(y, m, sg, &rjd2, &ns2);
628  rjd2 -= 1;
629  }
630  else {
631  c_find_ldom(y, m, sg, &rjd2, &ns2);
632  rjd2 += 7;
633  }
634  *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n;
635  *ns = (*rjd < sg) ? 0 : 1;
636 }
637 #endif
638 
639 inline static int
640 c_jd_to_wday(int jd)
641 {
642  return MOD(jd + 1, 7);
643 }
644 
645 #ifndef NDEBUG
646 static void
647 c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
648 {
649  int rd, rjd, ns2;
650 
651  c_jd_to_civil(jd, sg, ry, rm, &rd);
652  c_find_fdom(*ry, *rm, sg, &rjd, &ns2);
653  *rn = DIV(jd - rjd, 7) + 1;
654  *rk = c_jd_to_wday(jd);
655 }
656 #endif
657 
658 static int
659 c_valid_ordinal_p(int y, int d, double sg,
660  int *rd, int *rjd, int *ns)
661 {
662  int ry2, rd2;
663 
664  if (d < 0) {
665  int rjd2, ns2;
666 
667  if (!c_find_ldoy(y, sg, &rjd2, &ns2))
668  return 0;
669  c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2);
670  if (ry2 != y)
671  return 0;
672  d = rd2;
673  }
674  c_ordinal_to_jd(y, d, sg, rjd, ns);
675  c_jd_to_ordinal(*rjd, sg, &ry2, &rd2);
676  if (ry2 != y || rd2 != d)
677  return 0;
678  return 1;
679 }
680 
681 static const int monthtab[2][13] = {
682  { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
683  { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
684 };
685 
686 inline static int
687 c_julian_leap_p(int y)
688 {
689  return MOD(y, 4) == 0;
690 }
691 
692 inline static int
693 c_gregorian_leap_p(int y)
694 {
695  return (MOD(y, 4) == 0 && y % 100 != 0) || MOD(y, 400) == 0;
696 }
697 
698 static int
699 c_julian_last_day_of_month(int y, int m)
700 {
701  assert(m >= 1 && m <= 12);
702  return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
703 }
704 
705 static int
706 c_gregorian_last_day_of_month(int y, int m)
707 {
708  assert(m >= 1 && m <= 12);
709  return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
710 }
711 
712 static int
713 c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
714 {
715  int last;
716 
717  if (m < 0)
718  m += 13;
719  if (m < 1 || m > 12)
720  return 0;
721  last = c_julian_last_day_of_month(y, m);
722  if (d < 0)
723  d = last + d + 1;
724  if (d < 1 || d > last)
725  return 0;
726  *rm = m;
727  *rd = d;
728  return 1;
729 }
730 
731 static int
732 c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
733 {
734  int last;
735 
736  if (m < 0)
737  m += 13;
738  if (m < 1 || m > 12)
739  return 0;
740  last = c_gregorian_last_day_of_month(y, m);
741  if (d < 0)
742  d = last + d + 1;
743  if (d < 1 || d > last)
744  return 0;
745  *rm = m;
746  *rd = d;
747  return 1;
748 }
749 
750 static int
751 c_valid_civil_p(int y, int m, int d, double sg,
752  int *rm, int *rd, int *rjd, int *ns)
753 {
754  int ry;
755 
756  if (m < 0)
757  m += 13;
758  if (d < 0) {
759  if (!c_find_ldom(y, m, sg, rjd, ns))
760  return 0;
761  c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd);
762  if (ry != y || *rm != m)
763  return 0;
764  d = *rd;
765  }
766  c_civil_to_jd(y, m, d, sg, rjd, ns);
767  c_jd_to_civil(*rjd, sg, &ry, rm, rd);
768  if (ry != y || *rm != m || *rd != d)
769  return 0;
770  return 1;
771 }
772 
773 static int
774 c_valid_commercial_p(int y, int w, int d, double sg,
775  int *rw, int *rd, int *rjd, int *ns)
776 {
777  int ns2, ry2, rw2, rd2;
778 
779  if (d < 0)
780  d += 8;
781  if (w < 0) {
782  int rjd2;
783 
784  c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
785  c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
786  if (ry2 != y)
787  return 0;
788  w = rw2;
789  }
790  c_commercial_to_jd(y, w, d, sg, rjd, ns);
791  c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
792  if (y != ry2 || w != *rw || d != *rd)
793  return 0;
794  return 1;
795 }
796 
797 static int
798 c_valid_weeknum_p(int y, int w, int d, int f, double sg,
799  int *rw, int *rd, int *rjd, int *ns)
800 {
801  int ns2, ry2, rw2, rd2;
802 
803  if (d < 0)
804  d += 7;
805  if (w < 0) {
806  int rjd2;
807 
808  c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
809  c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
810  if (ry2 != y)
811  return 0;
812  w = rw2;
813  }
814  c_weeknum_to_jd(y, w, d, f, sg, rjd, ns);
815  c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
816  if (y != ry2 || w != *rw || d != *rd)
817  return 0;
818  return 1;
819 }
820 
821 #ifndef NDEBUG
822 static int
823 c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
824  int *rm, int *rn, int *rk, int *rjd, int *ns)
825 {
826  int ns2, ry2, rm2, rn2, rk2;
827 
828  if (k < 0)
829  k += 7;
830  if (n < 0) {
831  int t, ny, nm, rjd2;
832 
833  t = y * 12 + m;
834  ny = DIV(t, 12);
835  nm = MOD(t, 12) + 1;
836 
837  c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
838  c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
839  if (ry2 != y || rm2 != m)
840  return 0;
841  n = rn2;
842  }
843  c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
844  c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk);
845  if (y != ry2 || m != *rm || n != *rn || k != *rk)
846  return 0;
847  return 1;
848 }
849 #endif
850 
851 static int
852 c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
853 {
854  if (h < 0)
855  h += 24;
856  if (min < 0)
857  min += 60;
858  if (s < 0)
859  s += 60;
860  *rh = h;
861  *rmin = min;
862  *rs = s;
863  return !(h < 0 || h > 24 ||
864  min < 0 || min > 59 ||
865  s < 0 || s > 59 ||
866  (h == 24 && (min > 0 || s > 0)));
867 }
868 
869 inline static int
870 c_valid_start_p(double sg)
871 {
872  if (isnan(sg))
873  return 0;
874  if (isinf(sg))
875  return 1;
876  if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD)
877  return 0;
878  return 1;
879 }
880 
881 inline static int
882 df_local_to_utc(int df, int of)
883 {
884  df -= of;
885  if (df < 0)
886  df += DAY_IN_SECONDS;
887  else if (df >= DAY_IN_SECONDS)
888  df -= DAY_IN_SECONDS;
889  return df;
890 }
891 
892 inline static int
893 df_utc_to_local(int df, int of)
894 {
895  df += of;
896  if (df < 0)
897  df += DAY_IN_SECONDS;
898  else if (df >= DAY_IN_SECONDS)
899  df -= DAY_IN_SECONDS;
900  return df;
901 }
902 
903 inline static int
904 jd_local_to_utc(int jd, int df, int of)
905 {
906  df -= of;
907  if (df < 0)
908  jd -= 1;
909  else if (df >= DAY_IN_SECONDS)
910  jd += 1;
911  return jd;
912 }
913 
914 inline static int
915 jd_utc_to_local(int jd, int df, int of)
916 {
917  df += of;
918  if (df < 0)
919  jd -= 1;
920  else if (df >= DAY_IN_SECONDS)
921  jd += 1;
922  return jd;
923 }
924 
925 inline static int
926 time_to_df(int h, int min, int s)
927 {
928  return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
929 }
930 
931 inline static void
932 df_to_time(int df, int *h, int *min, int *s)
933 {
934  *h = df / HOUR_IN_SECONDS;
935  df %= HOUR_IN_SECONDS;
936  *min = df / MINUTE_IN_SECONDS;
937  *s = df % MINUTE_IN_SECONDS;
938 }
939 
940 static VALUE
941 sec_to_day(VALUE s)
942 {
943  if (FIXNUM_P(s))
945  return f_quo(s, INT2FIX(DAY_IN_SECONDS));
946 }
947 
948 inline static VALUE
949 isec_to_day(int s)
950 {
951  return sec_to_day(INT2FIX(s));
952 }
953 
954 static VALUE
955 ns_to_day(VALUE n)
956 {
957  if (FIXNUM_P(n))
958  return rb_rational_new2(n, day_in_nanoseconds);
959  return f_quo(n, day_in_nanoseconds);
960 }
961 
962 #ifndef NDEBUG
963 static VALUE
964 ms_to_sec(VALUE m)
965 {
966  if (FIXNUM_P(m))
969 }
970 #endif
971 
972 static VALUE
973 ns_to_sec(VALUE n)
974 {
975  if (FIXNUM_P(n))
978 }
979 
980 #ifndef NDEBUG
981 inline static VALUE
982 ins_to_day(int n)
983 {
984  return ns_to_day(INT2FIX(n));
985 }
986 #endif
987 
988 static int
989 safe_mul_p(VALUE x, long m)
990 {
991  long ix;
992 
993  if (!FIXNUM_P(x))
994  return 0;
995  ix = FIX2LONG(x);
996  if (ix < 0) {
997  if (ix <= (FIXNUM_MIN / m))
998  return 0;
999  }
1000  else {
1001  if (ix >= (FIXNUM_MAX / m))
1002  return 0;
1003  }
1004  return 1;
1005 }
1006 
1007 static VALUE
1008 day_to_sec(VALUE d)
1009 {
1010  if (safe_mul_p(d, DAY_IN_SECONDS))
1011  return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
1012  return f_mul(d, INT2FIX(DAY_IN_SECONDS));
1013 }
1014 
1015 #ifndef NDEBUG
1016 static VALUE
1017 day_to_ns(VALUE d)
1018 {
1019  return f_mul(d, day_in_nanoseconds);
1020 }
1021 #endif
1022 
1023 static VALUE
1024 sec_to_ms(VALUE s)
1025 {
1026  if (safe_mul_p(s, SECOND_IN_MILLISECONDS))
1028  return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS));
1029 }
1030 
1031 static VALUE
1032 sec_to_ns(VALUE s)
1033 {
1034  if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
1036  return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
1037 }
1038 
1039 #ifndef NDEBUG
1040 static VALUE
1041 isec_to_ns(int s)
1042 {
1043  return sec_to_ns(INT2FIX(s));
1044 }
1045 #endif
1046 
1047 static VALUE
1048 div_day(VALUE d, VALUE *f)
1049 {
1050  if (f)
1051  *f = f_mod(d, INT2FIX(1));
1052  return f_floor(d);
1053 }
1054 
1055 static VALUE
1056 div_df(VALUE d, VALUE *f)
1057 {
1058  VALUE s = day_to_sec(d);
1059 
1060  if (f)
1061  *f = f_mod(s, INT2FIX(1));
1062  return f_floor(s);
1063 }
1064 
1065 #ifndef NDEBUG
1066 static VALUE
1067 div_sf(VALUE s, VALUE *f)
1068 {
1069  VALUE n = sec_to_ns(s);
1070 
1071  if (f)
1072  *f = f_mod(n, INT2FIX(1));
1073  return f_floor(n);
1074 }
1075 #endif
1076 
1077 static void
1078 decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
1079 {
1080  VALUE f;
1081 
1082  *jd = div_day(d, &f);
1083  *df = div_df(f, &f);
1084  *sf = sec_to_ns(f);
1085 }
1086 
1087 inline static double
1088 s_virtual_sg(union DateData *x)
1089 {
1090  if (isinf(x->s.sg))
1091  return x->s.sg;
1092  if (f_zero_p(x->s.nth))
1093  return x->s.sg;
1094  else if (f_negative_p(x->s.nth))
1095  return positive_inf;
1096  return negative_inf;
1097 }
1098 
1099 inline static double
1100 c_virtual_sg(union DateData *x)
1101 {
1102  if (isinf(x->c.sg))
1103  return x->c.sg;
1104  if (f_zero_p(x->c.nth))
1105  return x->c.sg;
1106  else if (f_negative_p(x->c.nth))
1107  return positive_inf;
1108  return negative_inf;
1109 }
1110 
1111 inline static double
1112 m_virtual_sg(union DateData *x)
1113 {
1114  if (simple_dat_p(x))
1115  return s_virtual_sg(x);
1116  else
1117  return c_virtual_sg(x);
1118 }
1119 
1120 #define canonicalize_jd(_nth, _jd) \
1121 do {\
1122  if (_jd < 0) {\
1123  _nth = f_sub(_nth, INT2FIX(1));\
1124  _jd += CM_PERIOD;\
1125  }\
1126  if (_jd >= CM_PERIOD) {\
1127  _nth = f_add(_nth, INT2FIX(1));\
1128  _jd -= CM_PERIOD;\
1129  }\
1130 } while (0)
1131 
1132 inline static void
1133 canonicalize_s_jd(VALUE obj, union DateData *x)
1134 {
1135  int j = x->s.jd;
1136  VALUE nth = x->s.nth;
1137  assert(have_jd_p(x));
1138  canonicalize_jd(nth, x->s.jd);
1139  RB_OBJ_WRITE(obj, &x->s.nth, nth);
1140  if (x->s.jd != j)
1141  x->flags &= ~HAVE_CIVIL;
1142 }
1143 
1144 inline static void
1145 get_s_jd(union DateData *x)
1146 {
1147  assert(simple_dat_p(x));
1148  if (!have_jd_p(x)) {
1149  int jd, ns;
1150 
1151  assert(have_civil_p(x));
1152 #ifndef USE_PACK
1153  c_civil_to_jd(x->s.year, x->s.mon, x->s.mday,
1154  s_virtual_sg(x), &jd, &ns);
1155 #else
1156  c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
1157  s_virtual_sg(x), &jd, &ns);
1158 #endif
1159  x->s.jd = jd;
1160  x->s.flags |= HAVE_JD;
1161  }
1162 }
1163 
1164 inline static void
1165 get_s_civil(union DateData *x)
1166 {
1167  assert(simple_dat_p(x));
1168  if (!have_civil_p(x)) {
1169  int y, m, d;
1170 
1171  assert(have_jd_p(x));
1172  c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d);
1173  x->s.year = y;
1174 #ifndef USE_PACK
1175  x->s.mon = m;
1176  x->s.mday = d;
1177 #else
1178  x->s.pc = PACK2(m, d);
1179 #endif
1180  x->s.flags |= HAVE_CIVIL;
1181  }
1182 }
1183 
1184 inline static void
1185 get_c_df(union DateData *x)
1186 {
1187  assert(complex_dat_p(x));
1188  if (!have_df_p(x)) {
1189  assert(have_time_p(x));
1190 #ifndef USE_PACK
1191  x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec),
1192  x->c.of);
1193 #else
1194  x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
1195  EX_MIN(x->c.pc),
1196  EX_SEC(x->c.pc)),
1197  x->c.of);
1198 #endif
1199  x->c.flags |= HAVE_DF;
1200  }
1201 }
1202 
1203 inline static void
1204 get_c_time(union DateData *x)
1205 {
1206  assert(complex_dat_p(x));
1207  if (!have_time_p(x)) {
1208 #ifndef USE_PACK
1209  int r;
1210  assert(have_df_p(x));
1211  r = df_utc_to_local(x->c.df, x->c.of);
1212  df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
1213  x->c.flags |= HAVE_TIME;
1214 #else
1215  int r, m, d, h, min, s;
1216 
1217  assert(have_df_p(x));
1218  m = EX_MON(x->c.pc);
1219  d = EX_MDAY(x->c.pc);
1220  r = df_utc_to_local(x->c.df, x->c.of);
1221  df_to_time(r, &h, &min, &s);
1222  x->c.pc = PACK5(m, d, h, min, s);
1223  x->c.flags |= HAVE_TIME;
1224 #endif
1225  }
1226 }
1227 
1228 inline static void
1229 canonicalize_c_jd(VALUE obj, union DateData *x)
1230 {
1231  int j = x->c.jd;
1232  VALUE nth = x->c.nth;
1233  assert(have_jd_p(x));
1234  canonicalize_jd(nth, x->c.jd);
1235  RB_OBJ_WRITE(obj, &x->c.nth, nth);
1236  if (x->c.jd != j)
1237  x->flags &= ~HAVE_CIVIL;
1238 }
1239 
1240 inline static void
1241 get_c_jd(union DateData *x)
1242 {
1243  assert(complex_dat_p(x));
1244  if (!have_jd_p(x)) {
1245  int jd, ns;
1246 
1247  assert(have_civil_p(x));
1248 #ifndef USE_PACK
1249  c_civil_to_jd(x->c.year, x->c.mon, x->c.mday,
1250  c_virtual_sg(x), &jd, &ns);
1251 #else
1252  c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
1253  c_virtual_sg(x), &jd, &ns);
1254 #endif
1255 
1256  get_c_time(x);
1257 #ifndef USE_PACK
1258  x->c.jd = jd_local_to_utc(jd,
1259  time_to_df(x->c.hour, x->c.min, x->c.sec),
1260  x->c.of);
1261 #else
1262  x->c.jd = jd_local_to_utc(jd,
1263  time_to_df(EX_HOUR(x->c.pc),
1264  EX_MIN(x->c.pc),
1265  EX_SEC(x->c.pc)),
1266  x->c.of);
1267 #endif
1268  x->c.flags |= HAVE_JD;
1269  }
1270 }
1271 
1272 inline static void
1273 get_c_civil(union DateData *x)
1274 {
1275  assert(complex_dat_p(x));
1276  if (!have_civil_p(x)) {
1277 #ifndef USE_PACK
1278  int jd, y, m, d;
1279 #else
1280  int jd, y, m, d, h, min, s;
1281 #endif
1282 
1283  assert(have_jd_p(x));
1284  get_c_df(x);
1285  jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
1286  c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d);
1287  x->c.year = y;
1288 #ifndef USE_PACK
1289  x->c.mon = m;
1290  x->c.mday = d;
1291 #else
1292  h = EX_HOUR(x->c.pc);
1293  min = EX_MIN(x->c.pc);
1294  s = EX_SEC(x->c.pc);
1295  x->c.pc = PACK5(m, d, h, min, s);
1296 #endif
1297  x->c.flags |= HAVE_CIVIL;
1298  }
1299 }
1300 
1301 inline static int
1302 local_jd(union DateData *x)
1303 {
1304  assert(complex_dat_p(x));
1305  assert(have_jd_p(x));
1306  assert(have_df_p(x));
1307  return jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
1308 }
1309 
1310 inline static int
1311 local_df(union DateData *x)
1312 {
1313  assert(complex_dat_p(x));
1314  assert(have_df_p(x));
1315  return df_utc_to_local(x->c.df, x->c.of);
1316 }
1317 
1318 static void
1319 decode_year(VALUE y, double style,
1320  VALUE *nth, int *ry)
1321 {
1322  int period;
1323  VALUE t;
1324 
1325  period = (style < 0) ?
1326  CM_PERIOD_GCY :
1327  CM_PERIOD_JCY;
1328  if (FIXNUM_P(y)) {
1329  long iy, it, inth;
1330 
1331  iy = FIX2LONG(y);
1332  if (iy >= (FIXNUM_MAX - 4712))
1333  goto big;
1334  it = iy + 4712; /* shift */
1335  inth = DIV(it, ((long)period));
1336  *nth = LONG2FIX(inth);
1337  if (inth)
1338  it = MOD(it, ((long)period));
1339  *ry = (int)it - 4712; /* unshift */
1340  return;
1341  }
1342  big:
1343  t = f_add(y, INT2FIX(4712)); /* shift */
1344  *nth = f_idiv(t, INT2FIX(period));
1345  if (f_nonzero_p(*nth))
1346  t = f_mod(t, INT2FIX(period));
1347  *ry = FIX2INT(t) - 4712; /* unshift */
1348 }
1349 
1350 static void
1351 encode_year(VALUE nth, int y, double style,
1352  VALUE *ry)
1353 {
1354  int period;
1355  VALUE t;
1356 
1357  period = (style < 0) ?
1358  CM_PERIOD_GCY :
1359  CM_PERIOD_JCY;
1360  if (f_zero_p(nth))
1361  *ry = INT2FIX(y);
1362  else {
1363  t = f_mul(INT2FIX(period), nth);
1364  t = f_add(t, INT2FIX(y));
1365  *ry = t;
1366  }
1367 }
1368 
1369 static void
1370 decode_jd(VALUE jd, VALUE *nth, int *rjd)
1371 {
1372  *nth = f_idiv(jd, INT2FIX(CM_PERIOD));
1373  if (f_zero_p(*nth)) {
1374  *rjd = FIX2INT(jd);
1375  return;
1376  }
1377  *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD)));
1378 }
1379 
1380 static void
1381 encode_jd(VALUE nth, int jd, VALUE *rjd)
1382 {
1383  if (f_zero_p(nth)) {
1384  *rjd = INT2FIX(jd);
1385  return;
1386  }
1387  *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
1388 }
1389 
1390 inline static double
1391 guess_style(VALUE y, double sg) /* -/+oo or zero */
1392 {
1393  double style = 0;
1394 
1395  if (isinf(sg))
1396  style = sg;
1397  else if (!FIXNUM_P(y))
1398  style = f_positive_p(y) ? negative_inf : positive_inf;
1399  else {
1400  long iy = FIX2LONG(y);
1401 
1402  assert(FIXNUM_P(y));
1403  if (iy < REFORM_BEGIN_YEAR)
1404  style = positive_inf;
1405  else if (iy > REFORM_END_YEAR)
1406  style = negative_inf;
1407  }
1408  return style;
1409 }
1410 
1411 inline static void
1412 m_canonicalize_jd(VALUE obj, union DateData *x)
1413 {
1414  if (simple_dat_p(x)) {
1415  get_s_jd(x);
1416  canonicalize_s_jd(obj, x);
1417  }
1418  else {
1419  get_c_jd(x);
1420  canonicalize_c_jd(obj, x);
1421  }
1422 }
1423 
1424 inline static VALUE
1425 m_nth(union DateData *x)
1426 {
1427  if (simple_dat_p(x))
1428  return x->s.nth;
1429  else {
1430  get_c_civil(x);
1431  return x->c.nth;
1432  }
1433 }
1434 
1435 inline static int
1436 m_jd(union DateData *x)
1437 {
1438  if (simple_dat_p(x)) {
1439  get_s_jd(x);
1440  return x->s.jd;
1441  }
1442  else {
1443  get_c_jd(x);
1444  return x->c.jd;
1445  }
1446 }
1447 
1448 static VALUE
1449 m_real_jd(union DateData *x)
1450 {
1451  VALUE nth, rjd;
1452  int jd;
1453 
1454  nth = m_nth(x);
1455  jd = m_jd(x);
1456 
1457  encode_jd(nth, jd, &rjd);
1458  return rjd;
1459 }
1460 
1461 static int
1462 m_local_jd(union DateData *x)
1463 {
1464  if (simple_dat_p(x)) {
1465  get_s_jd(x);
1466  return x->s.jd;
1467  }
1468  else {
1469  get_c_jd(x);
1470  get_c_df(x);
1471  return local_jd(x);
1472  }
1473 }
1474 
1475 static VALUE
1476 m_real_local_jd(union DateData *x)
1477 {
1478  VALUE nth, rjd;
1479  int jd;
1480 
1481  nth = m_nth(x);
1482  jd = m_local_jd(x);
1483 
1484  encode_jd(nth, jd, &rjd);
1485  return rjd;
1486 }
1487 
1488 inline static int
1489 m_df(union DateData *x)
1490 {
1491  if (simple_dat_p(x))
1492  return 0;
1493  else {
1494  get_c_df(x);
1495  return x->c.df;
1496  }
1497 }
1498 
1499 #ifndef NDEBUG
1500 static VALUE
1501 m_df_in_day(union DateData *x)
1502 {
1503  return isec_to_day(m_df(x));
1504 }
1505 #endif
1506 
1507 static int
1508 m_local_df(union DateData *x)
1509 {
1510  if (simple_dat_p(x))
1511  return 0;
1512  else {
1513  get_c_df(x);
1514  return local_df(x);
1515  }
1516 }
1517 
1518 #ifndef NDEBUG
1519 static VALUE
1520 m_local_df_in_day(union DateData *x)
1521 {
1522  return isec_to_day(m_local_df(x));
1523 }
1524 #endif
1525 
1526 inline static VALUE
1527 m_sf(union DateData *x)
1528 {
1529  if (simple_dat_p(x))
1530  return INT2FIX(0);
1531  else
1532  return x->c.sf;
1533 }
1534 
1535 #ifndef NDEBUG
1536 static VALUE
1537 m_sf_in_day(union DateData *x)
1538 {
1539  return ns_to_day(m_sf(x));
1540 }
1541 #endif
1542 
1543 static VALUE
1544 m_sf_in_sec(union DateData *x)
1545 {
1546  return ns_to_sec(m_sf(x));
1547 }
1548 
1549 static VALUE
1550 m_fr(union DateData *x)
1551 {
1552  if (simple_dat_p(x))
1553  return INT2FIX(0);
1554  else {
1555  int df;
1556  VALUE sf, fr;
1557 
1558  df = m_local_df(x);
1559  sf = m_sf(x);
1560  fr = isec_to_day(df);
1561  if (f_nonzero_p(sf))
1562  fr = f_add(fr, ns_to_day(sf));
1563  return fr;
1564  }
1565 }
1566 
1567 #define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2)
1568 
1569 static VALUE
1570 m_ajd(union DateData *x)
1571 {
1572  VALUE r, sf;
1573  int df;
1574 
1575  if (simple_dat_p(x)) {
1576  r = m_real_jd(x);
1577  if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
1578  long ir = FIX2LONG(r);
1579  ir = ir * 2 - 1;
1580  return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
1581  }
1582  else
1583  return rb_rational_new2(f_sub(f_mul(r,
1584  INT2FIX(2)),
1585  INT2FIX(1)),
1586  INT2FIX(2));
1587  }
1588 
1589  r = m_real_jd(x);
1590  df = m_df(x);
1592  if (df)
1593  r = f_add(r, isec_to_day(df));
1594  sf = m_sf(x);
1595  if (f_nonzero_p(sf))
1596  r = f_add(r, ns_to_day(sf));
1597 
1598  return r;
1599 }
1600 
1601 static VALUE
1602 m_amjd(union DateData *x)
1603 {
1604  VALUE r, sf;
1605  int df;
1606 
1607  r = m_real_jd(x);
1608  if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) {
1609  long ir = FIX2LONG(r);
1610  ir -= 2400001;
1611  r = rb_rational_new1(LONG2FIX(ir));
1612  }
1613  else
1614  r = rb_rational_new1(f_sub(m_real_jd(x),
1615  INT2FIX(2400001)));
1616 
1617  if (simple_dat_p(x))
1618  return r;
1619 
1620  df = m_df(x);
1621  if (df)
1622  r = f_add(r, isec_to_day(df));
1623  sf = m_sf(x);
1624  if (f_nonzero_p(sf))
1625  r = f_add(r, ns_to_day(sf));
1626 
1627  return r;
1628 }
1629 
1630 inline static int
1631 m_of(union DateData *x)
1632 {
1633  if (simple_dat_p(x))
1634  return 0;
1635  else {
1636  get_c_jd(x);
1637  return x->c.of;
1638  }
1639 }
1640 
1641 static VALUE
1642 m_of_in_day(union DateData *x)
1643 {
1644  return isec_to_day(m_of(x));
1645 }
1646 
1647 inline static double
1648 m_sg(union DateData *x)
1649 {
1650  if (simple_dat_p(x))
1651  return x->s.sg;
1652  else {
1653  get_c_jd(x);
1654  return x->c.sg;
1655  }
1656 }
1657 
1658 static int
1659 m_julian_p(union DateData *x)
1660 {
1661  int jd;
1662  double sg;
1663 
1664  if (simple_dat_p(x)) {
1665  get_s_jd(x);
1666  jd = x->s.jd;
1667  sg = s_virtual_sg(x);
1668  }
1669  else {
1670  get_c_jd(x);
1671  jd = x->c.jd;
1672  sg = c_virtual_sg(x);
1673  }
1674  if (isinf(sg))
1675  return sg == positive_inf;
1676  return jd < sg;
1677 }
1678 
1679 inline static int
1680 m_gregorian_p(union DateData *x)
1681 {
1682  return !m_julian_p(x);
1683 }
1684 
1685 inline static int
1686 m_proleptic_julian_p(union DateData *x)
1687 {
1688  double sg;
1689 
1690  sg = m_sg(x);
1691  if (isinf(sg) && sg > 0)
1692  return 1;
1693  return 0;
1694 }
1695 
1696 inline static int
1697 m_proleptic_gregorian_p(union DateData *x)
1698 {
1699  double sg;
1700 
1701  sg = m_sg(x);
1702  if (isinf(sg) && sg < 0)
1703  return 1;
1704  return 0;
1705 }
1706 
1707 inline static int
1708 m_year(union DateData *x)
1709 {
1710  if (simple_dat_p(x)) {
1711  get_s_civil(x);
1712  return x->s.year;
1713  }
1714  else {
1715  get_c_civil(x);
1716  return x->c.year;
1717  }
1718 }
1719 
1720 static VALUE
1721 m_real_year(union DateData *x)
1722 {
1723  VALUE nth, ry;
1724  int year;
1725 
1726  nth = m_nth(x);
1727  year = m_year(x);
1728 
1729  if (f_zero_p(nth))
1730  return INT2FIX(year);
1731 
1732  encode_year(nth, year,
1733  m_gregorian_p(x) ? -1 : +1,
1734  &ry);
1735  return ry;
1736 }
1737 
1738 inline static int
1739 m_mon(union DateData *x)
1740 {
1741  if (simple_dat_p(x)) {
1742  get_s_civil(x);
1743 #ifndef USE_PACK
1744  return x->s.mon;
1745 #else
1746  return EX_MON(x->s.pc);
1747 #endif
1748  }
1749  else {
1750  get_c_civil(x);
1751 #ifndef USE_PACK
1752  return x->c.mon;
1753 #else
1754  return EX_MON(x->c.pc);
1755 #endif
1756  }
1757 }
1758 
1759 inline static int
1760 m_mday(union DateData *x)
1761 {
1762  if (simple_dat_p(x)) {
1763  get_s_civil(x);
1764 #ifndef USE_PACK
1765  return x->s.mday;
1766 #else
1767  return EX_MDAY(x->s.pc);
1768 #endif
1769  }
1770  else {
1771  get_c_civil(x);
1772 #ifndef USE_PACK
1773  return x->c.mday;
1774 #else
1775  return EX_MDAY(x->c.pc);
1776 #endif
1777  }
1778 }
1779 
1780 static const int yeartab[2][13] = {
1781  { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
1782  { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
1783 };
1784 
1785 static int
1786 c_julian_to_yday(int y, int m, int d)
1787 {
1788  assert(m >= 1 && m <= 12);
1789  return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
1790 }
1791 
1792 static int
1793 c_gregorian_to_yday(int y, int m, int d)
1794 {
1795  assert(m >= 1 && m <= 12);
1796  return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
1797 }
1798 
1799 static int
1800 m_yday(union DateData *x)
1801 {
1802  int jd, ry, rd;
1803  double sg;
1804 
1805  jd = m_local_jd(x);
1806  sg = m_virtual_sg(x); /* !=m_sg() */
1807 
1808  if (m_proleptic_gregorian_p(x) ||
1809  (jd - sg) > 366)
1810  return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
1811  if (m_proleptic_julian_p(x))
1812  return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
1813  c_jd_to_ordinal(jd, sg, &ry, &rd);
1814  return rd;
1815 }
1816 
1817 static int
1818 m_wday(union DateData *x)
1819 {
1820  return c_jd_to_wday(m_local_jd(x));
1821 }
1822 
1823 static int
1824 m_cwyear(union DateData *x)
1825 {
1826  int ry, rw, rd;
1827 
1828  c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
1829  &ry, &rw, &rd);
1830  return ry;
1831 }
1832 
1833 static VALUE
1834 m_real_cwyear(union DateData *x)
1835 {
1836  VALUE nth, ry;
1837  int year;
1838 
1839  nth = m_nth(x);
1840  year = m_cwyear(x);
1841 
1842  if (f_zero_p(nth))
1843  return INT2FIX(year);
1844 
1845  encode_year(nth, year,
1846  m_gregorian_p(x) ? -1 : +1,
1847  &ry);
1848  return ry;
1849 }
1850 
1851 static int
1852 m_cweek(union DateData *x)
1853 {
1854  int ry, rw, rd;
1855 
1856  c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */
1857  &ry, &rw, &rd);
1858  return rw;
1859 }
1860 
1861 static int
1862 m_cwday(union DateData *x)
1863 {
1864  int w;
1865 
1866  w = m_wday(x);
1867  if (w == 0)
1868  w = 7;
1869  return w;
1870 }
1871 
1872 static int
1873 m_wnumx(union DateData *x, int f)
1874 {
1875  int ry, rw, rd;
1876 
1877  c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x), /* !=m_sg() */
1878  &ry, &rw, &rd);
1879  return rw;
1880 }
1881 
1882 static int
1883 m_wnum0(union DateData *x)
1884 {
1885  return m_wnumx(x, 0);
1886 }
1887 
1888 static int
1889 m_wnum1(union DateData *x)
1890 {
1891  return m_wnumx(x, 1);
1892 }
1893 
1894 inline static int
1895 m_hour(union DateData *x)
1896 {
1897  if (simple_dat_p(x))
1898  return 0;
1899  else {
1900  get_c_time(x);
1901 #ifndef USE_PACK
1902  return x->c.hour;
1903 #else
1904  return EX_HOUR(x->c.pc);
1905 #endif
1906  }
1907 }
1908 
1909 inline static int
1910 m_min(union DateData *x)
1911 {
1912  if (simple_dat_p(x))
1913  return 0;
1914  else {
1915  get_c_time(x);
1916 #ifndef USE_PACK
1917  return x->c.min;
1918 #else
1919  return EX_MIN(x->c.pc);
1920 #endif
1921  }
1922 }
1923 
1924 inline static int
1925 m_sec(union DateData *x)
1926 {
1927  if (simple_dat_p(x))
1928  return 0;
1929  else {
1930  get_c_time(x);
1931 #ifndef USE_PACK
1932  return x->c.sec;
1933 #else
1934  return EX_SEC(x->c.pc);
1935 #endif
1936  }
1937 }
1938 
1939 #define decode_offset(of,s,h,m)\
1940 do {\
1941  int a;\
1942  s = (of < 0) ? '-' : '+';\
1943  a = (of < 0) ? -of : of;\
1944  h = a / HOUR_IN_SECONDS;\
1945  m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
1946 } while (0)
1947 
1948 static VALUE
1949 of2str(int of)
1950 {
1951  int s, h, m;
1952 
1953  decode_offset(of, s, h, m);
1954  return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
1955 }
1956 
1957 static VALUE
1958 m_zone(union DateData *x)
1959 {
1960  if (simple_dat_p(x))
1961  return rb_usascii_str_new2("+00:00");
1962  return of2str(m_of(x));
1963 }
1964 
1965 inline static VALUE
1966 f_kind_of_p(VALUE x, VALUE c)
1967 {
1968  return rb_obj_is_kind_of(x, c);
1969 }
1970 
1971 inline static VALUE
1972 k_date_p(VALUE x)
1973 {
1974  return f_kind_of_p(x, cDate);
1975 }
1976 
1977 inline static VALUE
1978 k_numeric_p(VALUE x)
1979 {
1980  return f_kind_of_p(x, rb_cNumeric);
1981 }
1982 
1983 inline static VALUE
1984 k_rational_p(VALUE x)
1985 {
1986  return f_kind_of_p(x, rb_cRational);
1987 }
1988 
1989 static inline void
1990 expect_numeric(VALUE x)
1991 {
1992  if (!k_numeric_p(x))
1993  rb_raise(rb_eTypeError, "expected numeric");
1994 }
1995 
1996 #ifndef NDEBUG
1997 static void
1998 civil_to_jd(VALUE y, int m, int d, double sg,
1999  VALUE *nth, int *ry,
2000  int *rjd,
2001  int *ns)
2002 {
2003  double style = guess_style(y, sg);
2004 
2005  if (style == 0) {
2006  int jd;
2007 
2008  c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns);
2009  decode_jd(INT2FIX(jd), nth, rjd);
2010  if (f_zero_p(*nth))
2011  *ry = FIX2INT(y);
2012  else {
2013  VALUE nth2;
2014  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2015  }
2016  }
2017  else {
2018  decode_year(y, style, nth, ry);
2019  c_civil_to_jd(*ry, m, d, style, rjd, ns);
2020  }
2021 }
2022 
2023 static void
2024 jd_to_civil(VALUE jd, double sg,
2025  VALUE *nth, int *rjd,
2026  int *ry, int *rm, int *rd)
2027 {
2028  decode_jd(jd, nth, rjd);
2029  c_jd_to_civil(*rjd, sg, ry, rm, rd);
2030 }
2031 
2032 static void
2033 ordinal_to_jd(VALUE y, int d, double sg,
2034  VALUE *nth, int *ry,
2035  int *rjd,
2036  int *ns)
2037 {
2038  double style = guess_style(y, sg);
2039 
2040  if (style == 0) {
2041  int jd;
2042 
2043  c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns);
2044  decode_jd(INT2FIX(jd), nth, rjd);
2045  if (f_zero_p(*nth))
2046  *ry = FIX2INT(y);
2047  else {
2048  VALUE nth2;
2049  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2050  }
2051  }
2052  else {
2053  decode_year(y, style, nth, ry);
2054  c_ordinal_to_jd(*ry, d, style, rjd, ns);
2055  }
2056 }
2057 
2058 static void
2059 jd_to_ordinal(VALUE jd, double sg,
2060  VALUE *nth, int *rjd,
2061  int *ry, int *rd)
2062 {
2063  decode_jd(jd, nth, rjd);
2064  c_jd_to_ordinal(*rjd, sg, ry, rd);
2065 }
2066 
2067 static void
2068 commercial_to_jd(VALUE y, int w, int d, double sg,
2069  VALUE *nth, int *ry,
2070  int *rjd,
2071  int *ns)
2072 {
2073  double style = guess_style(y, sg);
2074 
2075  if (style == 0) {
2076  int jd;
2077 
2078  c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns);
2079  decode_jd(INT2FIX(jd), nth, rjd);
2080  if (f_zero_p(*nth))
2081  *ry = FIX2INT(y);
2082  else {
2083  VALUE nth2;
2084  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2085  }
2086  }
2087  else {
2088  decode_year(y, style, nth, ry);
2089  c_commercial_to_jd(*ry, w, d, style, rjd, ns);
2090  }
2091 }
2092 
2093 static void
2094 jd_to_commercial(VALUE jd, double sg,
2095  VALUE *nth, int *rjd,
2096  int *ry, int *rw, int *rd)
2097 {
2098  decode_jd(jd, nth, rjd);
2099  c_jd_to_commercial(*rjd, sg, ry, rw, rd);
2100 }
2101 
2102 static void
2103 weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
2104  VALUE *nth, int *ry,
2105  int *rjd,
2106  int *ns)
2107 {
2108  double style = guess_style(y, sg);
2109 
2110  if (style == 0) {
2111  int jd;
2112 
2113  c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns);
2114  decode_jd(INT2FIX(jd), nth, rjd);
2115  if (f_zero_p(*nth))
2116  *ry = FIX2INT(y);
2117  else {
2118  VALUE nth2;
2119  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2120  }
2121  }
2122  else {
2123  decode_year(y, style, nth, ry);
2124  c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns);
2125  }
2126 }
2127 
2128 static void
2129 jd_to_weeknum(VALUE jd, int f, double sg,
2130  VALUE *nth, int *rjd,
2131  int *ry, int *rw, int *rd)
2132 {
2133  decode_jd(jd, nth, rjd);
2134  c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd);
2135 }
2136 
2137 static void
2138 nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
2139  VALUE *nth, int *ry,
2140  int *rjd,
2141  int *ns)
2142 {
2143  double style = guess_style(y, sg);
2144 
2145  if (style == 0) {
2146  int jd;
2147 
2148  c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns);
2149  decode_jd(INT2FIX(jd), nth, rjd);
2150  if (f_zero_p(*nth))
2151  *ry = FIX2INT(y);
2152  else {
2153  VALUE nth2;
2154  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2155  }
2156  }
2157  else {
2158  decode_year(y, style, nth, ry);
2159  c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns);
2160  }
2161 }
2162 
2163 static void
2164 jd_to_nth_kday(VALUE jd, double sg,
2165  VALUE *nth, int *rjd,
2166  int *ry, int *rm, int *rn, int *rk)
2167 {
2168  decode_jd(jd, nth, rjd);
2169  c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk);
2170 }
2171 #endif
2172 
2173 static int
2174 valid_ordinal_p(VALUE y, int d, double sg,
2175  VALUE *nth, int *ry,
2176  int *rd, int *rjd,
2177  int *ns)
2178 {
2179  double style = guess_style(y, sg);
2180  int r;
2181 
2182  if (style == 0) {
2183  int jd;
2184 
2185  r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
2186  if (!r)
2187  return 0;
2188  decode_jd(INT2FIX(jd), nth, rjd);
2189  if (f_zero_p(*nth))
2190  *ry = FIX2INT(y);
2191  else {
2192  VALUE nth2;
2193  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2194  }
2195  }
2196  else {
2197  decode_year(y, style, nth, ry);
2198  r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns);
2199  }
2200  return r;
2201 }
2202 
2203 static int
2204 valid_gregorian_p(VALUE y, int m, int d,
2205  VALUE *nth, int *ry,
2206  int *rm, int *rd)
2207 {
2208  decode_year(y, -1, nth, ry);
2209  return c_valid_gregorian_p(*ry, m, d, rm, rd);
2210 }
2211 
2212 static int
2213 valid_civil_p(VALUE y, int m, int d, double sg,
2214  VALUE *nth, int *ry,
2215  int *rm, int *rd, int *rjd,
2216  int *ns)
2217 {
2218  double style = guess_style(y, sg);
2219  int r;
2220 
2221  if (style == 0) {
2222  int jd;
2223 
2224  r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
2225  if (!r)
2226  return 0;
2227  decode_jd(INT2FIX(jd), nth, rjd);
2228  if (f_zero_p(*nth))
2229  *ry = FIX2INT(y);
2230  else {
2231  VALUE nth2;
2232  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2233  }
2234  }
2235  else {
2236  decode_year(y, style, nth, ry);
2237  if (style < 0)
2238  r = c_valid_gregorian_p(*ry, m, d, rm, rd);
2239  else
2240  r = c_valid_julian_p(*ry, m, d, rm, rd);
2241  if (!r)
2242  return 0;
2243  c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
2244  }
2245  return r;
2246 }
2247 
2248 static int
2249 valid_commercial_p(VALUE y, int w, int d, double sg,
2250  VALUE *nth, int *ry,
2251  int *rw, int *rd, int *rjd,
2252  int *ns)
2253 {
2254  double style = guess_style(y, sg);
2255  int r;
2256 
2257  if (style == 0) {
2258  int jd;
2259 
2260  r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
2261  if (!r)
2262  return 0;
2263  decode_jd(INT2FIX(jd), nth, rjd);
2264  if (f_zero_p(*nth))
2265  *ry = FIX2INT(y);
2266  else {
2267  VALUE nth2;
2268  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2269  }
2270  }
2271  else {
2272  decode_year(y, style, nth, ry);
2273  r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns);
2274  }
2275  return r;
2276 }
2277 
2278 static int
2279 valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
2280  VALUE *nth, int *ry,
2281  int *rw, int *rd, int *rjd,
2282  int *ns)
2283 {
2284  double style = guess_style(y, sg);
2285  int r;
2286 
2287  if (style == 0) {
2288  int jd;
2289 
2290  r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
2291  if (!r)
2292  return 0;
2293  decode_jd(INT2FIX(jd), nth, rjd);
2294  if (f_zero_p(*nth))
2295  *ry = FIX2INT(y);
2296  else {
2297  VALUE nth2;
2298  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2299  }
2300  }
2301  else {
2302  decode_year(y, style, nth, ry);
2303  r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns);
2304  }
2305  return r;
2306 }
2307 
2308 #ifndef NDEBUG
2309 static int
2310 valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
2311  VALUE *nth, int *ry,
2312  int *rm, int *rn, int *rk, int *rjd,
2313  int *ns)
2314 {
2315  double style = guess_style(y, sg);
2316  int r;
2317 
2318  if (style == 0) {
2319  int jd;
2320 
2321  r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
2322  if (!r)
2323  return 0;
2324  decode_jd(INT2FIX(jd), nth, rjd);
2325  if (f_zero_p(*nth))
2326  *ry = FIX2INT(y);
2327  else {
2328  VALUE nth2;
2329  decode_year(y, *ns ? -1 : +1, &nth2, ry);
2330  }
2331  }
2332  else {
2333  decode_year(y, style, nth, ry);
2334  r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns);
2335  }
2336  return r;
2337 }
2338 #endif
2339 
2341 
2342 static int
2343 offset_to_sec(VALUE vof, int *rof)
2344 {
2345  int try_rational = 1;
2346 
2347  again:
2348  switch (TYPE(vof)) {
2349  case T_FIXNUM:
2350  {
2351  long n;
2352 
2353  n = FIX2LONG(vof);
2354  if (n != -1 && n != 0 && n != 1)
2355  return 0;
2356  *rof = (int)n * DAY_IN_SECONDS;
2357  return 1;
2358  }
2359  case T_FLOAT:
2360  {
2361  double n;
2362 
2363  n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS;
2364  if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2365  return 0;
2366  *rof = (int)round(n);
2367  if (*rof != n)
2368  rb_warning("fraction of offset is ignored");
2369  return 1;
2370  }
2371  default:
2372  expect_numeric(vof);
2373  vof = f_to_r(vof);
2374  if (!k_rational_p(vof)) {
2375  if (!try_rational) Check_Type(vof, T_RATIONAL);
2376  try_rational = 0;
2377  goto again;
2378  }
2379  /* fall through */
2380  case T_RATIONAL:
2381  {
2382  VALUE vs, vn, vd;
2383  long n;
2384 
2385  vs = day_to_sec(vof);
2386 
2387  if (!k_rational_p(vs)) {
2388  vn = vs;
2389  goto rounded;
2390  }
2391  vn = rb_rational_num(vs);
2392  vd = rb_rational_den(vs);
2393 
2394  if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1))
2395  n = FIX2LONG(vn);
2396  else {
2397  vn = f_round(vs);
2398  if (!f_eqeq_p(vn, vs))
2399  rb_warning("fraction of offset is ignored");
2400  rounded:
2401  if (!FIXNUM_P(vn))
2402  return 0;
2403  n = FIX2LONG(vn);
2404  if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2405  return 0;
2406  }
2407  *rof = (int)n;
2408  return 1;
2409  }
2410  case T_STRING:
2411  {
2412  VALUE vs = date_zone_to_diff(vof);
2413  long n;
2414 
2415  if (!FIXNUM_P(vs))
2416  return 0;
2417  n = FIX2LONG(vs);
2418  if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
2419  return 0;
2420  *rof = (int)n;
2421  return 1;
2422  }
2423  }
2424  return 0;
2425 }
2426 
2427 /* date */
2428 
2429 #define valid_sg(sg) \
2430 do {\
2431  if (!c_valid_start_p(sg)) {\
2432  sg = 0;\
2433  rb_warning("invalid start is ignored");\
2434  }\
2435 } while (0)
2436 
2437 static VALUE
2438 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2439 {
2440  double sg = NUM2DBL(argv[1]);
2441  valid_sg(sg);
2442  return argv[0];
2443 }
2444 
2445 #ifndef NDEBUG
2446 static VALUE
2447 date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
2448 {
2449  VALUE vjd, vsg;
2450  VALUE argv2[2];
2451 
2452  rb_scan_args(argc, argv, "11", &vjd, &vsg);
2453 
2454  argv2[0] = vjd;
2455  if (argc < 2)
2456  argv2[1] = DBL2NUM(GREGORIAN);
2457  else
2458  argv2[1] = vsg;
2459 
2460  return valid_jd_sub(2, argv2, klass, 1);
2461 }
2462 #endif
2463 
2464 /*
2465  * call-seq:
2466  * Date.valid_jd?(jd[, start=Date::ITALY]) -> bool
2467  *
2468  * Just returns true. It's nonsense, but is for symmetry.
2469  *
2470  * Date.valid_jd?(2451944) #=> true
2471  *
2472  * See also ::jd.
2473  */
2474 static VALUE
2475 date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
2476 {
2477  VALUE vjd, vsg;
2478  VALUE argv2[2];
2479 
2480  rb_scan_args(argc, argv, "11", &vjd, &vsg);
2481 
2483  argv2[0] = vjd;
2484  if (argc < 2)
2485  argv2[1] = INT2FIX(DEFAULT_SG);
2486  else
2487  argv2[1] = vsg;
2488 
2489  if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
2490  return Qfalse;
2491  return Qtrue;
2492 }
2493 
2494 static VALUE
2495 valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2496 {
2497  VALUE nth, y;
2498  int m, d, ry, rm, rd;
2499  double sg;
2500 
2501  y = argv[0];
2502  m = NUM2INT(argv[1]);
2503  d = NUM2INT(argv[2]);
2504  sg = NUM2DBL(argv[3]);
2505 
2506  valid_sg(sg);
2507 
2508  if (!need_jd && (guess_style(y, sg) < 0)) {
2509  if (!valid_gregorian_p(y, m, d,
2510  &nth, &ry,
2511  &rm, &rd))
2512  return Qnil;
2513  return INT2FIX(0); /* dummy */
2514  }
2515  else {
2516  int rjd, ns;
2517  VALUE rjd2;
2518 
2519  if (!valid_civil_p(y, m, d, sg,
2520  &nth, &ry,
2521  &rm, &rd, &rjd,
2522  &ns))
2523  return Qnil;
2524  if (!need_jd)
2525  return INT2FIX(0); /* dummy */
2526  encode_jd(nth, rjd, &rjd2);
2527  return rjd2;
2528  }
2529 }
2530 
2531 #ifndef NDEBUG
2532 static VALUE
2533 date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
2534 {
2535  VALUE vy, vm, vd, vsg;
2536  VALUE argv2[4];
2537 
2538  rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2539 
2540  argv2[0] = vy;
2541  argv2[1] = vm;
2542  argv2[2] = vd;
2543  if (argc < 4)
2544  argv2[3] = DBL2NUM(GREGORIAN);
2545  else
2546  argv2[3] = vsg;
2547 
2548  return valid_civil_sub(4, argv2, klass, 1);
2549 }
2550 #endif
2551 
2552 /*
2553  * call-seq:
2554  * Date.valid_civil?(year, month, mday[, start=Date::ITALY]) -> bool
2555  * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool
2556  *
2557  * Returns true if the given calendar date is valid, and false if not.
2558  * Valid in this context is whether the arguments passed to this
2559  * method would be accepted by ::new.
2560  *
2561  * Date.valid_date?(2001,2,3) #=> true
2562  * Date.valid_date?(2001,2,29) #=> false
2563  * Date.valid_date?(2001,2,-1) #=> true
2564  *
2565  * See also ::jd and ::civil.
2566  */
2567 static VALUE
2568 date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
2569 {
2570  VALUE vy, vm, vd, vsg;
2571  VALUE argv2[4];
2572 
2573  rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
2574 
2578  argv2[0] = vy;
2579  argv2[1] = vm;
2580  argv2[2] = vd;
2581  if (argc < 4)
2582  argv2[3] = INT2FIX(DEFAULT_SG);
2583  else
2584  argv2[3] = vsg;
2585 
2586  if (NIL_P(valid_civil_sub(4, argv2, klass, 0)))
2587  return Qfalse;
2588  return Qtrue;
2589 }
2590 
2591 static VALUE
2592 valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2593 {
2594  VALUE nth, y;
2595  int d, ry, rd;
2596  double sg;
2597 
2598  y = argv[0];
2599  d = NUM2INT(argv[1]);
2600  sg = NUM2DBL(argv[2]);
2601 
2602  valid_sg(sg);
2603 
2604  {
2605  int rjd, ns;
2606  VALUE rjd2;
2607 
2608  if (!valid_ordinal_p(y, d, sg,
2609  &nth, &ry,
2610  &rd, &rjd,
2611  &ns))
2612  return Qnil;
2613  if (!need_jd)
2614  return INT2FIX(0); /* dummy */
2615  encode_jd(nth, rjd, &rjd2);
2616  return rjd2;
2617  }
2618 }
2619 
2620 #ifndef NDEBUG
2621 static VALUE
2622 date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2623 {
2624  VALUE vy, vd, vsg;
2625  VALUE argv2[3];
2626 
2627  rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2628 
2629  argv2[0] = vy;
2630  argv2[1] = vd;
2631  if (argc < 3)
2632  argv2[2] = DBL2NUM(GREGORIAN);
2633  else
2634  argv2[2] = vsg;
2635 
2636  return valid_ordinal_sub(3, argv2, klass, 1);
2637 }
2638 #endif
2639 
2640 /*
2641  * call-seq:
2642  * Date.valid_ordinal?(year, yday[, start=Date::ITALY]) -> bool
2643  *
2644  * Returns true if the given ordinal date is valid, and false if not.
2645  *
2646  * Date.valid_ordinal?(2001,34) #=> true
2647  * Date.valid_ordinal?(2001,366) #=> false
2648  *
2649  * See also ::jd and ::ordinal.
2650  */
2651 static VALUE
2652 date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
2653 {
2654  VALUE vy, vd, vsg;
2655  VALUE argv2[3];
2656 
2657  rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
2658 
2661  argv2[0] = vy;
2662  argv2[1] = vd;
2663  if (argc < 3)
2664  argv2[2] = INT2FIX(DEFAULT_SG);
2665  else
2666  argv2[2] = vsg;
2667 
2668  if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0)))
2669  return Qfalse;
2670  return Qtrue;
2671 }
2672 
2673 static VALUE
2674 valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2675 {
2676  VALUE nth, y;
2677  int w, d, ry, rw, rd;
2678  double sg;
2679 
2680  y = argv[0];
2681  w = NUM2INT(argv[1]);
2682  d = NUM2INT(argv[2]);
2683  sg = NUM2DBL(argv[3]);
2684 
2685  valid_sg(sg);
2686 
2687  {
2688  int rjd, ns;
2689  VALUE rjd2;
2690 
2691  if (!valid_commercial_p(y, w, d, sg,
2692  &nth, &ry,
2693  &rw, &rd, &rjd,
2694  &ns))
2695  return Qnil;
2696  if (!need_jd)
2697  return INT2FIX(0); /* dummy */
2698  encode_jd(nth, rjd, &rjd2);
2699  return rjd2;
2700  }
2701 }
2702 
2703 #ifndef NDEBUG
2704 static VALUE
2705 date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2706 {
2707  VALUE vy, vw, vd, vsg;
2708  VALUE argv2[4];
2709 
2710  rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2711 
2712  argv2[0] = vy;
2713  argv2[1] = vw;
2714  argv2[2] = vd;
2715  if (argc < 4)
2716  argv2[3] = DBL2NUM(GREGORIAN);
2717  else
2718  argv2[3] = vsg;
2719 
2720  return valid_commercial_sub(4, argv2, klass, 1);
2721 }
2722 #endif
2723 
2724 /*
2725  * call-seq:
2726  * Date.valid_commercial?(cwyear, cweek, cwday[, start=Date::ITALY]) -> bool
2727  *
2728  * Returns true if the given week date is valid, and false if not.
2729  *
2730  * Date.valid_commercial?(2001,5,6) #=> true
2731  * Date.valid_commercial?(2001,5,8) #=> false
2732  *
2733  * See also ::jd and ::commercial.
2734  */
2735 static VALUE
2736 date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
2737 {
2738  VALUE vy, vw, vd, vsg;
2739  VALUE argv2[4];
2740 
2741  rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
2742 
2746  argv2[0] = vy;
2747  argv2[1] = vw;
2748  argv2[2] = vd;
2749  if (argc < 4)
2750  argv2[3] = INT2FIX(DEFAULT_SG);
2751  else
2752  argv2[3] = vsg;
2753 
2754  if (NIL_P(valid_commercial_sub(4, argv2, klass, 0)))
2755  return Qfalse;
2756  return Qtrue;
2757 }
2758 
2759 #ifndef NDEBUG
2760 static VALUE
2761 valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2762 {
2763  VALUE nth, y;
2764  int w, d, f, ry, rw, rd;
2765  double sg;
2766 
2767  y = argv[0];
2768  w = NUM2INT(argv[1]);
2769  d = NUM2INT(argv[2]);
2770  f = NUM2INT(argv[3]);
2771  sg = NUM2DBL(argv[4]);
2772 
2773  valid_sg(sg);
2774 
2775  {
2776  int rjd, ns;
2777  VALUE rjd2;
2778 
2779  if (!valid_weeknum_p(y, w, d, f, sg,
2780  &nth, &ry,
2781  &rw, &rd, &rjd,
2782  &ns))
2783  return Qnil;
2784  if (!need_jd)
2785  return INT2FIX(0); /* dummy */
2786  encode_jd(nth, rjd, &rjd2);
2787  return rjd2;
2788  }
2789 }
2790 
2791 static VALUE
2792 date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
2793 {
2794  VALUE vy, vw, vd, vf, vsg;
2795  VALUE argv2[5];
2796 
2797  rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
2798 
2799  argv2[0] = vy;
2800  argv2[1] = vw;
2801  argv2[2] = vd;
2802  argv2[3] = vf;
2803  if (argc < 5)
2804  argv2[4] = DBL2NUM(GREGORIAN);
2805  else
2806  argv2[4] = vsg;
2807 
2808  return valid_weeknum_sub(5, argv2, klass, 1);
2809 }
2810 
2811 static VALUE
2812 date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
2813 {
2814  VALUE vy, vw, vd, vf, vsg;
2815  VALUE argv2[5];
2816 
2817  rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
2818 
2819  argv2[0] = vy;
2820  argv2[1] = vw;
2821  argv2[2] = vd;
2822  argv2[3] = vf;
2823  if (argc < 5)
2824  argv2[4] = INT2FIX(DEFAULT_SG);
2825  else
2826  argv2[4] = vsg;
2827 
2828  if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0)))
2829  return Qfalse;
2830  return Qtrue;
2831 }
2832 
2833 static VALUE
2834 valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
2835 {
2836  VALUE nth, y;
2837  int m, n, k, ry, rm, rn, rk;
2838  double sg;
2839 
2840  y = argv[0];
2841  m = NUM2INT(argv[1]);
2842  n = NUM2INT(argv[2]);
2843  k = NUM2INT(argv[3]);
2844  sg = NUM2DBL(argv[4]);
2845 
2846  {
2847  int rjd, ns;
2848  VALUE rjd2;
2849 
2850  if (!valid_nth_kday_p(y, m, n, k, sg,
2851  &nth, &ry,
2852  &rm, &rn, &rk, &rjd,
2853  &ns))
2854  return Qnil;
2855  if (!need_jd)
2856  return INT2FIX(0); /* dummy */
2857  encode_jd(nth, rjd, &rjd2);
2858  return rjd2;
2859  }
2860 }
2861 
2862 static VALUE
2863 date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
2864 {
2865  VALUE vy, vm, vn, vk, vsg;
2866  VALUE argv2[5];
2867 
2868  rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
2869 
2870  argv2[0] = vy;
2871  argv2[1] = vm;
2872  argv2[2] = vn;
2873  argv2[3] = vk;
2874  if (argc < 5)
2875  argv2[4] = DBL2NUM(GREGORIAN);
2876  else
2877  argv2[4] = vsg;
2878 
2879  return valid_nth_kday_sub(5, argv2, klass, 1);
2880 }
2881 
2882 static VALUE
2883 date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
2884 {
2885  VALUE vy, vm, vn, vk, vsg;
2886  VALUE argv2[5];
2887 
2888  rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
2889 
2890  argv2[0] = vy;
2891  argv2[1] = vm;
2892  argv2[2] = vn;
2893  argv2[3] = vk;
2894  if (argc < 5)
2895  argv2[4] = INT2FIX(DEFAULT_SG);
2896  else
2897  argv2[4] = vsg;
2898 
2899  if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0)))
2900  return Qfalse;
2901  return Qtrue;
2902 }
2903 
2904 static VALUE
2905 date_s_zone_to_diff(VALUE klass, VALUE str)
2906 {
2907  return date_zone_to_diff(str);
2908 }
2909 #endif
2910 
2911 /*
2912  * call-seq:
2913  * Date.julian_leap?(year) -> bool
2914  *
2915  * Returns true if the given year is a leap year of the proleptic
2916  * Julian calendar.
2917  *
2918  * Date.julian_leap?(1900) #=> true
2919  * Date.julian_leap?(1901) #=> false
2920  */
2921 static VALUE
2922 date_s_julian_leap_p(VALUE klass, VALUE y)
2923 {
2924  VALUE nth;
2925  int ry;
2926 
2927  check_numeric(y, "year");
2928  decode_year(y, +1, &nth, &ry);
2929  return f_boolcast(c_julian_leap_p(ry));
2930 }
2931 
2932 /*
2933  * call-seq:
2934  * Date.gregorian_leap?(year) -> bool
2935  * Date.leap?(year) -> bool
2936  *
2937  * Returns true if the given year is a leap year of the proleptic
2938  * Gregorian calendar.
2939  *
2940  * Date.gregorian_leap?(1900) #=> false
2941  * Date.gregorian_leap?(2000) #=> true
2942  */
2943 static VALUE
2944 date_s_gregorian_leap_p(VALUE klass, VALUE y)
2945 {
2946  VALUE nth;
2947  int ry;
2948 
2949  check_numeric(y, "year");
2950  decode_year(y, -1, &nth, &ry);
2951  return f_boolcast(c_gregorian_leap_p(ry));
2952 }
2953 
2954 static void
2955 d_lite_gc_mark(void *ptr)
2956 {
2957  union DateData *dat = ptr;
2958  if (simple_dat_p(dat))
2959  rb_gc_mark(dat->s.nth);
2960  else {
2961  rb_gc_mark(dat->c.nth);
2962  rb_gc_mark(dat->c.sf);
2963  }
2964 }
2965 
2966 static size_t
2967 d_lite_memsize(const void *ptr)
2968 {
2969  const union DateData *dat = ptr;
2970  return complex_dat_p(dat) ? sizeof(struct ComplexDateData) : sizeof(struct SimpleDateData);
2971 }
2972 
2973 static const rb_data_type_t d_lite_type = {
2974  "Date",
2975  {d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
2976  0, 0,
2978 };
2979 
2980 inline static VALUE
2981 d_simple_new_internal(VALUE klass,
2982  VALUE nth, int jd,
2983  double sg,
2984  int y, int m, int d,
2985  unsigned flags)
2986 {
2987  struct SimpleDateData *dat;
2988  VALUE obj;
2989 
2991  &d_lite_type, dat);
2992  set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
2993 
2994  assert(have_jd_p(dat) || have_civil_p(dat));
2995 
2996  return obj;
2997 }
2998 
2999 inline static VALUE
3000 d_complex_new_internal(VALUE klass,
3001  VALUE nth, int jd,
3002  int df, VALUE sf,
3003  int of, double sg,
3004  int y, int m, int d,
3005  int h, int min, int s,
3006  unsigned flags)
3007 {
3008  struct ComplexDateData *dat;
3009  VALUE obj;
3010 
3012  &d_lite_type, dat);
3013  set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
3014  y, m, d, h, min, s, flags);
3015 
3016  assert(have_jd_p(dat) || have_civil_p(dat));
3017  assert(have_df_p(dat) || have_time_p(dat));
3018 
3019  return obj;
3020 }
3021 
3022 static VALUE
3023 d_lite_s_alloc_simple(VALUE klass)
3024 {
3025  return d_simple_new_internal(klass,
3026  INT2FIX(0), 0,
3027  DEFAULT_SG,
3028  0, 0, 0,
3029  HAVE_JD);
3030 }
3031 
3032 static VALUE
3033 d_lite_s_alloc_complex(VALUE klass)
3034 {
3035  return d_complex_new_internal(klass,
3036  INT2FIX(0), 0,
3037  0, INT2FIX(0),
3038  0, DEFAULT_SG,
3039  0, 0, 0,
3040  0, 0, 0,
3041  HAVE_JD | HAVE_DF);
3042 }
3043 
3044 static VALUE
3045 d_lite_s_alloc(VALUE klass)
3046 {
3047  return d_lite_s_alloc_complex(klass);
3048 }
3049 
3050 static void
3051 old_to_new(VALUE ajd, VALUE of, VALUE sg,
3052  VALUE *rnth, int *rjd, int *rdf, VALUE *rsf,
3053  int *rof, double *rsg)
3054 {
3055  VALUE jd, df, sf, of2, t;
3056 
3057  decode_day(f_add(ajd, half_days_in_day),
3058  &jd, &df, &sf);
3059  t = day_to_sec(of);
3060  of2 = f_round(t);
3061 
3062  if (!f_eqeq_p(of2, t))
3063  rb_warning("fraction of offset is ignored");
3064 
3065  decode_jd(jd, rnth, rjd);
3066 
3067  *rdf = NUM2INT(df);
3068  *rsf = sf;
3069  *rof = NUM2INT(of2);
3070  *rsg = NUM2DBL(sg);
3071 
3072  if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
3073  rb_raise(eDateError, "invalid day fraction");
3074 
3075  if (f_lt_p(*rsf, INT2FIX(0)) ||
3077 
3078  if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
3079  *rof = 0;
3080  rb_warning("invalid offset is ignored");
3081  }
3082 
3083  if (!c_valid_start_p(*rsg)) {
3084  *rsg = DEFAULT_SG;
3085  rb_warning("invalid start is ignored");
3086  }
3087 }
3088 
3089 #ifndef NDEBUG
3090 static VALUE
3091 date_s_new_bang(int argc, VALUE *argv, VALUE klass)
3092 {
3093  VALUE ajd, of, sg, nth, sf;
3094  int jd, df, rof;
3095  double rsg;
3096 
3097  rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
3098 
3099  switch (argc) {
3100  case 0:
3101  ajd = INT2FIX(0);
3102  case 1:
3103  of = INT2FIX(0);
3104  case 2:
3105  sg = INT2FIX(DEFAULT_SG);
3106  }
3107 
3108  old_to_new(ajd, of, sg,
3109  &nth, &jd, &df, &sf, &rof, &rsg);
3110 
3111  if (!df && f_zero_p(sf) && !rof)
3112  return d_simple_new_internal(klass,
3113  nth, jd,
3114  rsg,
3115  0, 0, 0,
3116  HAVE_JD);
3117  else
3118  return d_complex_new_internal(klass,
3119  nth, jd,
3120  df, sf,
3121  rof, rsg,
3122  0, 0, 0,
3123  0, 0, 0,
3124  HAVE_JD | HAVE_DF);
3125 }
3126 #endif
3127 
3128 inline static int
3129 wholenum_p(VALUE x)
3130 {
3131  if (FIXNUM_P(x))
3132  return 1;
3133  switch (TYPE(x)) {
3134  case T_BIGNUM:
3135  return 1;
3136  case T_FLOAT:
3137  {
3138  double d = RFLOAT_VALUE(x);
3139  return round(d) == d;
3140  }
3141  break;
3142  case T_RATIONAL:
3143  {
3144  VALUE den = rb_rational_den(x);
3145  return FIXNUM_P(den) && FIX2LONG(den) == 1;
3146  }
3147  break;
3148  }
3149  return 0;
3150 }
3151 
3152 inline static VALUE
3153 to_integer(VALUE x)
3154 {
3155  if (RB_INTEGER_TYPE_P(x))
3156  return x;
3157  return f_to_i(x);
3158 }
3159 
3160 inline static VALUE
3161 d_trunc(VALUE d, VALUE *fr)
3162 {
3163  VALUE rd;
3164 
3165  if (wholenum_p(d)) {
3166  rd = to_integer(d);
3167  *fr = INT2FIX(0);
3168  }
3169  else {
3170  rd = f_idiv(d, INT2FIX(1));
3171  *fr = f_mod(d, INT2FIX(1));
3172  }
3173  return rd;
3174 }
3175 
3176 #define jd_trunc d_trunc
3177 #define k_trunc d_trunc
3178 
3179 inline static VALUE
3180 h_trunc(VALUE h, VALUE *fr)
3181 {
3182  VALUE rh;
3183 
3184  if (wholenum_p(h)) {
3185  rh = to_integer(h);
3186  *fr = INT2FIX(0);
3187  }
3188  else {
3189  rh = f_idiv(h, INT2FIX(1));
3190  *fr = f_mod(h, INT2FIX(1));
3191  *fr = f_quo(*fr, INT2FIX(24));
3192  }
3193  return rh;
3194 }
3195 
3196 inline static VALUE
3197 min_trunc(VALUE min, VALUE *fr)
3198 {
3199  VALUE rmin;
3200 
3201  if (wholenum_p(min)) {
3202  rmin = to_integer(min);
3203  *fr = INT2FIX(0);
3204  }
3205  else {
3206  rmin = f_idiv(min, INT2FIX(1));
3207  *fr = f_mod(min, INT2FIX(1));
3208  *fr = f_quo(*fr, INT2FIX(1440));
3209  }
3210  return rmin;
3211 }
3212 
3213 inline static VALUE
3214 s_trunc(VALUE s, VALUE *fr)
3215 {
3216  VALUE rs;
3217 
3218  if (wholenum_p(s)) {
3219  rs = to_integer(s);
3220  *fr = INT2FIX(0);
3221  }
3222  else {
3223  rs = f_idiv(s, INT2FIX(1));
3224  *fr = f_mod(s, INT2FIX(1));
3225  *fr = f_quo(*fr, INT2FIX(86400));
3226  }
3227  return rs;
3228 }
3229 
3230 #define num2num_with_frac(s,n) \
3231 do {\
3232  s = s##_trunc(v##s, &fr);\
3233  if (f_nonzero_p(fr)) {\
3234  if (argc > n)\
3235  rb_raise(eDateError, "invalid fraction");\
3236  fr2 = fr;\
3237  }\
3238 } while (0)
3239 
3240 #define num2int_with_frac(s,n) \
3241 do {\
3242  s = NUM2INT(s##_trunc(v##s, &fr));\
3243  if (f_nonzero_p(fr)) {\
3244  if (argc > n)\
3245  rb_raise(eDateError, "invalid fraction");\
3246  fr2 = fr;\
3247  }\
3248 } while (0)
3249 
3250 #define canon24oc() \
3251 do {\
3252  if (rh == 24) {\
3253  rh = 0;\
3254  fr2 = f_add(fr2, INT2FIX(1));\
3255  }\
3256 } while (0)
3257 
3258 #define add_frac() \
3259 do {\
3260  if (f_nonzero_p(fr2))\
3261  ret = d_lite_plus(ret, fr2);\
3262 } while (0)
3263 
3264 #define val2sg(vsg,dsg) \
3265 do {\
3266  dsg = NUM2DBL(vsg);\
3267  if (!c_valid_start_p(dsg)) {\
3268  dsg = DEFAULT_SG;\
3269  rb_warning("invalid start is ignored");\
3270  }\
3271 } while (0)
3272 
3273 static VALUE d_lite_plus(VALUE, VALUE);
3274 
3275 /*
3276  * call-seq:
3277  * Date.jd([jd=0[, start=Date::ITALY]]) -> date
3278  *
3279  * Creates a date object denoting the given chronological Julian day
3280  * number.
3281  *
3282  * Date.jd(2451944) #=> #<Date: 2001-02-03 ...>
3283  * Date.jd(2451945) #=> #<Date: 2001-02-04 ...>
3284  * Date.jd(0) #=> #<Date: -4712-01-01 ...>
3285  *
3286  * See also ::new.
3287  */
3288 static VALUE
3289 date_s_jd(int argc, VALUE *argv, VALUE klass)
3290 {
3291  VALUE vjd, vsg, jd, fr, fr2, ret;
3292  double sg;
3293 
3294  rb_scan_args(argc, argv, "02", &vjd, &vsg);
3295 
3296  jd = INT2FIX(0);
3297  fr2 = INT2FIX(0);
3298  sg = DEFAULT_SG;
3299 
3300  switch (argc) {
3301  case 2:
3302  val2sg(vsg, sg);
3303  case 1:
3304  check_numeric(vjd, "jd");
3305  num2num_with_frac(jd, positive_inf);
3306  }
3307 
3308  {
3309  VALUE nth;
3310  int rjd;
3311 
3312  decode_jd(jd, &nth, &rjd);
3313  ret = d_simple_new_internal(klass,
3314  nth, rjd,
3315  sg,
3316  0, 0, 0,
3317  HAVE_JD);
3318  }
3319  add_frac();
3320  return ret;
3321 }
3322 
3323 /*
3324  * call-seq:
3325  * Date.ordinal([year=-4712[, yday=1[, start=Date::ITALY]]]) -> date
3326  *
3327  * Creates a date object denoting the given ordinal date.
3328  *
3329  * The day of year should be a negative or a positive number (as a
3330  * relative day from the end of year when negative). It should not be
3331  * zero.
3332  *
3333  * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...>
3334  * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...>
3335  * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...>
3336  *
3337  * See also ::jd and ::new.
3338  */
3339 static VALUE
3340 date_s_ordinal(int argc, VALUE *argv, VALUE klass)
3341 {
3342  VALUE vy, vd, vsg, y, fr, fr2, ret;
3343  int d;
3344  double sg;
3345 
3346  rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
3347 
3348  y = INT2FIX(-4712);
3349  d = 1;
3350  fr2 = INT2FIX(0);
3351  sg = DEFAULT_SG;
3352 
3353  switch (argc) {
3354  case 3:
3355  val2sg(vsg, sg);
3356  case 2:
3357  check_numeric(vd, "yday");
3358  num2int_with_frac(d, positive_inf);
3359  case 1:
3360  check_numeric(vy, "year");
3361  y = vy;
3362  }
3363 
3364  {
3365  VALUE nth;
3366  int ry, rd, rjd, ns;
3367 
3368  if (!valid_ordinal_p(y, d, sg,
3369  &nth, &ry,
3370  &rd, &rjd,
3371  &ns))
3372  rb_raise(eDateError, "invalid date");
3373 
3374  ret = d_simple_new_internal(klass,
3375  nth, rjd,
3376  sg,
3377  0, 0, 0,
3378  HAVE_JD);
3379  }
3380  add_frac();
3381  return ret;
3382 }
3383 
3384 /*
3385  * call-seq:
3386  * Date.civil([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
3387  * Date.new([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
3388  *
3389  * Creates a date object denoting the given calendar date.
3390  *
3391  * In this class, BCE years are counted astronomically. Thus, the
3392  * year before the year 1 is the year zero, and the year preceding the
3393  * year zero is the year -1. The month and the day of month should be
3394  * a negative or a positive number (as a relative month/day from the
3395  * end of year/month when negative). They should not be zero.
3396  *
3397  * The last argument should be a Julian day number which denotes the
3398  * day of calendar reform. Date::ITALY (2299161=1582-10-15),
3399  * Date::ENGLAND (2361222=1752-09-14), Date::GREGORIAN (the proleptic
3400  * Gregorian calendar) and Date::JULIAN (the proleptic Julian
3401  * calendar) can be specified as a day of calendar reform.
3402  *
3403  * Date.new(2001) #=> #<Date: 2001-01-01 ...>
3404  * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...>
3405  * Date.new(2001,2,-1) #=> #<Date: 2001-02-28 ...>
3406  *
3407  * See also ::jd.
3408  */
3409 static VALUE
3410 date_s_civil(int argc, VALUE *argv, VALUE klass)
3411 {
3412  return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
3413 }
3414 
3415 static VALUE
3416 date_initialize(int argc, VALUE *argv, VALUE self)
3417 {
3418  VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
3419  int m, d;
3420  double sg;
3421  struct SimpleDateData *dat = rb_check_typeddata(self, &d_lite_type);
3422 
3423  if (!simple_dat_p(dat)) {
3424  rb_raise(rb_eTypeError, "Date expected");
3425  }
3426 
3427  rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
3428 
3429  y = INT2FIX(-4712);
3430  m = 1;
3431  d = 1;
3432  fr2 = INT2FIX(0);
3433  sg = DEFAULT_SG;
3434 
3435  switch (argc) {
3436  case 4:
3437  val2sg(vsg, sg);
3438  case 3:
3439  check_numeric(vd, "day");
3440  num2int_with_frac(d, positive_inf);
3441  case 2:
3442  check_numeric(vm, "month");
3443  m = NUM2INT(vm);
3444  case 1:
3445  check_numeric(vy, "year");
3446  y = vy;
3447  }
3448 
3449  if (guess_style(y, sg) < 0) {
3450  VALUE nth;
3451  int ry, rm, rd;
3452 
3453  if (!valid_gregorian_p(y, m, d,
3454  &nth, &ry,
3455  &rm, &rd))
3456  rb_raise(eDateError, "invalid date");
3457 
3458  set_to_simple(self, dat, nth, 0, sg, ry, rm, rd, HAVE_CIVIL);
3459  }
3460  else {
3461  VALUE nth;
3462  int ry, rm, rd, rjd, ns;
3463 
3464  if (!valid_civil_p(y, m, d, sg,
3465  &nth, &ry,
3466  &rm, &rd, &rjd,
3467  &ns))
3468  rb_raise(eDateError, "invalid date");
3469 
3470  set_to_simple(self, dat, nth, rjd, sg, ry, rm, rd, HAVE_JD | HAVE_CIVIL);
3471  }
3472  ret = self;
3473  add_frac();
3474  return ret;
3475 }
3476 
3477 /*
3478  * call-seq:
3479  * Date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) -> date
3480  *
3481  * Creates a date object denoting the given week date.
3482  *
3483  * The week and the day of week should be a negative or a positive
3484  * number (as a relative week/day from the end of year/week when
3485  * negative). They should not be zero.
3486  *
3487  * Date.commercial(2001) #=> #<Date: 2001-01-01 ...>
3488  * Date.commercial(2002) #=> #<Date: 2001-12-31 ...>
3489  * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...>
3490  *
3491  * See also ::jd and ::new.
3492  */
3493 static VALUE
3494 date_s_commercial(int argc, VALUE *argv, VALUE klass)
3495 {
3496  VALUE vy, vw, vd, vsg, y, fr, fr2, ret;
3497  int w, d;
3498  double sg;
3499 
3500  rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
3501 
3502  y = INT2FIX(-4712);
3503  w = 1;
3504  d = 1;
3505  fr2 = INT2FIX(0);
3506  sg = DEFAULT_SG;
3507 
3508  switch (argc) {
3509  case 4:
3510  val2sg(vsg, sg);
3511  case 3:
3512  check_numeric(vd, "cwday");
3513  num2int_with_frac(d, positive_inf);
3514  case 2:
3515  check_numeric(vw, "cweek");
3516  w = NUM2INT(vw);
3517  case 1:
3518  check_numeric(vy, "year");
3519  y = vy;
3520  }
3521 
3522  {
3523  VALUE nth;
3524  int ry, rw, rd, rjd, ns;
3525 
3526  if (!valid_commercial_p(y, w, d, sg,
3527  &nth, &ry,
3528  &rw, &rd, &rjd,
3529  &ns))
3530  rb_raise(eDateError, "invalid date");
3531 
3532  ret = d_simple_new_internal(klass,
3533  nth, rjd,
3534  sg,
3535  0, 0, 0,
3536  HAVE_JD);
3537  }
3538  add_frac();
3539  return ret;
3540 }
3541 
3542 #ifndef NDEBUG
3543 static VALUE
3544 date_s_weeknum(int argc, VALUE *argv, VALUE klass)
3545 {
3546  VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret;
3547  int w, d, f;
3548  double sg;
3549 
3550  rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
3551 
3552  y = INT2FIX(-4712);
3553  w = 0;
3554  d = 1;
3555  f = 0;
3556  fr2 = INT2FIX(0);
3557  sg = DEFAULT_SG;
3558 
3559  switch (argc) {
3560  case 5:
3561  val2sg(vsg, sg);
3562  case 4:
3563  f = NUM2INT(vf);
3564  case 3:
3565  num2int_with_frac(d, positive_inf);
3566  case 2:
3567  w = NUM2INT(vw);
3568  case 1:
3569  y = vy;
3570  }
3571 
3572  {
3573  VALUE nth;
3574  int ry, rw, rd, rjd, ns;
3575 
3576  if (!valid_weeknum_p(y, w, d, f, sg,
3577  &nth, &ry,
3578  &rw, &rd, &rjd,
3579  &ns))
3580  rb_raise(eDateError, "invalid date");
3581 
3582  ret = d_simple_new_internal(klass,
3583  nth, rjd,
3584  sg,
3585  0, 0, 0,
3586  HAVE_JD);
3587  }
3588  add_frac();
3589  return ret;
3590 }
3591 
3592 static VALUE
3593 date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
3594 {
3595  VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret;
3596  int m, n, k;
3597  double sg;
3598 
3599  rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
3600 
3601  y = INT2FIX(-4712);
3602  m = 1;
3603  n = 1;
3604  k = 1;
3605  fr2 = INT2FIX(0);
3606  sg = DEFAULT_SG;
3607 
3608  switch (argc) {
3609  case 5:
3610  val2sg(vsg, sg);
3611  case 4:
3612  num2int_with_frac(k, positive_inf);
3613  case 3:
3614  n = NUM2INT(vn);
3615  case 2:
3616  m = NUM2INT(vm);
3617  case 1:
3618  y = vy;
3619  }
3620 
3621  {
3622  VALUE nth;
3623  int ry, rm, rn, rk, rjd, ns;
3624 
3625  if (!valid_nth_kday_p(y, m, n, k, sg,
3626  &nth, &ry,
3627  &rm, &rn, &rk, &rjd,
3628  &ns))
3629  rb_raise(eDateError, "invalid date");
3630 
3631  ret = d_simple_new_internal(klass,
3632  nth, rjd,
3633  sg,
3634  0, 0, 0,
3635  HAVE_JD);
3636  }
3637  add_frac();
3638  return ret;
3639 }
3640 #endif
3641 
3642 #if !defined(HAVE_GMTIME_R)
3643 static struct tm*
3644 gmtime_r(const time_t *t, struct tm *tm)
3645 {
3646  auto struct tm *tmp = gmtime(t);
3647  if (tmp)
3648  *tm = *tmp;
3649  return tmp;
3650 }
3651 
3652 static struct tm*
3653 localtime_r(const time_t *t, struct tm *tm)
3654 {
3655  auto struct tm *tmp = localtime(t);
3656  if (tmp)
3657  *tm = *tmp;
3658  return tmp;
3659 }
3660 #endif
3661 
3662 static void set_sg(union DateData *, double);
3663 
3664 /*
3665  * call-seq:
3666  * Date.today([start=Date::ITALY]) -> date
3667  *
3668  * Creates a date object denoting the present day.
3669  *
3670  * Date.today #=> #<Date: 2011-06-11 ...>
3671  */
3672 static VALUE
3673 date_s_today(int argc, VALUE *argv, VALUE klass)
3674 {
3675  VALUE vsg, nth, ret;
3676  double sg;
3677  time_t t;
3678  struct tm tm;
3679  int y, ry, m, d;
3680 
3681  rb_scan_args(argc, argv, "01", &vsg);
3682 
3683  if (argc < 1)
3684  sg = DEFAULT_SG;
3685  else
3686  val2sg(vsg, sg);
3687 
3688  if (time(&t) == -1)
3689  rb_sys_fail("time");
3690  tzset();
3691  if (!localtime_r(&t, &tm))
3692  rb_sys_fail("localtime");
3693 
3694  y = tm.tm_year + 1900;
3695  m = tm.tm_mon + 1;
3696  d = tm.tm_mday;
3697 
3698  decode_year(INT2FIX(y), -1, &nth, &ry);
3699 
3700  ret = d_simple_new_internal(klass,
3701  nth, 0,
3702  GREGORIAN,
3703  ry, m, d,
3704  HAVE_CIVIL);
3705  {
3706  get_d1(ret);
3707  set_sg(dat, sg);
3708  }
3709  return ret;
3710 }
3711 
3712 #define set_hash0(k,v) rb_hash_aset(hash, k, v)
3713 #define ref_hash0(k) rb_hash_aref(hash, k)
3714 #define del_hash0(k) rb_hash_delete(hash, k)
3715 
3716 #define sym(x) ID2SYM(rb_intern(x""))
3717 
3718 #define set_hash(k,v) set_hash0(sym(k), v)
3719 #define ref_hash(k) ref_hash0(sym(k))
3720 #define del_hash(k) del_hash0(sym(k))
3721 
3722 static VALUE
3723 rt_rewrite_frags(VALUE hash)
3724 {
3725  VALUE seconds;
3726 
3727  seconds = del_hash("seconds");
3728  if (!NIL_P(seconds)) {
3729  VALUE offset, d, h, min, s, fr;
3730 
3731  offset = ref_hash("offset");
3732  if (!NIL_P(offset))
3733  seconds = f_add(seconds, offset);
3734 
3735  d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS));
3736  fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS));
3737 
3738  h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS));
3739  fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS));
3740 
3741  min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS));
3742  fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS));
3743 
3744  s = f_idiv(fr, INT2FIX(1));
3745  fr = f_mod(fr, INT2FIX(1));
3746 
3747  set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d));
3748  set_hash("hour", h);
3749  set_hash("min", min);
3750  set_hash("sec", s);
3751  set_hash("sec_fraction", fr);
3752  }
3753  return hash;
3754 }
3755 
3756 static VALUE d_lite_year(VALUE);
3757 static VALUE d_lite_wday(VALUE);
3758 static VALUE d_lite_jd(VALUE);
3759 
3760 static VALUE
3761 rt_complete_frags(VALUE klass, VALUE hash)
3762 {
3763  static VALUE tab = Qnil;
3764  int g;
3765  long e;
3766  VALUE k, a, d;
3767 
3768  if (NIL_P(tab)) {
3769  tab = rb_ary_new3(11,
3770  rb_ary_new3(2,
3771  sym("time"),
3772  rb_ary_new3(3,
3773  sym("hour"),
3774  sym("min"),
3775  sym("sec"))),
3776  rb_ary_new3(2,
3777  Qnil,
3778  rb_ary_new3(1,
3779  sym("jd"))),
3780  rb_ary_new3(2,
3781  sym("ordinal"),
3782  rb_ary_new3(5,
3783  sym("year"),
3784  sym("yday"),
3785  sym("hour"),
3786  sym("min"),
3787  sym("sec"))),
3788  rb_ary_new3(2,
3789  sym("civil"),
3790  rb_ary_new3(6,
3791  sym("year"),
3792  sym("mon"),
3793  sym("mday"),
3794  sym("hour"),
3795  sym("min"),
3796  sym("sec"))),
3797  rb_ary_new3(2,
3798  sym("commercial"),
3799  rb_ary_new3(6,
3800  sym("cwyear"),
3801  sym("cweek"),
3802  sym("cwday"),
3803  sym("hour"),
3804  sym("min"),
3805  sym("sec"))),
3806  rb_ary_new3(2,
3807  sym("wday"),
3808  rb_ary_new3(4,
3809  sym("wday"),
3810  sym("hour"),
3811  sym("min"),
3812  sym("sec"))),
3813  rb_ary_new3(2,
3814  sym("wnum0"),
3815  rb_ary_new3(6,
3816  sym("year"),
3817  sym("wnum0"),
3818  sym("wday"),
3819  sym("hour"),
3820  sym("min"),
3821  sym("sec"))),
3822  rb_ary_new3(2,
3823  sym("wnum1"),
3824  rb_ary_new3(6,
3825  sym("year"),
3826  sym("wnum1"),
3827  sym("wday"),
3828  sym("hour"),
3829  sym("min"),
3830  sym("sec"))),
3831  rb_ary_new3(2,
3832  Qnil,
3833  rb_ary_new3(6,
3834  sym("cwyear"),
3835  sym("cweek"),
3836  sym("wday"),
3837  sym("hour"),
3838  sym("min"),
3839  sym("sec"))),
3840  rb_ary_new3(2,
3841  Qnil,
3842  rb_ary_new3(6,
3843  sym("year"),
3844  sym("wnum0"),
3845  sym("cwday"),
3846  sym("hour"),
3847  sym("min"),
3848  sym("sec"))),
3849  rb_ary_new3(2,
3850  Qnil,
3851  rb_ary_new3(6,
3852  sym("year"),
3853  sym("wnum1"),
3854  sym("cwday"),
3855  sym("hour"),
3856  sym("min"),
3857  sym("sec"))));
3859  }
3860 
3861  {
3862  long i, eno = 0, idx = 0;
3863 
3864  for (i = 0; i < RARRAY_LEN(tab); i++) {
3865  VALUE x, a;
3866 
3867  x = RARRAY_AREF(tab, i);
3868  a = RARRAY_AREF(x, 1);
3869 
3870  {
3871  long j, n = 0;
3872 
3873  for (j = 0; j < RARRAY_LEN(a); j++)
3874  if (!NIL_P(ref_hash0(RARRAY_AREF(a, j))))
3875  n++;
3876  if (n > eno) {
3877  eno = n;
3878  idx = i;
3879  }
3880  }
3881  }
3882  if (eno == 0)
3883  g = 0;
3884  else {
3885  g = 1;
3886  k = RARRAY_AREF(RARRAY_AREF(tab, idx), 0);
3887  a = RARRAY_AREF(RARRAY_AREF(tab, idx), 1);
3888  e = eno;
3889  }
3890  }
3891 
3892  d = Qnil;
3893 
3894  if (g && !NIL_P(k) && (RARRAY_LEN(a) - e)) {
3895  if (k == sym("ordinal")) {
3896  if (NIL_P(ref_hash("year"))) {
3897  if (NIL_P(d))
3898  d = date_s_today(0, (VALUE *)0, cDate);
3899  set_hash("year", d_lite_year(d));
3900  }
3901  if (NIL_P(ref_hash("yday")))
3902  set_hash("yday", INT2FIX(1));
3903  }
3904  else if (k == sym("civil")) {
3905  long i;
3906 
3907  for (i = 0; i < RARRAY_LEN(a); i++) {
3908  VALUE e = RARRAY_AREF(a, i);
3909 
3910  if (!NIL_P(ref_hash0(e)))
3911  break;
3912  if (NIL_P(d))
3913  d = date_s_today(0, (VALUE *)0, cDate);
3914  set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3915  }
3916  if (NIL_P(ref_hash("mon")))
3917  set_hash("mon", INT2FIX(1));
3918  if (NIL_P(ref_hash("mday")))
3919  set_hash("mday", INT2FIX(1));
3920  }
3921  else if (k == sym("commercial")) {
3922  long i;
3923 
3924  for (i = 0; i < RARRAY_LEN(a); i++) {
3925  VALUE e = RARRAY_AREF(a, i);
3926 
3927  if (!NIL_P(ref_hash0(e)))
3928  break;
3929  if (NIL_P(d))
3930  d = date_s_today(0, (VALUE *)0, cDate);
3931  set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3932  }
3933  if (NIL_P(ref_hash("cweek")))
3934  set_hash("cweek", INT2FIX(1));
3935  if (NIL_P(ref_hash("cwday")))
3936  set_hash("cwday", INT2FIX(1));
3937  }
3938  else if (k == sym("wday")) {
3939  if (NIL_P(d))
3940  d = date_s_today(0, (VALUE *)0, cDate);
3941  set_hash("jd", d_lite_jd(f_add(f_sub(d,
3942  d_lite_wday(d)),
3943  ref_hash("wday"))));
3944  }
3945  else if (k == sym("wnum0")) {
3946  long i;
3947 
3948  for (i = 0; i < RARRAY_LEN(a); i++) {
3949  VALUE e = RARRAY_AREF(a, i);
3950 
3951  if (!NIL_P(ref_hash0(e)))
3952  break;
3953  if (NIL_P(d))
3954  d = date_s_today(0, (VALUE *)0, cDate);
3955  set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3956  }
3957  if (NIL_P(ref_hash("wnum0")))
3958  set_hash("wnum0", INT2FIX(0));
3959  if (NIL_P(ref_hash("wday")))
3960  set_hash("wday", INT2FIX(0));
3961  }
3962  else if (k == sym("wnum1")) {
3963  long i;
3964 
3965  for (i = 0; i < RARRAY_LEN(a); i++) {
3966  VALUE e = RARRAY_AREF(a, i);
3967 
3968  if (!NIL_P(ref_hash0(e)))
3969  break;
3970  if (NIL_P(d))
3971  d = date_s_today(0, (VALUE *)0, cDate);
3972  set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
3973  }
3974  if (NIL_P(ref_hash("wnum1")))
3975  set_hash("wnum1", INT2FIX(0));
3976  if (NIL_P(ref_hash("wday")))
3977  set_hash("wday", INT2FIX(1));
3978  }
3979  }
3980 
3981  if (g && k == sym("time")) {
3982  if (f_le_p(klass, cDateTime)) {
3983  if (NIL_P(d))
3984  d = date_s_today(0, (VALUE *)0, cDate);
3985  if (NIL_P(ref_hash("jd")))
3986  set_hash("jd", d_lite_jd(d));
3987  }
3988  }
3989 
3990  if (NIL_P(ref_hash("hour")))
3991  set_hash("hour", INT2FIX(0));
3992  if (NIL_P(ref_hash("min")))
3993  set_hash("min", INT2FIX(0));
3994  if (NIL_P(ref_hash("sec")))
3995  set_hash("sec", INT2FIX(0));
3996  else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
3997  set_hash("sec", INT2FIX(59));
3998 
3999  return hash;
4000 }
4001 
4002 static VALUE
4003 rt__valid_jd_p(VALUE jd, VALUE sg)
4004 {
4005  return jd;
4006 }
4007 
4008 static VALUE
4009 rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
4010 {
4011  VALUE nth, rjd2;
4012  int ry, rd, rjd, ns;
4013 
4014  if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg),
4015  &nth, &ry,
4016  &rd, &rjd,
4017  &ns))
4018  return Qnil;
4019  encode_jd(nth, rjd, &rjd2);
4020  return rjd2;
4021 }
4022 
4023 static VALUE
4024 rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
4025 {
4026  VALUE nth, rjd2;
4027  int ry, rm, rd, rjd, ns;
4028 
4029  if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg),
4030  &nth, &ry,
4031  &rm, &rd, &rjd,
4032  &ns))
4033  return Qnil;
4034  encode_jd(nth, rjd, &rjd2);
4035  return rjd2;
4036 }
4037 
4038 static VALUE
4039 rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
4040 {
4041  VALUE nth, rjd2;
4042  int ry, rw, rd, rjd, ns;
4043 
4044  if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg),
4045  &nth, &ry,
4046  &rw, &rd, &rjd,
4047  &ns))
4048  return Qnil;
4049  encode_jd(nth, rjd, &rjd2);
4050  return rjd2;
4051 }
4052 
4053 static VALUE
4054 rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
4055 {
4056  VALUE nth, rjd2;
4057  int ry, rw, rd, rjd, ns;
4058 
4059  if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg),
4060  &nth, &ry,
4061  &rw, &rd, &rjd,
4062  &ns))
4063  return Qnil;
4064  encode_jd(nth, rjd, &rjd2);
4065  return rjd2;
4066 }
4067 
4068 static VALUE
4069 rt__valid_date_frags_p(VALUE hash, VALUE sg)
4070 {
4071  {
4072  VALUE vjd;
4073 
4074  if (!NIL_P(vjd = ref_hash("jd"))) {
4075  VALUE jd = rt__valid_jd_p(vjd, sg);
4076  if (!NIL_P(jd))
4077  return jd;
4078  }
4079  }
4080 
4081  {
4082  VALUE year, yday;
4083 
4084  if (!NIL_P(yday = ref_hash("yday")) &&
4085  !NIL_P(year = ref_hash("year"))) {
4086  VALUE jd = rt__valid_ordinal_p(year, yday, sg);
4087  if (!NIL_P(jd))
4088  return jd;
4089  }
4090  }
4091 
4092  {
4093  VALUE year, mon, mday;
4094 
4095  if (!NIL_P(mday = ref_hash("mday")) &&
4096  !NIL_P(mon = ref_hash("mon")) &&
4097  !NIL_P(year = ref_hash("year"))) {
4098  VALUE jd = rt__valid_civil_p(year, mon, mday, sg);
4099  if (!NIL_P(jd))
4100  return jd;
4101  }
4102  }
4103 
4104  {
4105  VALUE year, week, wday;
4106 
4107  wday = ref_hash("cwday");
4108  if (NIL_P(wday)) {
4109  wday = ref_hash("wday");
4110  if (!NIL_P(wday))
4111  if (f_zero_p(wday))
4112  wday = INT2FIX(7);
4113  }
4114 
4115  if (!NIL_P(wday) &&
4116  !NIL_P(week = ref_hash("cweek")) &&
4117  !NIL_P(year = ref_hash("cwyear"))) {
4118  VALUE jd = rt__valid_commercial_p(year, week, wday, sg);
4119  if (!NIL_P(jd))
4120  return jd;
4121  }
4122  }
4123 
4124  {
4125  VALUE year, week, wday;
4126 
4127  wday = ref_hash("wday");
4128  if (NIL_P(wday)) {
4129  wday = ref_hash("cwday");
4130  if (!NIL_P(wday))
4131  if (f_eqeq_p(wday, INT2FIX(7)))
4132  wday = INT2FIX(0);
4133  }
4134 
4135  if (!NIL_P(wday) &&
4136  !NIL_P(week = ref_hash("wnum0")) &&
4137  !NIL_P(year = ref_hash("year"))) {
4138  VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg);
4139  if (!NIL_P(jd))
4140  return jd;
4141  }
4142  }
4143 
4144  {
4145  VALUE year, week, wday;
4146 
4147  wday = ref_hash("wday");
4148  if (NIL_P(wday))
4149  wday = ref_hash("cwday");
4150  if (!NIL_P(wday))
4151  wday = f_mod(f_sub(wday, INT2FIX(1)),
4152  INT2FIX(7));
4153 
4154  if (!NIL_P(wday) &&
4155  !NIL_P(week = ref_hash("wnum1")) &&
4156  !NIL_P(year = ref_hash("year"))) {
4157  VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg);
4158  if (!NIL_P(jd))
4159  return jd;
4160  }
4161  }
4162  return Qnil;
4163 }
4164 
4165 static VALUE
4166 d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
4167 {
4168  VALUE jd;
4169 
4170  if (!c_valid_start_p(NUM2DBL(sg))) {
4171  sg = INT2FIX(DEFAULT_SG);
4172  rb_warning("invalid start is ignored");
4173  }
4174 
4175  if (NIL_P(hash))
4176  rb_raise(eDateError, "invalid date");
4177 
4178  if (NIL_P(ref_hash("jd")) &&
4179  NIL_P(ref_hash("yday")) &&
4180  !NIL_P(ref_hash("year")) &&
4181  !NIL_P(ref_hash("mon")) &&
4182  !NIL_P(ref_hash("mday")))
4183  jd = rt__valid_civil_p(ref_hash("year"),
4184  ref_hash("mon"),
4185  ref_hash("mday"), sg);
4186  else {
4187  hash = rt_rewrite_frags(hash);
4188  hash = rt_complete_frags(klass, hash);
4189  jd = rt__valid_date_frags_p(hash, sg);
4190  }
4191 
4192  if (NIL_P(jd))
4193  rb_raise(eDateError, "invalid date");
4194  {
4195  VALUE nth;
4196  int rjd;
4197 
4198  decode_jd(jd, &nth, &rjd);
4199  return d_simple_new_internal(klass,
4200  nth, rjd,
4201  NUM2DBL(sg),
4202  0, 0, 0,
4203  HAVE_JD);
4204  }
4205 }
4206 
4207 VALUE date__strptime(const char *str, size_t slen,
4208  const char *fmt, size_t flen, VALUE hash);
4209 
4210 static VALUE
4211 date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
4212  const char *default_fmt)
4213 {
4214  VALUE vstr, vfmt, hash;
4215  const char *str, *fmt;
4216  size_t slen, flen;
4217 
4218  rb_scan_args(argc, argv, "11", &vstr, &vfmt);
4219 
4220  StringValue(vstr);
4221  if (!rb_enc_str_asciicompat_p(vstr))
4223  "string should have ASCII compatible encoding");
4224  str = RSTRING_PTR(vstr);
4225  slen = RSTRING_LEN(vstr);
4226  if (argc < 2) {
4227  fmt = default_fmt;
4228  flen = strlen(default_fmt);
4229  }
4230  else {
4231  StringValue(vfmt);
4232  if (!rb_enc_str_asciicompat_p(vfmt))
4234  "format should have ASCII compatible encoding");
4235  fmt = RSTRING_PTR(vfmt);
4236  flen = RSTRING_LEN(vfmt);
4237  }
4238  hash = rb_hash_new();
4239  if (NIL_P(date__strptime(str, slen, fmt, flen, hash)))
4240  return Qnil;
4241 
4242  {
4243  VALUE zone = ref_hash("zone");
4244  VALUE left = ref_hash("leftover");
4245 
4246  if (!NIL_P(zone)) {
4247  rb_enc_copy(zone, vstr);
4248  set_hash("zone", zone);
4249  }
4250  if (!NIL_P(left)) {
4251  rb_enc_copy(left, vstr);
4252  set_hash("leftover", left);
4253  }
4254  }
4255 
4256  return hash;
4257 }
4258 
4259 /*
4260  * call-seq:
4261  * Date._strptime(string[, format='%F']) -> hash
4262  *
4263  * Parses the given representation of date and time with the given
4264  * template, and returns a hash of parsed elements. _strptime does
4265  * not support specification of flags and width unlike strftime.
4266  *
4267  * Date._strptime('2001-02-03', '%Y-%m-%d')
4268  * #=> {:year=>2001, :mon=>2, :mday=>3}
4269  *
4270  * See also strptime(3) and #strftime.
4271  */
4272 static VALUE
4273 date_s__strptime(int argc, VALUE *argv, VALUE klass)
4274 {
4275  return date_s__strptime_internal(argc, argv, klass, "%F");
4276 }
4277 
4278 /*
4279  * call-seq:
4280  * Date.strptime([string='-4712-01-01'[, format='%F'[, start=Date::ITALY]]]) -> date
4281  *
4282  * Parses the given representation of date and time with the given
4283  * template, and creates a date object. strptime does not support
4284  * specification of flags and width unlike strftime.
4285  *
4286  * Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...>
4287  * Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...>
4288  * Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...>
4289  * Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...>
4290  * Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...>
4291  * Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...>
4292  * Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...>
4293  *
4294  * See also strptime(3) and #strftime.
4295  */
4296 static VALUE
4297 date_s_strptime(int argc, VALUE *argv, VALUE klass)
4298 {
4299  VALUE str, fmt, sg;
4300 
4301  rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
4302 
4303  switch (argc) {
4304  case 0:
4305  str = rb_str_new2("-4712-01-01");
4306  case 1:
4307  fmt = rb_str_new2("%F");
4308  case 2:
4309  sg = INT2FIX(DEFAULT_SG);
4310  }
4311 
4312  {
4313  VALUE argv2[2], hash;
4314 
4315  argv2[0] = str;
4316  argv2[1] = fmt;
4317  hash = date_s__strptime(2, argv2, klass);
4318  return d_new_by_frags(klass, hash, sg);
4319  }
4320 }
4321 
4323 
4324 static VALUE
4325 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
4326 {
4327  VALUE vstr, vcomp, hash;
4328 
4329  rb_scan_args(argc, argv, "11", &vstr, &vcomp);
4330  StringValue(vstr);
4331  if (!rb_enc_str_asciicompat_p(vstr))
4333  "string should have ASCII compatible encoding");
4334  if (argc < 2)
4335  vcomp = Qtrue;
4336 
4337  hash = date__parse(vstr, vcomp);
4338 
4339  return hash;
4340 }
4341 
4342 /*
4343  * call-seq:
4344  * Date._parse(string[, comp=true]) -> hash
4345  *
4346  * Parses the given representation of date and time, and returns a
4347  * hash of parsed elements. This method does not function as a
4348  * validator.
4349  *
4350  * If the optional second argument is true and the detected year is in
4351  * the range "00" to "99", considers the year a 2-digit form and makes
4352  * it full.
4353  *
4354  * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3}
4355  */
4356 static VALUE
4357 date_s__parse(int argc, VALUE *argv, VALUE klass)
4358 {
4359  return date_s__parse_internal(argc, argv, klass);
4360 }
4361 
4362 /*
4363  * call-seq:
4364  * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date
4365  *
4366  * Parses the given representation of date and time, and creates a
4367  * date object. This method does not function as a validator.
4368  *
4369  * If the optional second argument is true and the detected year is in
4370  * the range "00" to "99", considers the year a 2-digit form and makes
4371  * it full.
4372  *
4373  * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
4374  * Date.parse('20010203') #=> #<Date: 2001-02-03 ...>
4375  * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...>
4376  */
4377 static VALUE
4378 date_s_parse(int argc, VALUE *argv, VALUE klass)
4379 {
4380  VALUE str, comp, sg;
4381 
4382  rb_scan_args(argc, argv, "03", &str, &comp, &sg);
4383 
4384  switch (argc) {
4385  case 0:
4386  str = rb_str_new2("-4712-01-01");
4387  case 1:
4388  comp = Qtrue;
4389  case 2:
4390  sg = INT2FIX(DEFAULT_SG);
4391  }
4392 
4393  {
4394  VALUE argv2[2], hash;
4395 
4396  argv2[0] = str;
4397  argv2[1] = comp;
4398  hash = date_s__parse(2, argv2, klass);
4399  return d_new_by_frags(klass, hash, sg);
4400  }
4401 }
4402 
4409 
4410 /*
4411  * call-seq:
4412  * Date._iso8601(string) -> hash
4413  *
4414  * Returns a hash of parsed elements.
4415  */
4416 static VALUE
4417 date_s__iso8601(VALUE klass, VALUE str)
4418 {
4419  return date__iso8601(str);
4420 }
4421 
4422 /*
4423  * call-seq:
4424  * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date
4425  *
4426  * Creates a new Date object by parsing from a string according to
4427  * some typical ISO 8601 formats.
4428  *
4429  * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...>
4430  * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...>
4431  * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...>
4432  */
4433 static VALUE
4434 date_s_iso8601(int argc, VALUE *argv, VALUE klass)
4435 {
4436  VALUE str, sg;
4437 
4438  rb_scan_args(argc, argv, "02", &str, &sg);
4439 
4440  switch (argc) {
4441  case 0:
4442  str = rb_str_new2("-4712-01-01");
4443  case 1:
4444  sg = INT2FIX(DEFAULT_SG);
4445  }
4446 
4447  {
4448  VALUE hash = date_s__iso8601(klass, str);
4449  return d_new_by_frags(klass, hash, sg);
4450  }
4451 }
4452 
4453 /*
4454  * call-seq:
4455  * Date._rfc3339(string) -> hash
4456  *
4457  * Returns a hash of parsed elements.
4458  */
4459 static VALUE
4460 date_s__rfc3339(VALUE klass, VALUE str)
4461 {
4462  return date__rfc3339(str);
4463 }
4464 
4465 /*
4466  * call-seq:
4467  * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date
4468  *
4469  * Creates a new Date object by parsing from a string according to
4470  * some typical RFC 3339 formats.
4471  *
4472  * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
4473  */
4474 static VALUE
4475 date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
4476 {
4477  VALUE str, sg;
4478 
4479  rb_scan_args(argc, argv, "02", &str, &sg);
4480 
4481  switch (argc) {
4482  case 0:
4483  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
4484  case 1:
4485  sg = INT2FIX(DEFAULT_SG);
4486  }
4487 
4488  {
4489  VALUE hash = date_s__rfc3339(klass, str);
4490  return d_new_by_frags(klass, hash, sg);
4491  }
4492 }
4493 
4494 /*
4495  * call-seq:
4496  * Date._xmlschema(string) -> hash
4497  *
4498  * Returns a hash of parsed elements.
4499  */
4500 static VALUE
4501 date_s__xmlschema(VALUE klass, VALUE str)
4502 {
4503  return date__xmlschema(str);
4504 }
4505 
4506 /*
4507  * call-seq:
4508  * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date
4509  *
4510  * Creates a new Date object by parsing from a string according to
4511  * some typical XML Schema formats.
4512  *
4513  * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...>
4514  */
4515 static VALUE
4516 date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
4517 {
4518  VALUE str, sg;
4519 
4520  rb_scan_args(argc, argv, "02", &str, &sg);
4521 
4522  switch (argc) {
4523  case 0:
4524  str = rb_str_new2("-4712-01-01");
4525  case 1:
4526  sg = INT2FIX(DEFAULT_SG);
4527  }
4528 
4529  {
4530  VALUE hash = date_s__xmlschema(klass, str);
4531  return d_new_by_frags(klass, hash, sg);
4532  }
4533 }
4534 
4535 /*
4536  * call-seq:
4537  * Date._rfc2822(string) -> hash
4538  * Date._rfc822(string) -> hash
4539  *
4540  * Returns a hash of parsed elements.
4541  */
4542 static VALUE
4543 date_s__rfc2822(VALUE klass, VALUE str)
4544 {
4545  return date__rfc2822(str);
4546 }
4547 
4548 /*
4549  * call-seq:
4550  * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4551  * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
4552  *
4553  * Creates a new Date object by parsing from a string according to
4554  * some typical RFC 2822 formats.
4555  *
4556  * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
4557  * #=> #<Date: 2001-02-03 ...>
4558  */
4559 static VALUE
4560 date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
4561 {
4562  VALUE str, sg;
4563 
4564  rb_scan_args(argc, argv, "02", &str, &sg);
4565 
4566  switch (argc) {
4567  case 0:
4568  str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
4569  case 1:
4570  sg = INT2FIX(DEFAULT_SG);
4571  }
4572 
4573  {
4574  VALUE hash = date_s__rfc2822(klass, str);
4575  return d_new_by_frags(klass, hash, sg);
4576  }
4577 }
4578 
4579 /*
4580  * call-seq:
4581  * Date._httpdate(string) -> hash
4582  *
4583  * Returns a hash of parsed elements.
4584  */
4585 static VALUE
4586 date_s__httpdate(VALUE klass, VALUE str)
4587 {
4588  return date__httpdate(str);
4589 }
4590 
4591 /*
4592  * call-seq:
4593  * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date
4594  *
4595  * Creates a new Date object by parsing from a string according to
4596  * some RFC 2616 format.
4597  *
4598  * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
4599  * #=> #<Date: 2001-02-03 ...>
4600  */
4601 static VALUE
4602 date_s_httpdate(int argc, VALUE *argv, VALUE klass)
4603 {
4604  VALUE str, sg;
4605 
4606  rb_scan_args(argc, argv, "02", &str, &sg);
4607 
4608  switch (argc) {
4609  case 0:
4610  str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
4611  case 1:
4612  sg = INT2FIX(DEFAULT_SG);
4613  }
4614 
4615  {
4616  VALUE hash = date_s__httpdate(klass, str);
4617  return d_new_by_frags(klass, hash, sg);
4618  }
4619 }
4620 
4621 /*
4622  * call-seq:
4623  * Date._jisx0301(string) -> hash
4624  *
4625  * Returns a hash of parsed elements.
4626  */
4627 static VALUE
4628 date_s__jisx0301(VALUE klass, VALUE str)
4629 {
4630  return date__jisx0301(str);
4631 }
4632 
4633 /*
4634  * call-seq:
4635  * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date
4636  *
4637  * Creates a new Date object by parsing from a string according to
4638  * some typical JIS X 0301 formats.
4639  *
4640  * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
4641  *
4642  * For no-era year, legacy format, Heisei is assumed.
4643  *
4644  * Date.jisx0301('13.02.03') #=> #<Date: 2001-02-03 ...>
4645  */
4646 static VALUE
4647 date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
4648 {
4649  VALUE str, sg;
4650 
4651  rb_scan_args(argc, argv, "02", &str, &sg);
4652 
4653  switch (argc) {
4654  case 0:
4655  str = rb_str_new2("-4712-01-01");
4656  case 1:
4657  sg = INT2FIX(DEFAULT_SG);
4658  }
4659 
4660  {
4661  VALUE hash = date_s__jisx0301(klass, str);
4662  return d_new_by_frags(klass, hash, sg);
4663  }
4664 }
4665 
4666 static VALUE
4667 dup_obj(VALUE self)
4668 {
4669  get_d1a(self);
4670 
4671  if (simple_dat_p(adat)) {
4672  VALUE new = d_lite_s_alloc_simple(rb_obj_class(self));
4673  {
4674  get_d1b(new);
4675  bdat->s = adat->s;
4676  RB_OBJ_WRITTEN(new, Qundef, bdat->s.nth);
4677  return new;
4678  }
4679  }
4680  else {
4681  VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4682  {
4683  get_d1b(new);
4684  bdat->c = adat->c;
4685  RB_OBJ_WRITTEN(new, Qundef, bdat->c.nth);
4686  RB_OBJ_WRITTEN(new, Qundef, bdat->c.sf);
4687  return new;
4688  }
4689  }
4690 }
4691 
4692 static VALUE
4693 dup_obj_as_complex(VALUE self)
4694 {
4695  get_d1a(self);
4696 
4697  if (simple_dat_p(adat)) {
4698  VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4699  {
4700  get_d1b(new);
4701  copy_simple_to_complex(new, &bdat->c, &adat->s);
4702  bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
4703  return new;
4704  }
4705  }
4706  else {
4707  VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
4708  {
4709  get_d1b(new);
4710  bdat->c = adat->c;
4711  RB_OBJ_WRITTEN(new, Qundef, bdat->c.nth);
4712  RB_OBJ_WRITTEN(new, Qundef, bdat->c.sf);
4713  return new;
4714  }
4715  }
4716 }
4717 
4718 #define val2off(vof,iof) \
4719 do {\
4720  if (!offset_to_sec(vof, &iof)) {\
4721  iof = 0;\
4722  rb_warning("invalid offset is ignored");\
4723  }\
4724 } while (0)
4725 
4726 #if 0
4727 static VALUE
4728 d_lite_initialize(int argc, VALUE *argv, VALUE self)
4729 {
4730  VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
4731  int df, of;
4732  double sg;
4733 
4734  rb_check_frozen(self);
4735 
4736  rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
4737 
4738  jd = INT2FIX(0);
4739  df = 0;
4740  sf = INT2FIX(0);
4741  of = 0;
4742  sg = DEFAULT_SG;
4743 
4744  switch (argc) {
4745  case 5:
4746  val2sg(vsg, sg);
4747  case 4:
4748  val2off(vof, of);
4749  case 3:
4750  sf = vsf;
4751  if (f_lt_p(sf, INT2FIX(0)) ||
4753  rb_raise(eDateError, "invalid second fraction");
4754  case 2:
4755  df = NUM2INT(vdf);
4756  if (df < 0 || df >= DAY_IN_SECONDS)
4757  rb_raise(eDateError, "invalid day fraction");
4758  case 1:
4759  jd = vjd;
4760  }
4761 
4762  {
4763  VALUE nth;
4764  int rjd;
4765 
4766  get_d1(self);
4767 
4768  decode_jd(jd, &nth, &rjd);
4769  if (!df && f_zero_p(sf) && !of) {
4770  set_to_simple(self, &dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
4771  }
4772  else {
4773  if (!complex_dat_p(dat))
4775  "cannot load complex into simple");
4776 
4777  set_to_complex(self, &dat->c, nth, rjd, df, sf, of, sg,
4778  0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF);
4779  }
4780  }
4781  return self;
4782 }
4783 #endif
4784 
4785 /* :nodoc: */
4786 static VALUE
4787 d_lite_initialize_copy(VALUE copy, VALUE date)
4788 {
4789  rb_check_frozen(copy);
4790 
4791  if (copy == date)
4792  return copy;
4793  {
4794  get_d2(copy, date);
4795  if (simple_dat_p(bdat)) {
4796  if (simple_dat_p(adat)) {
4797  adat->s = bdat->s;
4798  }
4799  else {
4800  adat->c.flags = bdat->s.flags | COMPLEX_DAT;
4801  adat->c.nth = bdat->s.nth;
4802  adat->c.jd = bdat->s.jd;
4803  adat->c.df = 0;
4804  adat->c.sf = INT2FIX(0);
4805  adat->c.of = 0;
4806  adat->c.sg = bdat->s.sg;
4807  adat->c.year = bdat->s.year;
4808 #ifndef USE_PACK
4809  adat->c.mon = bdat->s.mon;
4810  adat->c.mday = bdat->s.mday;
4811  adat->c.hour = bdat->s.hour;
4812  adat->c.min = bdat->s.min;
4813  adat->c.sec = bdat->s.sec;
4814 #else
4815  adat->c.pc = bdat->s.pc;
4816 #endif
4817  }
4818  }
4819  else {
4820  if (!complex_dat_p(adat))
4822  "cannot load complex into simple");
4823 
4824  adat->c = bdat->c;
4825  }
4826  }
4827  return copy;
4828 }
4829 
4830 #ifndef NDEBUG
4831 static VALUE
4832 d_lite_fill(VALUE self)
4833 {
4834  get_d1(self);
4835 
4836  if (simple_dat_p(dat)) {
4837  get_s_jd(dat);
4838  get_s_civil(dat);
4839  }
4840  else {
4841  get_c_jd(dat);
4842  get_c_civil(dat);
4843  get_c_df(dat);
4844  get_c_time(dat);
4845  }
4846  return self;
4847 }
4848 #endif
4849 
4850 /*
4851  * call-seq:
4852  * d.ajd -> rational
4853  *
4854  * Returns the astronomical Julian day number. This is a fractional
4855  * number, which is not adjusted by the offset.
4856  *
4857  * DateTime.new(2001,2,3,4,5,6,'+7').ajd #=> (11769328217/4800)
4858  * DateTime.new(2001,2,2,14,5,6,'-7').ajd #=> (11769328217/4800)
4859  */
4860 static VALUE
4861 d_lite_ajd(VALUE self)
4862 {
4863  get_d1(self);
4864  return m_ajd(dat);
4865 }
4866 
4867 /*
4868  * call-seq:
4869  * d.amjd -> rational
4870  *
4871  * Returns the astronomical modified Julian day number. This is
4872  * a fractional number, which is not adjusted by the offset.
4873  *
4874  * DateTime.new(2001,2,3,4,5,6,'+7').amjd #=> (249325817/4800)
4875  * DateTime.new(2001,2,2,14,5,6,'-7').amjd #=> (249325817/4800)
4876  */
4877 static VALUE
4878 d_lite_amjd(VALUE self)
4879 {
4880  get_d1(self);
4881  return m_amjd(dat);
4882 }
4883 
4884 /*
4885  * call-seq:
4886  * d.jd -> integer
4887  *
4888  * Returns the Julian day number. This is a whole number, which is
4889  * adjusted by the offset as the local time.
4890  *
4891  * DateTime.new(2001,2,3,4,5,6,'+7').jd #=> 2451944
4892  * DateTime.new(2001,2,3,4,5,6,'-7').jd #=> 2451944
4893  */
4894 static VALUE
4895 d_lite_jd(VALUE self)
4896 {
4897  get_d1(self);
4898  return m_real_local_jd(dat);
4899 }
4900 
4901 /*
4902  * call-seq:
4903  * d.mjd -> integer
4904  *
4905  * Returns the modified Julian day number. This is a whole number,
4906  * which is adjusted by the offset as the local time.
4907  *
4908  * DateTime.new(2001,2,3,4,5,6,'+7').mjd #=> 51943
4909  * DateTime.new(2001,2,3,4,5,6,'-7').mjd #=> 51943
4910  */
4911 static VALUE
4912 d_lite_mjd(VALUE self)
4913 {
4914  get_d1(self);
4915  return f_sub(m_real_local_jd(dat), INT2FIX(2400001));
4916 }
4917 
4918 /*
4919  * call-seq:
4920  * d.ld -> integer
4921  *
4922  * Returns the Lilian day number. This is a whole number, which is
4923  * adjusted by the offset as the local time.
4924  *
4925  * Date.new(2001,2,3).ld #=> 152784
4926  */
4927 static VALUE
4928 d_lite_ld(VALUE self)
4929 {
4930  get_d1(self);
4931  return f_sub(m_real_local_jd(dat), INT2FIX(2299160));
4932 }
4933 
4934 /*
4935  * call-seq:
4936  * d.year -> integer
4937  *
4938  * Returns the year.
4939  *
4940  * Date.new(2001,2,3).year #=> 2001
4941  * (Date.new(1,1,1) - 1).year #=> 0
4942  */
4943 static VALUE
4944 d_lite_year(VALUE self)
4945 {
4946  get_d1(self);
4947  return m_real_year(dat);
4948 }
4949 
4950 /*
4951  * call-seq:
4952  * d.yday -> fixnum
4953  *
4954  * Returns the day of the year (1-366).
4955  *
4956  * Date.new(2001,2,3).yday #=> 34
4957  */
4958 static VALUE
4959 d_lite_yday(VALUE self)
4960 {
4961  get_d1(self);
4962  return INT2FIX(m_yday(dat));
4963 }
4964 
4965 /*
4966  * call-seq:
4967  * d.mon -> fixnum
4968  * d.month -> fixnum
4969  *
4970  * Returns the month (1-12).
4971  *
4972  * Date.new(2001,2,3).mon #=> 2
4973  */
4974 static VALUE
4975 d_lite_mon(VALUE self)
4976 {
4977  get_d1(self);
4978  return INT2FIX(m_mon(dat));
4979 }
4980 
4981 /*
4982  * call-seq:
4983  * d.mday -> fixnum
4984  * d.day -> fixnum
4985  *
4986  * Returns the day of the month (1-31).
4987  *
4988  * Date.new(2001,2,3).mday #=> 3
4989  */
4990 static VALUE
4991 d_lite_mday(VALUE self)
4992 {
4993  get_d1(self);
4994  return INT2FIX(m_mday(dat));
4995 }
4996 
4997 /*
4998  * call-seq:
4999  * d.day_fraction -> rational
5000  *
5001  * Returns the fractional part of the day.
5002  *
5003  * DateTime.new(2001,2,3,12).day_fraction #=> (1/2)
5004  */
5005 static VALUE
5006 d_lite_day_fraction(VALUE self)
5007 {
5008  get_d1(self);
5009  if (simple_dat_p(dat))
5010  return INT2FIX(0);
5011  return m_fr(dat);
5012 }
5013 
5014 /*
5015  * call-seq:
5016  * d.cwyear -> integer
5017  *
5018  * Returns the calendar week based year.
5019  *
5020  * Date.new(2001,2,3).cwyear #=> 2001
5021  * Date.new(2000,1,1).cwyear #=> 1999
5022  */
5023 static VALUE
5024 d_lite_cwyear(VALUE self)
5025 {
5026  get_d1(self);
5027  return m_real_cwyear(dat);
5028 }
5029 
5030 /*
5031  * call-seq:
5032  * d.cweek -> fixnum
5033  *
5034  * Returns the calendar week number (1-53).
5035  *
5036  * Date.new(2001,2,3).cweek #=> 5
5037  */
5038 static VALUE
5039 d_lite_cweek(VALUE self)
5040 {
5041  get_d1(self);
5042  return INT2FIX(m_cweek(dat));
5043 }
5044 
5045 /*
5046  * call-seq:
5047  * d.cwday -> fixnum
5048  *
5049  * Returns the day of calendar week (1-7, Monday is 1).
5050  *
5051  * Date.new(2001,2,3).cwday #=> 6
5052  */
5053 static VALUE
5054 d_lite_cwday(VALUE self)
5055 {
5056  get_d1(self);
5057  return INT2FIX(m_cwday(dat));
5058 }
5059 
5060 #ifndef NDEBUG
5061 static VALUE
5062 d_lite_wnum0(VALUE self)
5063 {
5064  get_d1(self);
5065  return INT2FIX(m_wnum0(dat));
5066 }
5067 
5068 static VALUE
5069 d_lite_wnum1(VALUE self)
5070 {
5071  get_d1(self);
5072  return INT2FIX(m_wnum1(dat));
5073 }
5074 #endif
5075 
5076 /*
5077  * call-seq:
5078  * d.wday -> fixnum
5079  *
5080  * Returns the day of week (0-6, Sunday is zero).
5081  *
5082  * Date.new(2001,2,3).wday #=> 6
5083  */
5084 static VALUE
5085 d_lite_wday(VALUE self)
5086 {
5087  get_d1(self);
5088  return INT2FIX(m_wday(dat));
5089 }
5090 
5091 /*
5092  * call-seq:
5093  * d.sunday? -> bool
5094  *
5095  * Returns true if the date is Sunday.
5096  */
5097 static VALUE
5098 d_lite_sunday_p(VALUE self)
5099 {
5100  get_d1(self);
5101  return f_boolcast(m_wday(dat) == 0);
5102 }
5103 
5104 /*
5105  * call-seq:
5106  * d.monday? -> bool
5107  *
5108  * Returns true if the date is Monday.
5109  */
5110 static VALUE
5111 d_lite_monday_p(VALUE self)
5112 {
5113  get_d1(self);
5114  return f_boolcast(m_wday(dat) == 1);
5115 }
5116 
5117 /*
5118  * call-seq:
5119  * d.tuesday? -> bool
5120  *
5121  * Returns true if the date is Tuesday.
5122  */
5123 static VALUE
5124 d_lite_tuesday_p(VALUE self)
5125 {
5126  get_d1(self);
5127  return f_boolcast(m_wday(dat) == 2);
5128 }
5129 
5130 /*
5131  * call-seq:
5132  * d.wednesday? -> bool
5133  *
5134  * Returns true if the date is Wednesday.
5135  */
5136 static VALUE
5137 d_lite_wednesday_p(VALUE self)
5138 {
5139  get_d1(self);
5140  return f_boolcast(m_wday(dat) == 3);
5141 }
5142 
5143 /*
5144  * call-seq:
5145  * d.thursday? -> bool
5146  *
5147  * Returns true if the date is Thursday.
5148  */
5149 static VALUE
5150 d_lite_thursday_p(VALUE self)
5151 {
5152  get_d1(self);
5153  return f_boolcast(m_wday(dat) == 4);
5154 }
5155 
5156 /*
5157  * call-seq:
5158  * d.friday? -> bool
5159  *
5160  * Returns true if the date is Friday.
5161  */
5162 static VALUE
5163 d_lite_friday_p(VALUE self)
5164 {
5165  get_d1(self);
5166  return f_boolcast(m_wday(dat) == 5);
5167 }
5168 
5169 /*
5170  * call-seq:
5171  * d.saturday? -> bool
5172  *
5173  * Returns true if the date is Saturday.
5174  */
5175 static VALUE
5176 d_lite_saturday_p(VALUE self)
5177 {
5178  get_d1(self);
5179  return f_boolcast(m_wday(dat) == 6);
5180 }
5181 
5182 #ifndef NDEBUG
5183 static VALUE
5184 d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
5185 {
5186  int rjd, ns;
5187 
5188  get_d1(self);
5189 
5190  if (NUM2INT(k) != m_wday(dat))
5191  return Qfalse;
5192 
5193  c_nth_kday_to_jd(m_year(dat), m_mon(dat),
5194  NUM2INT(n), NUM2INT(k), m_virtual_sg(dat), /* !=m_sg() */
5195  &rjd, &ns);
5196  if (m_local_jd(dat) != rjd)
5197  return Qfalse;
5198  return Qtrue;
5199 }
5200 #endif
5201 
5202 /*
5203  * call-seq:
5204  * d.hour -> fixnum
5205  *
5206  * Returns the hour (0-23).
5207  *
5208  * DateTime.new(2001,2,3,4,5,6).hour #=> 4
5209  */
5210 static VALUE
5211 d_lite_hour(VALUE self)
5212 {
5213  get_d1(self);
5214  return INT2FIX(m_hour(dat));
5215 }
5216 
5217 /*
5218  * call-seq:
5219  * d.min -> fixnum
5220  * d.minute -> fixnum
5221  *
5222  * Returns the minute (0-59).
5223  *
5224  * DateTime.new(2001,2,3,4,5,6).min #=> 5
5225  */
5226 static VALUE
5227 d_lite_min(VALUE self)
5228 {
5229  get_d1(self);
5230  return INT2FIX(m_min(dat));
5231 }
5232 
5233 /*
5234  * call-seq:
5235  * d.sec -> fixnum
5236  * d.second -> fixnum
5237  *
5238  * Returns the second (0-59).
5239  *
5240  * DateTime.new(2001,2,3,4,5,6).sec #=> 6
5241  */
5242 static VALUE
5243 d_lite_sec(VALUE self)
5244 {
5245  get_d1(self);
5246  return INT2FIX(m_sec(dat));
5247 }
5248 
5249 /*
5250  * call-seq:
5251  * d.sec_fraction -> rational
5252  * d.second_fraction -> rational
5253  *
5254  * Returns the fractional part of the second.
5255  *
5256  * DateTime.new(2001,2,3,4,5,6.5).sec_fraction #=> (1/2)
5257  */
5258 static VALUE
5259 d_lite_sec_fraction(VALUE self)
5260 {
5261  get_d1(self);
5262  return m_sf_in_sec(dat);
5263 }
5264 
5265 /*
5266  * call-seq:
5267  * d.offset -> rational
5268  *
5269  * Returns the offset.
5270  *
5271  * DateTime.parse('04pm+0730').offset #=> (5/16)
5272  */
5273 static VALUE
5274 d_lite_offset(VALUE self)
5275 {
5276  get_d1(self);
5277  return m_of_in_day(dat);
5278 }
5279 
5280 /*
5281  * call-seq:
5282  * d.zone -> string
5283  *
5284  * Returns the timezone.
5285  *
5286  * DateTime.parse('04pm+0730').zone #=> "+07:30"
5287  */
5288 static VALUE
5289 d_lite_zone(VALUE self)
5290 {
5291  get_d1(self);
5292  return m_zone(dat);
5293 }
5294 
5295 /*
5296  * call-seq:
5297  * d.julian? -> bool
5298  *
5299  * Returns true if the date is before the day of calendar reform.
5300  *
5301  * Date.new(1582,10,15).julian? #=> false
5302  * (Date.new(1582,10,15) - 1).julian? #=> true
5303  */
5304 static VALUE
5305 d_lite_julian_p(VALUE self)
5306 {
5307  get_d1(self);
5308  return f_boolcast(m_julian_p(dat));
5309 }
5310 
5311 /*
5312  * call-seq:
5313  * d.gregorian? -> bool
5314  *
5315  * Returns true if the date is on or after the day of calendar reform.
5316  *
5317  * Date.new(1582,10,15).gregorian? #=> true
5318  * (Date.new(1582,10,15) - 1).gregorian? #=> false
5319  */
5320 static VALUE
5321 d_lite_gregorian_p(VALUE self)
5322 {
5323  get_d1(self);
5324  return f_boolcast(m_gregorian_p(dat));
5325 }
5326 
5327 /*
5328  * call-seq:
5329  * d.leap? -> bool
5330  *
5331  * Returns true if the year is a leap year.
5332  *
5333  * Date.new(2000).leap? #=> true
5334  * Date.new(2001).leap? #=> false
5335  */
5336 static VALUE
5337 d_lite_leap_p(VALUE self)
5338 {
5339  int rjd, ns, ry, rm, rd;
5340 
5341  get_d1(self);
5342  if (m_gregorian_p(dat))
5343  return f_boolcast(c_gregorian_leap_p(m_year(dat)));
5344 
5345  c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat),
5346  &rjd, &ns);
5347  c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd);
5348  return f_boolcast(rd == 29);
5349 }
5350 
5351 /*
5352  * call-seq:
5353  * d.start -> float
5354  *
5355  * Returns the Julian day number denoting the day of calendar reform.
5356  *
5357  * Date.new(2001,2,3).start #=> 2299161.0
5358  * Date.new(2001,2,3,Date::GREGORIAN).start #=> -Infinity
5359  */
5360 static VALUE
5361 d_lite_start(VALUE self)
5362 {
5363  get_d1(self);
5364  return DBL2NUM(m_sg(dat));
5365 }
5366 
5367 static void
5368 clear_civil(union DateData *x)
5369 {
5370  if (simple_dat_p(x)) {
5371  x->s.year = 0;
5372 #ifndef USE_PACK
5373  x->s.mon = 0;
5374  x->s.mday = 0;
5375 #else
5376  x->s.pc = 0;
5377 #endif
5378  x->s.flags &= ~HAVE_CIVIL;
5379  }
5380  else {
5381  x->c.year = 0;
5382 #ifndef USE_PACK
5383  x->c.mon = 0;
5384  x->c.mday = 0;
5385  x->c.hour = 0;
5386  x->c.min = 0;
5387  x->c.sec = 0;
5388 #else
5389  x->c.pc = 0;
5390 #endif
5391  x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
5392  }
5393 }
5394 
5395 static void
5396 set_sg(union DateData *x, double sg)
5397 {
5398  if (simple_dat_p(x)) {
5399  get_s_jd(x);
5400  clear_civil(x);
5401  x->s.sg = (date_sg_t)sg;
5402  } else {
5403  get_c_jd(x);
5404  get_c_df(x);
5405  clear_civil(x);
5406  x->c.sg = (date_sg_t)sg;
5407  }
5408 }
5409 
5410 static VALUE
5411 dup_obj_with_new_start(VALUE obj, double sg)
5412 {
5413  volatile VALUE dup = dup_obj(obj);
5414  {
5415  get_d1(dup);
5416  set_sg(dat, sg);
5417  }
5418  return dup;
5419 }
5420 
5421 /*
5422  * call-seq:
5423  * d.new_start([start=Date::ITALY]) -> date
5424  *
5425  * Duplicates self and resets its day of calendar reform.
5426  *
5427  * d = Date.new(1582,10,15)
5428  * d.new_start(Date::JULIAN) #=> #<Date: 1582-10-05 ...>
5429  */
5430 static VALUE
5431 d_lite_new_start(int argc, VALUE *argv, VALUE self)
5432 {
5433  VALUE vsg;
5434  double sg;
5435 
5436  rb_scan_args(argc, argv, "01", &vsg);
5437 
5438  sg = DEFAULT_SG;
5439  if (argc >= 1)
5440  val2sg(vsg, sg);
5441 
5442  return dup_obj_with_new_start(self, sg);
5443 }
5444 
5445 /*
5446  * call-seq:
5447  * d.italy -> date
5448  *
5449  * This method is equivalent to new_start(Date::ITALY).
5450  */
5451 static VALUE
5452 d_lite_italy(VALUE self)
5453 {
5454  return dup_obj_with_new_start(self, ITALY);
5455 }
5456 
5457 /*
5458  * call-seq:
5459  * d.england -> date
5460  *
5461  * This method is equivalent to new_start(Date::ENGLAND).
5462  */
5463 static VALUE
5464 d_lite_england(VALUE self)
5465 {
5466  return dup_obj_with_new_start(self, ENGLAND);
5467 }
5468 
5469 /*
5470  * call-seq:
5471  * d.julian -> date
5472  *
5473  * This method is equivalent to new_start(Date::JULIAN).
5474  */
5475 static VALUE
5476 d_lite_julian(VALUE self)
5477 {
5478  return dup_obj_with_new_start(self, JULIAN);
5479 }
5480 
5481 /*
5482  * call-seq:
5483  * d.gregorian -> date
5484  *
5485  * This method is equivalent to new_start(Date::GREGORIAN).
5486  */
5487 static VALUE
5488 d_lite_gregorian(VALUE self)
5489 {
5490  return dup_obj_with_new_start(self, GREGORIAN);
5491 }
5492 
5493 static void
5494 set_of(union DateData *x, int of)
5495 {
5496  assert(complex_dat_p(x));
5497  get_c_jd(x);
5498  get_c_df(x);
5499  clear_civil(x);
5500  x->c.of = of;
5501 }
5502 
5503 static VALUE
5504 dup_obj_with_new_offset(VALUE obj, int of)
5505 {
5506  volatile VALUE dup = dup_obj_as_complex(obj);
5507  {
5508  get_d1(dup);
5509  set_of(dat, of);
5510  }
5511  return dup;
5512 }
5513 
5514 /*
5515  * call-seq:
5516  * d.new_offset([offset=0]) -> date
5517  *
5518  * Duplicates self and resets its offset.
5519  *
5520  * d = DateTime.new(2001,2,3,4,5,6,'-02:00')
5521  * #=> #<DateTime: 2001-02-03T04:05:06-02:00 ...>
5522  * d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...>
5523  */
5524 static VALUE
5525 d_lite_new_offset(int argc, VALUE *argv, VALUE self)
5526 {
5527  VALUE vof;
5528  int rof;
5529 
5530  rb_scan_args(argc, argv, "01", &vof);
5531 
5532  rof = 0;
5533  if (argc >= 1)
5534  val2off(vof, rof);
5535 
5536  return dup_obj_with_new_offset(self, rof);
5537 }
5538 
5539 /*
5540  * call-seq:
5541  * d + other -> date
5542  *
5543  * Returns a date object pointing +other+ days after self. The other
5544  * should be a numeric value. If the other is a fractional number,
5545  * assumes its precision is at most nanosecond.
5546  *
5547  * Date.new(2001,2,3) + 1 #=> #<Date: 2001-02-04 ...>
5548  * DateTime.new(2001,2,3) + Rational(1,2)
5549  * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
5550  * DateTime.new(2001,2,3) + Rational(-1,2)
5551  * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
5552  * DateTime.jd(0,12) + DateTime.new(2001,2,3).ajd
5553  * #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
5554  */
5555 static VALUE
5556 d_lite_plus(VALUE self, VALUE other)
5557 {
5558  int try_rational = 1;
5559  get_d1(self);
5560 
5561  again:
5562  switch (TYPE(other)) {
5563  case T_FIXNUM:
5564  {
5565  VALUE nth;
5566  long t;
5567  int jd;
5568 
5569  nth = m_nth(dat);
5570  t = FIX2LONG(other);
5571  if (DIV(t, CM_PERIOD)) {
5572  nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
5573  t = MOD(t, CM_PERIOD);
5574  }
5575 
5576  if (!t)
5577  jd = m_jd(dat);
5578  else {
5579  jd = m_jd(dat) + (int)t;
5580  canonicalize_jd(nth, jd);
5581  }
5582 
5583  if (simple_dat_p(dat))
5584  return d_simple_new_internal(rb_obj_class(self),
5585  nth, jd,
5586  dat->s.sg,
5587  0, 0, 0,
5588  (dat->s.flags | HAVE_JD) &
5589  ~HAVE_CIVIL);
5590  else
5591  return d_complex_new_internal(rb_obj_class(self),
5592  nth, jd,
5593  dat->c.df, dat->c.sf,
5594  dat->c.of, dat->c.sg,
5595  0, 0, 0,
5596 #ifndef USE_PACK
5597  dat->c.hour,
5598  dat->c.min,
5599  dat->c.sec,
5600 #else
5601  EX_HOUR(dat->c.pc),
5602  EX_MIN(dat->c.pc),
5603  EX_SEC(dat->c.pc),
5604 #endif
5605  (dat->c.flags | HAVE_JD) &
5606  ~HAVE_CIVIL);
5607  }
5608  break;
5609  case T_BIGNUM:
5610  {
5611  VALUE nth;
5612  int jd, s;
5613 
5614  if (f_positive_p(other))
5615  s = +1;
5616  else {
5617  s = -1;
5618  other = f_negate(other);
5619  }
5620 
5621  nth = f_idiv(other, INT2FIX(CM_PERIOD));
5622  jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD)));
5623 
5624  if (s < 0) {
5625  nth = f_negate(nth);
5626  jd = -jd;
5627  }
5628 
5629  if (!jd)
5630  jd = m_jd(dat);
5631  else {
5632  jd = m_jd(dat) + jd;
5633  canonicalize_jd(nth, jd);
5634  }
5635 
5636  if (f_zero_p(nth))
5637  nth = m_nth(dat);
5638  else
5639  nth = f_add(m_nth(dat), nth);
5640 
5641  if (simple_dat_p(dat))
5642  return d_simple_new_internal(rb_obj_class(self),
5643  nth, jd,
5644  dat->s.sg,
5645  0, 0, 0,
5646  (dat->s.flags | HAVE_JD) &
5647  ~HAVE_CIVIL);
5648  else
5649  return d_complex_new_internal(rb_obj_class(self),
5650  nth, jd,
5651  dat->c.df, dat->c.sf,
5652  dat->c.of, dat->c.sg,
5653  0, 0, 0,
5654 #ifndef USE_PACK
5655  dat->c.hour,
5656  dat->c.min,
5657  dat->c.sec,
5658 #else
5659  EX_HOUR(dat->c.pc),
5660  EX_MIN(dat->c.pc),
5661  EX_SEC(dat->c.pc),
5662 #endif
5663  (dat->c.flags | HAVE_JD) &
5664  ~HAVE_CIVIL);
5665  }
5666  break;
5667  case T_FLOAT:
5668  {
5669  double jd, o, tmp;
5670  int s, df;
5671  VALUE nth, sf;
5672 
5673  o = RFLOAT_VALUE(other);
5674 
5675  if (o > 0)
5676  s = +1;
5677  else {
5678  s = -1;
5679  o = -o;
5680  }
5681 
5682  o = modf(o, &tmp);
5683 
5684  if (!floor(tmp / CM_PERIOD)) {
5685  nth = INT2FIX(0);
5686  jd = (int)tmp;
5687  }
5688  else {
5689  double i, f;
5690 
5691  f = modf(tmp / CM_PERIOD, &i);
5692  nth = f_floor(DBL2NUM(i));
5693  jd = (int)(f * CM_PERIOD);
5694  }
5695 
5696  o *= DAY_IN_SECONDS;
5697  o = modf(o, &tmp);
5698  df = (int)tmp;
5699  o *= SECOND_IN_NANOSECONDS;
5700  sf = INT2FIX((int)round(o));
5701 
5702  if (s < 0) {
5703  jd = -jd;
5704  df = -df;
5705  sf = f_negate(sf);
5706  }
5707 
5708  if (f_zero_p(sf))
5709  sf = m_sf(dat);
5710  else {
5711  sf = f_add(m_sf(dat), sf);
5712  if (f_lt_p(sf, INT2FIX(0))) {
5713  df -= 1;
5714  sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5715  }
5716  else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5717  df += 1;
5718  sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5719  }
5720  }
5721 
5722  if (!df)
5723  df = m_df(dat);
5724  else {
5725  df = m_df(dat) + df;
5726  if (df < 0) {
5727  jd -= 1;
5728  df += DAY_IN_SECONDS;
5729  }
5730  else if (df >= DAY_IN_SECONDS) {
5731  jd += 1;
5732  df -= DAY_IN_SECONDS;
5733  }
5734  }
5735 
5736  if (!jd)
5737  jd = m_jd(dat);
5738  else {
5739  jd = m_jd(dat) + jd;
5740  canonicalize_jd(nth, jd);
5741  }
5742 
5743  if (f_zero_p(nth))
5744  nth = m_nth(dat);
5745  else
5746  nth = f_add(m_nth(dat), nth);
5747 
5748  if (!df && f_zero_p(sf) && !m_of(dat))
5749  return d_simple_new_internal(rb_obj_class(self),
5750  nth, (int)jd,
5751  m_sg(dat),
5752  0, 0, 0,
5753  (dat->s.flags | HAVE_JD) &
5754  ~(HAVE_CIVIL | HAVE_TIME |
5755  COMPLEX_DAT));
5756  else
5757  return d_complex_new_internal(rb_obj_class(self),
5758  nth, (int)jd,
5759  df, sf,
5760  m_of(dat), m_sg(dat),
5761  0, 0, 0,
5762  0, 0, 0,
5763  (dat->c.flags |
5764  HAVE_JD | HAVE_DF) &
5765  ~(HAVE_CIVIL | HAVE_TIME));
5766  }
5767  break;
5768  default:
5769  expect_numeric(other);
5770  other = f_to_r(other);
5771  if (!k_rational_p(other)) {
5772  if (!try_rational) Check_Type(other, T_RATIONAL);
5773  try_rational = 0;
5774  goto again;
5775  }
5776  /* fall through */
5777  case T_RATIONAL:
5778  {
5779  VALUE nth, sf, t;
5780  int jd, df, s;
5781 
5782  if (wholenum_p(other)) {
5783  other = rb_rational_num(other);
5784  goto again;
5785  }
5786 
5787  if (f_positive_p(other))
5788  s = +1;
5789  else {
5790  s = -1;
5791  other = f_negate(other);
5792  }
5793 
5794  nth = f_idiv(other, INT2FIX(CM_PERIOD));
5795  t = f_mod(other, INT2FIX(CM_PERIOD));
5796 
5797  jd = FIX2INT(f_idiv(t, INT2FIX(1)));
5798  t = f_mod(t, INT2FIX(1));
5799 
5800  t = f_mul(t, INT2FIX(DAY_IN_SECONDS));
5801  df = FIX2INT(f_idiv(t, INT2FIX(1)));
5802  t = f_mod(t, INT2FIX(1));
5803 
5805 
5806  if (s < 0) {
5807  nth = f_negate(nth);
5808  jd = -jd;
5809  df = -df;
5810  sf = f_negate(sf);
5811  }
5812 
5813  if (f_zero_p(sf))
5814  sf = m_sf(dat);
5815  else {
5816  sf = f_add(m_sf(dat), sf);
5817  if (f_lt_p(sf, INT2FIX(0))) {
5818  df -= 1;
5819  sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5820  }
5821  else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5822  df += 1;
5823  sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5824  }
5825  }
5826 
5827  if (!df)
5828  df = m_df(dat);
5829  else {
5830  df = m_df(dat) + df;
5831  if (df < 0) {
5832  jd -= 1;
5833  df += DAY_IN_SECONDS;
5834  }
5835  else if (df >= DAY_IN_SECONDS) {
5836  jd += 1;
5837  df -= DAY_IN_SECONDS;
5838  }
5839  }
5840 
5841  if (!jd)
5842  jd = m_jd(dat);
5843  else {
5844  jd = m_jd(dat) + jd;
5845  canonicalize_jd(nth, jd);
5846  }
5847 
5848  if (f_zero_p(nth))
5849  nth = m_nth(dat);
5850  else
5851  nth = f_add(m_nth(dat), nth);
5852 
5853  if (!df && f_zero_p(sf) && !m_of(dat))
5854  return d_simple_new_internal(rb_obj_class(self),
5855  nth, jd,
5856  m_sg(dat),
5857  0, 0, 0,
5858  (dat->s.flags | HAVE_JD) &
5859  ~(HAVE_CIVIL | HAVE_TIME |
5860  COMPLEX_DAT));
5861  else
5862  return d_complex_new_internal(rb_obj_class(self),
5863  nth, jd,
5864  df, sf,
5865  m_of(dat), m_sg(dat),
5866  0, 0, 0,
5867  0, 0, 0,
5868  (dat->c.flags |
5869  HAVE_JD | HAVE_DF) &
5870  ~(HAVE_CIVIL | HAVE_TIME));
5871  }
5872  break;
5873  }
5874 }
5875 
5876 static VALUE
5877 minus_dd(VALUE self, VALUE other)
5878 {
5879  get_d2(self, other);
5880 
5881  {
5882  int d, df;
5883  VALUE n, sf, r;
5884 
5885  n = f_sub(m_nth(adat), m_nth(bdat));
5886  d = m_jd(adat) - m_jd(bdat);
5887  df = m_df(adat) - m_df(bdat);
5888  sf = f_sub(m_sf(adat), m_sf(bdat));
5889  canonicalize_jd(n, d);
5890 
5891  if (df < 0) {
5892  d -= 1;
5893  df += DAY_IN_SECONDS;
5894  }
5895  else if (df >= DAY_IN_SECONDS) {
5896  d += 1;
5897  df -= DAY_IN_SECONDS;
5898  }
5899 
5900  if (f_lt_p(sf, INT2FIX(0))) {
5901  df -= 1;
5902  sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5903  }
5904  else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
5905  df += 1;
5906  sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
5907  }
5908 
5909  if (f_zero_p(n))
5910  r = INT2FIX(0);
5911  else
5912  r = f_mul(n, INT2FIX(CM_PERIOD));
5913 
5914  if (d)
5915  r = f_add(r, rb_rational_new1(INT2FIX(d)));
5916  if (df)
5917  r = f_add(r, isec_to_day(df));
5918  if (f_nonzero_p(sf))
5919  r = f_add(r, ns_to_day(sf));
5920 
5921  if (RB_TYPE_P(r, T_RATIONAL))
5922  return r;
5923  return rb_rational_new1(r);
5924  }
5925 }
5926 
5927 /*
5928  * call-seq:
5929  * d - other -> date or rational
5930  *
5931  * Returns the difference between the two dates if the other is a date
5932  * object. If the other is a numeric value, returns a date object
5933  * pointing +other+ days before self. If the other is a fractional number,
5934  * assumes its precision is at most nanosecond.
5935  *
5936  * Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...>
5937  * DateTime.new(2001,2,3) - Rational(1,2)
5938  * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...>
5939  * Date.new(2001,2,3) - Date.new(2001)
5940  * #=> (33/1)
5941  * DateTime.new(2001,2,3) - DateTime.new(2001,2,2,12)
5942  * #=> (1/2)
5943  */
5944 static VALUE
5945 d_lite_minus(VALUE self, VALUE other)
5946 {
5947  if (k_date_p(other))
5948  return minus_dd(self, other);
5949 
5950  switch (TYPE(other)) {
5951  case T_FIXNUM:
5952  return d_lite_plus(self, LONG2NUM(-FIX2LONG(other)));
5953  case T_FLOAT:
5954  return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other)));
5955  default:
5956  expect_numeric(other);
5957  /* fall through */
5958  case T_BIGNUM:
5959  case T_RATIONAL:
5960  return d_lite_plus(self, f_negate(other));
5961  }
5962 }
5963 
5964 /*
5965  * call-seq:
5966  * d.next_day([n=1]) -> date
5967  *
5968  * This method is equivalent to d + n.
5969  */
5970 static VALUE
5971 d_lite_next_day(int argc, VALUE *argv, VALUE self)
5972 {
5973  VALUE n;
5974 
5975  rb_scan_args(argc, argv, "01", &n);
5976  if (argc < 1)
5977  n = INT2FIX(1);
5978  return d_lite_plus(self, n);
5979 }
5980 
5981 /*
5982  * call-seq:
5983  * d.prev_day([n=1]) -> date
5984  *
5985  * This method is equivalent to d - n.
5986  */
5987 static VALUE
5988 d_lite_prev_day(int argc, VALUE *argv, VALUE self)
5989 {
5990  VALUE n;
5991 
5992  rb_scan_args(argc, argv, "01", &n);
5993  if (argc < 1)
5994  n = INT2FIX(1);
5995  return d_lite_minus(self, n);
5996 }
5997 
5998 /*
5999  * call-seq:
6000  * d.succ -> date
6001  * d.next -> date
6002  *
6003  * Returns a date object denoting the following day.
6004  */
6005 static VALUE
6006 d_lite_next(VALUE self)
6007 {
6008  return d_lite_next_day(0, (VALUE *)NULL, self);
6009 }
6010 
6011 /*
6012  * call-seq:
6013  * d >> n -> date
6014  *
6015  * Returns a date object pointing +n+ months after self.
6016  * The argument +n+ should be a numeric value.
6017  *
6018  * Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...>
6019  * Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...>
6020  *
6021  * When the same day does not exist for the corresponding month,
6022  * the last day of the month is used instead:
6023  *
6024  * Date.new(2001,1,28) >> 1 #=> #<Date: 2001-02-28 ...>
6025  * Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...>
6026  *
6027  * This also results in the following, possibly unexpected, behavior:
6028  *
6029  * Date.new(2001,1,31) >> 2 #=> #<Date: 2001-03-31 ...>
6030  * Date.new(2001,1,31) >> 1 >> 1 #=> #<Date: 2001-03-28 ...>
6031  *
6032  * Date.new(2001,1,31) >> 1 >> -1 #=> #<Date: 2001-01-28 ...>
6033  */
6034 static VALUE
6035 d_lite_rshift(VALUE self, VALUE other)
6036 {
6037  VALUE t, y, nth, rjd2;
6038  int m, d, rjd;
6039  double sg;
6040 
6041  get_d1(self);
6042  t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)),
6043  INT2FIX(m_mon(dat) - 1),
6044  other);
6045  if (FIXNUM_P(t)) {
6046  long it = FIX2LONG(t);
6047  y = LONG2NUM(DIV(it, 12));
6048  it = MOD(it, 12);
6049  m = (int)it + 1;
6050  }
6051  else {
6052  y = f_idiv(t, INT2FIX(12));
6053  t = f_mod(t, INT2FIX(12));
6054  m = FIX2INT(t) + 1;
6055  }
6056  d = m_mday(dat);
6057  sg = m_sg(dat);
6058 
6059  while (1) {
6060  int ry, rm, rd, ns;
6061 
6062  if (valid_civil_p(y, m, d, sg,
6063  &nth, &ry,
6064  &rm, &rd, &rjd, &ns))
6065  break;
6066  if (--d < 1)
6067  rb_raise(eDateError, "invalid date");
6068  }
6069  encode_jd(nth, rjd, &rjd2);
6070  return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
6071 }
6072 
6073 /*
6074  * call-seq:
6075  * d << n -> date
6076  *
6077  * Returns a date object pointing +n+ months before self.
6078  * The argument +n+ should be a numeric value.
6079  *
6080  * Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...>
6081  * Date.new(2001,2,3) << -2 #=> #<Date: 2001-04-03 ...>
6082  *
6083  * When the same day does not exist for the corresponding month,
6084  * the last day of the month is used instead:
6085  *
6086  * Date.new(2001,3,28) << 1 #=> #<Date: 2001-02-28 ...>
6087  * Date.new(2001,3,31) << 1 #=> #<Date: 2001-02-28 ...>
6088  *
6089  * This also results in the following, possibly unexpected, behavior:
6090  *
6091  * Date.new(2001,3,31) << 2 #=> #<Date: 2001-01-31 ...>
6092  * Date.new(2001,3,31) << 1 << 1 #=> #<Date: 2001-01-28 ...>
6093  *
6094  * Date.new(2001,3,31) << 1 << -1 #=> #<Date: 2001-03-28 ...>
6095  */
6096 static VALUE
6097 d_lite_lshift(VALUE self, VALUE other)
6098 {
6099  expect_numeric(other);
6100  return d_lite_rshift(self, f_negate(other));
6101 }
6102 
6103 /*
6104  * call-seq:
6105  * d.next_month([n=1]) -> date
6106  *
6107  * This method is equivalent to d >> n.
6108  *
6109  * See Date#>> for examples.
6110  */
6111 static VALUE
6112 d_lite_next_month(int argc, VALUE *argv, VALUE self)
6113 {
6114  VALUE n;
6115 
6116  rb_scan_args(argc, argv, "01", &n);
6117  if (argc < 1)
6118  n = INT2FIX(1);
6119  return d_lite_rshift(self, n);
6120 }
6121 
6122 /*
6123  * call-seq:
6124  * d.prev_month([n=1]) -> date
6125  *
6126  * This method is equivalent to d << n.
6127  *
6128  * See Date#<< for examples.
6129  */
6130 static VALUE
6131 d_lite_prev_month(int argc, VALUE *argv, VALUE self)
6132 {
6133  VALUE n;
6134 
6135  rb_scan_args(argc, argv, "01", &n);
6136  if (argc < 1)
6137  n = INT2FIX(1);
6138  return d_lite_lshift(self, n);
6139 }
6140 
6141 /*
6142  * call-seq:
6143  * d.next_year([n=1]) -> date
6144  *
6145  * This method is equivalent to d >> (n * 12).
6146  *
6147  * Date.new(2001,2,3).next_year #=> #<Date: 2002-02-03 ...>
6148  * Date.new(2008,2,29).next_year #=> #<Date: 2009-02-28 ...>
6149  * Date.new(2008,2,29).next_year(4) #=> #<Date: 2012-02-29 ...>
6150  *
6151  * See also Date#>>.
6152  */
6153 static VALUE
6154 d_lite_next_year(int argc, VALUE *argv, VALUE self)
6155 {
6156  VALUE n;
6157 
6158  rb_scan_args(argc, argv, "01", &n);
6159  if (argc < 1)
6160  n = INT2FIX(1);
6161  return d_lite_rshift(self, f_mul(n, INT2FIX(12)));
6162 }
6163 
6164 /*
6165  * call-seq:
6166  * d.prev_year([n=1]) -> date
6167  *
6168  * This method is equivalent to d << (n * 12).
6169  *
6170  * Date.new(2001,2,3).prev_year #=> #<Date: 2000-02-03 ...>
6171  * Date.new(2008,2,29).prev_year #=> #<Date: 2007-02-28 ...>
6172  * Date.new(2008,2,29).prev_year(4) #=> #<Date: 2004-02-29 ...>
6173  *
6174  * See also Date#<<.
6175  */
6176 static VALUE
6177 d_lite_prev_year(int argc, VALUE *argv, VALUE self)
6178 {
6179  VALUE n;
6180 
6181  rb_scan_args(argc, argv, "01", &n);
6182  if (argc < 1)
6183  n = INT2FIX(1);
6184  return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
6185 }
6186 
6187 static VALUE d_lite_cmp(VALUE, VALUE);
6188 
6189 /*
6190  * call-seq:
6191  * d.step(limit[, step=1]) -> enumerator
6192  * d.step(limit[, step=1]){|date| ...} -> self
6193  *
6194  * Iterates evaluation of the given block, which takes a date object.
6195  * The limit should be a date object.
6196  *
6197  * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size
6198  * #=> 52
6199  */
6200 static VALUE
6201 d_lite_step(int argc, VALUE *argv, VALUE self)
6202 {
6203  VALUE limit, step, date;
6204  int c;
6205 
6206  rb_scan_args(argc, argv, "11", &limit, &step);
6207 
6208  if (argc < 2)
6209  step = INT2FIX(1);
6210 
6211 #if 0
6212  if (f_zero_p(step))
6213  rb_raise(rb_eArgError, "step can't be 0");
6214 #endif
6215 
6216  RETURN_ENUMERATOR(self, argc, argv);
6217 
6218  date = self;
6219  c = f_cmp(step, INT2FIX(0));
6220  if (c < 0) {
6221  while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
6222  rb_yield(date);
6223  date = d_lite_plus(date, step);
6224  }
6225  }
6226  else if (c == 0) {
6227  while (1)
6228  rb_yield(date);
6229  }
6230  else /* if (c > 0) */ {
6231  while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
6232  rb_yield(date);
6233  date = d_lite_plus(date, step);
6234  }
6235  }
6236  return self;
6237 }
6238 
6239 /*
6240  * call-seq:
6241  * d.upto(max) -> enumerator
6242  * d.upto(max){|date| ...} -> self
6243  *
6244  * This method is equivalent to step(max, 1){|date| ...}.
6245  */
6246 static VALUE
6247 d_lite_upto(VALUE self, VALUE max)
6248 {
6249  VALUE date;
6250 
6251  RETURN_ENUMERATOR(self, 1, &max);
6252 
6253  date = self;
6254  while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
6255  rb_yield(date);
6256  date = d_lite_plus(date, INT2FIX(1));
6257  }
6258  return self;
6259 }
6260 
6261 /*
6262  * call-seq:
6263  * d.downto(min) -> enumerator
6264  * d.downto(min){|date| ...} -> self
6265  *
6266  * This method is equivalent to step(min, -1){|date| ...}.
6267  */
6268 static VALUE
6269 d_lite_downto(VALUE self, VALUE min)
6270 {
6271  VALUE date;
6272 
6273  RETURN_ENUMERATOR(self, 1, &min);
6274 
6275  date = self;
6276  while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
6277  rb_yield(date);
6278  date = d_lite_plus(date, INT2FIX(-1));
6279  }
6280  return self;
6281 }
6282 
6283 static VALUE
6284 cmp_gen(VALUE self, VALUE other)
6285 {
6286  get_d1(self);
6287 
6288  if (k_numeric_p(other))
6289  return INT2FIX(f_cmp(m_ajd(dat), other));
6290  else if (k_date_p(other))
6291  return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other)));
6292  return rb_num_coerce_cmp(self, other, id_cmp);
6293 }
6294 
6295 static VALUE
6296 cmp_dd(VALUE self, VALUE other)
6297 {
6298  get_d2(self, other);
6299 
6300  {
6301  VALUE a_nth, b_nth,
6302  a_sf, b_sf;
6303  int a_jd, b_jd,
6304  a_df, b_df;
6305 
6306  m_canonicalize_jd(self, adat);
6307  m_canonicalize_jd(other, bdat);
6308  a_nth = m_nth(adat);
6309  b_nth = m_nth(bdat);
6310  if (f_eqeq_p(a_nth, b_nth)) {
6311  a_jd = m_jd(adat);
6312  b_jd = m_jd(bdat);
6313  if (a_jd == b_jd) {
6314  a_df = m_df(adat);
6315  b_df = m_df(bdat);
6316  if (a_df == b_df) {
6317  a_sf = m_sf(adat);
6318  b_sf = m_sf(bdat);
6319  if (f_eqeq_p(a_sf, b_sf)) {
6320  return INT2FIX(0);
6321  }
6322  else if (f_lt_p(a_sf, b_sf)) {
6323  return INT2FIX(-1);
6324  }
6325  else {
6326  return INT2FIX(1);
6327  }
6328  }
6329  else if (a_df < b_df) {
6330  return INT2FIX(-1);
6331  }
6332  else {
6333  return INT2FIX(1);
6334  }
6335  }
6336  else if (a_jd < b_jd) {
6337  return INT2FIX(-1);
6338  }
6339  else {
6340  return INT2FIX(1);
6341  }
6342  }
6343  else if (f_lt_p(a_nth, b_nth)) {
6344  return INT2FIX(-1);
6345  }
6346  else {
6347  return INT2FIX(1);
6348  }
6349  }
6350 }
6351 
6352 /*
6353  * call-seq:
6354  * d <=> other -> -1, 0, +1 or nil
6355  *
6356  * Compares the two dates and returns -1, zero, 1 or nil. The other
6357  * should be a date object or a numeric value as an astronomical
6358  * Julian day number.
6359  *
6360  * Date.new(2001,2,3) <=> Date.new(2001,2,4) #=> -1
6361  * Date.new(2001,2,3) <=> Date.new(2001,2,3) #=> 0
6362  * Date.new(2001,2,3) <=> Date.new(2001,2,2) #=> 1
6363  * Date.new(2001,2,3) <=> Object.new #=> nil
6364  * Date.new(2001,2,3) <=> Rational(4903887,2) #=> 0
6365  *
6366  * See also Comparable.
6367  */
6368 static VALUE
6369 d_lite_cmp(VALUE self, VALUE other)
6370 {
6371  if (!k_date_p(other))
6372  return cmp_gen(self, other);
6373 
6374  {
6375  get_d2(self, other);
6376 
6377  if (!(simple_dat_p(adat) && simple_dat_p(bdat) &&
6378  m_gregorian_p(adat) == m_gregorian_p(bdat)))
6379  return cmp_dd(self, other);
6380 
6381  {
6382  VALUE a_nth, b_nth;
6383  int a_jd, b_jd;
6384 
6385  m_canonicalize_jd(self, adat);
6386  m_canonicalize_jd(other, bdat);
6387  a_nth = m_nth(adat);
6388  b_nth = m_nth(bdat);
6389  if (f_eqeq_p(a_nth, b_nth)) {
6390  a_jd = m_jd(adat);
6391  b_jd = m_jd(bdat);
6392  if (a_jd == b_jd) {
6393  return INT2FIX(0);
6394  }
6395  else if (a_jd < b_jd) {
6396  return INT2FIX(-1);
6397  }
6398  else {
6399  return INT2FIX(1);
6400  }
6401  }
6402  else if (f_lt_p(a_nth, b_nth)) {
6403  return INT2FIX(-1);
6404  }
6405  else {
6406  return INT2FIX(1);
6407  }
6408  }
6409  }
6410 }
6411 
6412 static VALUE
6413 equal_gen(VALUE self, VALUE other)
6414 {
6415  get_d1(self);
6416 
6417  if (k_numeric_p(other))
6418  return f_eqeq_p(m_real_local_jd(dat), other);
6419  else if (k_date_p(other))
6420  return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
6421  return rb_num_coerce_cmp(self, other, id_eqeq_p);
6422 }
6423 
6424 /*
6425  * call-seq:
6426  * d === other -> bool
6427  *
6428  * Returns true if they are the same day.
6429  *
6430  * Date.new(2001,2,3) === Date.new(2001,2,3)
6431  * #=> true
6432  * Date.new(2001,2,3) === Date.new(2001,2,4)
6433  * #=> false
6434  * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,12)
6435  * #=> true
6436  * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,0,0,0,'+24:00')
6437  * #=> true
6438  * DateTime.new(2001,2,3) === DateTime.new(2001,2,4,0,0,0,'+24:00')
6439  * #=> false
6440  */
6441 static VALUE
6442 d_lite_equal(VALUE self, VALUE other)
6443 {
6444  if (!k_date_p(other))
6445  return equal_gen(self, other);
6446 
6447  {
6448  get_d2(self, other);
6449 
6450  if (!(m_gregorian_p(adat) == m_gregorian_p(bdat)))
6451  return equal_gen(self, other);
6452 
6453  {
6454  VALUE a_nth, b_nth;
6455  int a_jd, b_jd;
6456 
6457  m_canonicalize_jd(self, adat);
6458  m_canonicalize_jd(other, bdat);
6459  a_nth = m_nth(adat);
6460  b_nth = m_nth(bdat);
6461  a_jd = m_local_jd(adat);
6462  b_jd = m_local_jd(bdat);
6463  if (f_eqeq_p(a_nth, b_nth) &&
6464  a_jd == b_jd)
6465  return Qtrue;
6466  return Qfalse;
6467  }
6468  }
6469 }
6470 
6471 /* :nodoc: */
6472 static VALUE
6473 d_lite_eql_p(VALUE self, VALUE other)
6474 {
6475  if (!k_date_p(other))
6476  return Qfalse;
6477  return f_zero_p(d_lite_cmp(self, other));
6478 }
6479 
6480 /* :nodoc: */
6481 static VALUE
6482 d_lite_hash(VALUE self)
6483 {
6484  st_index_t v, h[4];
6485 
6486  get_d1(self);
6487  h[0] = m_nth(dat);
6488  h[1] = m_jd(dat);
6489  h[2] = m_df(dat);
6490  h[3] = m_sf(dat);
6491  v = rb_memhash(h, sizeof(h));
6492  return ST2FIX(v);
6493 }
6494 
6495 #include "date_tmx.h"
6496 static void set_tmx(VALUE, struct tmx *);
6497 static VALUE strftimev(const char *, VALUE,
6498  void (*)(VALUE, struct tmx *));
6499 
6500 /*
6501  * call-seq:
6502  * d.to_s -> string
6503  *
6504  * Returns a string in an ISO 8601 format. (This method doesn't use the
6505  * expanded representations.)
6506  *
6507  * Date.new(2001,2,3).to_s #=> "2001-02-03"
6508  */
6509 static VALUE
6510 d_lite_to_s(VALUE self)
6511 {
6512  return strftimev("%Y-%m-%d", self, set_tmx);
6513 }
6514 
6515 #ifndef NDEBUG
6516 static VALUE
6517 mk_inspect_raw(union DateData *x, VALUE klass)
6518 {
6519  char flags[6];
6520 
6521  flags[0] = (x->flags & COMPLEX_DAT) ? 'C' : 'S';
6522  flags[1] = (x->flags & HAVE_JD) ? 'j' : '-';
6523  flags[2] = (x->flags & HAVE_DF) ? 'd' : '-';
6524  flags[3] = (x->flags & HAVE_CIVIL) ? 'c' : '-';
6525  flags[4] = (x->flags & HAVE_TIME) ? 't' : '-';
6526  flags[5] = '\0';
6527 
6528  if (simple_dat_p(x)) {
6530  "#<%"PRIsVALUE": "
6531  "(%+"PRIsVALUE"th,%dj),+0s,%.0fj; "
6532  "%dy%dm%dd; %s>",
6533  klass,
6534  x->s.nth, x->s.jd, x->s.sg,
6535 #ifndef USE_PACK
6536  x->s.year, x->s.mon, x->s.mday,
6537 #else
6538  x->s.year,
6539  EX_MON(x->s.pc), EX_MDAY(x->s.pc),
6540 #endif
6541  flags);
6542  }
6543  else {
6545  "#<%"PRIsVALUE": "
6546  "(%+"PRIsVALUE"th,%dj,%ds,%+"PRIsVALUE"n),"
6547  "%+ds,%.0fj; "
6548  "%dy%dm%dd %dh%dm%ds; %s>",
6549  klass,
6550  x->c.nth, x->c.jd, x->c.df, x->c.sf,
6551  x->c.of, x->c.sg,
6552 #ifndef USE_PACK
6553  x->c.year, x->c.mon, x->c.mday,
6554  x->c.hour, x->c.min, x->c.sec,
6555 #else
6556  x->c.year,
6557  EX_MON(x->c.pc), EX_MDAY(x->c.pc),
6558  EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
6559  EX_SEC(x->c.pc),
6560 #endif
6561  flags);
6562  }
6563 }
6564 
6565 static VALUE
6566 d_lite_inspect_raw(VALUE self)
6567 {
6568  get_d1(self);
6569  return mk_inspect_raw(dat, rb_obj_class(self));
6570 }
6571 #endif
6572 
6573 static VALUE
6574 mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
6575 {
6577  "#<%"PRIsVALUE": %"PRIsVALUE" "
6578  "((%+"PRIsVALUE"j,%ds,%+"PRIsVALUE"n),%+ds,%.0fj)>",
6579  klass, to_s,
6580  m_real_jd(x), m_df(x), m_sf(x),
6581  m_of(x), m_sg(x));
6582 }
6583 
6584 /*
6585  * call-seq:
6586  * d.inspect -> string
6587  *
6588  * Returns the value as a string for inspection.
6589  *
6590  * Date.new(2001,2,3).inspect
6591  * #=> "#<Date: 2001-02-03>"
6592  * DateTime.new(2001,2,3,4,5,6,'-7').inspect
6593  * #=> "#<DateTime: 2001-02-03T04:05:06-07:00>"
6594  */
6595 static VALUE
6596 d_lite_inspect(VALUE self)
6597 {
6598  get_d1(self);
6599  return mk_inspect(dat, rb_obj_class(self), self);
6600 }
6601 
6602 #include <errno.h>
6603 #include "date_tmx.h"
6604 
6605 size_t date_strftime(char *s, size_t maxsize, const char *format,
6606  const struct tmx *tmx);
6607 
6608 #define SMALLBUF 100
6609 static size_t
6610 date_strftime_alloc(char **buf, const char *format,
6611  struct tmx *tmx)
6612 {
6613  size_t size, len, flen;
6614 
6615  (*buf)[0] = '\0';
6616  flen = strlen(format);
6617  if (flen == 0) {
6618  return 0;
6619  }
6620  errno = 0;
6621  len = date_strftime(*buf, SMALLBUF, format, tmx);
6622  if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
6623  for (size=1024; ; size*=2) {
6624  *buf = xmalloc(size);
6625  (*buf)[0] = '\0';
6626  len = date_strftime(*buf, size, format, tmx);
6627  /*
6628  * buflen can be zero EITHER because there's not enough
6629  * room in the string, or because the control command
6630  * goes to the empty string. Make a reasonable guess that
6631  * if the buffer is 1024 times bigger than the length of the
6632  * format string, it's not failing for lack of room.
6633  */
6634  if (len > 0) break;
6635  xfree(*buf);
6636  if (size >= 1024 * flen) {
6637  rb_sys_fail(format);
6638  break;
6639  }
6640  }
6641  return len;
6642 }
6643 
6644 static VALUE
6645 tmx_m_secs(union DateData *x)
6646 {
6647  VALUE s;
6648  int df;
6649 
6650  s = day_to_sec(f_sub(m_real_jd(x),
6652  if (simple_dat_p(x))
6653  return s;
6654  df = m_df(x);
6655  if (df)
6656  s = f_add(s, INT2FIX(df));
6657  return s;
6658 }
6659 
6660 #define MILLISECOND_IN_NANOSECONDS 1000000
6661 
6662 static VALUE
6663 tmx_m_msecs(union DateData *x)
6664 {
6665  VALUE s, sf;
6666 
6667  s = sec_to_ms(tmx_m_secs(x));
6668  if (simple_dat_p(x))
6669  return s;
6670  sf = m_sf(x);
6671  if (f_nonzero_p(sf))
6673  return s;
6674 }
6675 
6676 static int
6677 tmx_m_of(union DateData *x)
6678 {
6679  return m_of(x);
6680 }
6681 
6682 static char *
6683 tmx_m_zone(union DateData *x)
6684 {
6685  VALUE zone = m_zone(x);
6686  /* TODO: fix potential dangling pointer */
6687  return RSTRING_PTR(zone);
6688 }
6689 
6690 static const struct tmx_funcs tmx_funcs = {
6691  (VALUE (*)(void *))m_real_year,
6692  (int (*)(void *))m_yday,
6693  (int (*)(void *))m_mon,
6694  (int (*)(void *))m_mday,
6695  (VALUE (*)(void *))m_real_cwyear,
6696  (int (*)(void *))m_cweek,
6697  (int (*)(void *))m_cwday,
6698  (int (*)(void *))m_wnum0,
6699  (int (*)(void *))m_wnum1,
6700  (int (*)(void *))m_wday,
6701  (int (*)(void *))m_hour,
6702  (int (*)(void *))m_min,
6703  (int (*)(void *))m_sec,
6704  (VALUE (*)(void *))m_sf_in_sec,
6705  (VALUE (*)(void *))tmx_m_secs,
6706  (VALUE (*)(void *))tmx_m_msecs,
6707  (int (*)(void *))tmx_m_of,
6708  (char *(*)(void *))tmx_m_zone
6709 };
6710 
6711 static void
6712 set_tmx(VALUE self, struct tmx *tmx)
6713 {
6714  get_d1(self);
6715  tmx->dat = (void *)dat;
6716  tmx->funcs = &tmx_funcs;
6717 }
6718 
6719 static VALUE
6720 date_strftime_internal(int argc, VALUE *argv, VALUE self,
6721  const char *default_fmt,
6722  void (*func)(VALUE, struct tmx *))
6723 {
6724  VALUE vfmt;
6725  const char *fmt;
6726  long len;
6727  char buffer[SMALLBUF], *buf = buffer;
6728  struct tmx tmx;
6729  VALUE str;
6730 
6731  rb_scan_args(argc, argv, "01", &vfmt);
6732 
6733  if (argc < 1)
6734  vfmt = rb_usascii_str_new2(default_fmt);
6735  else {
6736  StringValue(vfmt);
6737  if (!rb_enc_str_asciicompat_p(vfmt)) {
6739  "format should have ASCII compatible encoding");
6740  }
6741  }
6742  fmt = RSTRING_PTR(vfmt);
6743  len = RSTRING_LEN(vfmt);
6744  (*func)(self, &tmx);
6745  if (memchr(fmt, '\0', len)) {
6746  /* Ruby string may contain \0's. */
6747  const char *p = fmt, *pe = fmt + len;
6748 
6749  str = rb_str_new(0, 0);
6750  while (p < pe) {
6751  len = date_strftime_alloc(&buf, p, &tmx);
6752  rb_str_cat(str, buf, len);
6753  p += strlen(p);
6754  if (buf != buffer) {
6755  xfree(buf);
6756  buf = buffer;
6757  }
6758  for (fmt = p; p < pe && !*p; ++p);
6759  if (p > fmt) rb_str_cat(str, fmt, p - fmt);
6760  }
6761  rb_enc_copy(str, vfmt);
6762  return str;
6763  }
6764  else
6765  len = date_strftime_alloc(&buf, fmt, &tmx);
6766 
6767  str = rb_str_new(buf, len);
6768  if (buf != buffer) xfree(buf);
6769  rb_enc_copy(str, vfmt);
6770  return str;
6771 }
6772 
6773 /*
6774  * call-seq:
6775  * d.strftime([format='%F']) -> string
6776  *
6777  * Formats date according to the directives in the given format
6778  * string.
6779  * The directives begin with a percent (%) character.
6780  * Any text not listed as a directive will be passed through to the
6781  * output string.
6782  *
6783  * A directive consists of a percent (%) character,
6784  * zero or more flags, an optional minimum field width,
6785  * an optional modifier, and a conversion specifier
6786  * as follows.
6787  *
6788  * %<flags><width><modifier><conversion>
6789  *
6790  * Flags:
6791  * - don't pad a numerical output.
6792  * _ use spaces for padding.
6793  * 0 use zeros for padding.
6794  * ^ upcase the result string.
6795  * # change case.
6796  *
6797  * The minimum field width specifies the minimum width.
6798  *
6799  * The modifiers are "E", "O", ":", "::" and ":::".
6800  * "E" and "O" are ignored. No effect to result currently.
6801  *
6802  * Format directives:
6803  *
6804  * Date (Year, Month, Day):
6805  * %Y - Year with century (can be negative, 4 digits at least)
6806  * -0001, 0000, 1995, 2009, 14292, etc.
6807  * %C - year / 100 (round down. 20 in 2009)
6808  * %y - year % 100 (00..99)
6809  *
6810  * %m - Month of the year, zero-padded (01..12)
6811  * %_m blank-padded ( 1..12)
6812  * %-m no-padded (1..12)
6813  * %B - The full month name (``January'')
6814  * %^B uppercased (``JANUARY'')
6815  * %b - The abbreviated month name (``Jan'')
6816  * %^b uppercased (``JAN'')
6817  * %h - Equivalent to %b
6818  *
6819  * %d - Day of the month, zero-padded (01..31)
6820  * %-d no-padded (1..31)
6821  * %e - Day of the month, blank-padded ( 1..31)
6822  *
6823  * %j - Day of the year (001..366)
6824  *
6825  * Time (Hour, Minute, Second, Subsecond):
6826  * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
6827  * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
6828  * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
6829  * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
6830  * %P - Meridian indicator, lowercase (``am'' or ``pm'')
6831  * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
6832  *
6833  * %M - Minute of the hour (00..59)
6834  *
6835  * %S - Second of the minute (00..60)
6836  *
6837  * %L - Millisecond of the second (000..999)
6838  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
6839  * %3N millisecond (3 digits) %15N femtosecond (15 digits)
6840  * %6N microsecond (6 digits) %18N attosecond (18 digits)
6841  * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
6842  * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
6843  *
6844  * Time zone:
6845  * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
6846  * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
6847  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
6848  * %:::z - hour, minute and second offset from UTC
6849  * (e.g. +09, +09:30, +09:30:30)
6850  * %Z - Equivalent to %:z (e.g. +09:00)
6851  *
6852  * Weekday:
6853  * %A - The full weekday name (``Sunday'')
6854  * %^A uppercased (``SUNDAY'')
6855  * %a - The abbreviated name (``Sun'')
6856  * %^a uppercased (``SUN'')
6857  * %u - Day of the week (Monday is 1, 1..7)
6858  * %w - Day of the week (Sunday is 0, 0..6)
6859  *
6860  * ISO 8601 week-based year and week number:
6861  * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
6862  * The days in the year before the first week are in the last week of
6863  * the previous year.
6864  * %G - The week-based year
6865  * %g - The last 2 digits of the week-based year (00..99)
6866  * %V - Week number of the week-based year (01..53)
6867  *
6868  * Week number:
6869  * The week 1 of YYYY starts with a Sunday or Monday (according to %U
6870  * or %W). The days in the year before the first week are in week 0.
6871  * %U - Week number of the year. The week starts with Sunday. (00..53)
6872  * %W - Week number of the year. The week starts with Monday. (00..53)
6873  *
6874  * Seconds since the Unix Epoch:
6875  * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
6876  * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
6877  *
6878  * Literal string:
6879  * %n - Newline character (\n)
6880  * %t - Tab character (\t)
6881  * %% - Literal ``%'' character
6882  *
6883  * Combination:
6884  * %c - date and time (%a %b %e %T %Y)
6885  * %D - Date (%m/%d/%y)
6886  * %F - The ISO 8601 date format (%Y-%m-%d)
6887  * %v - VMS date (%e-%b-%Y)
6888  * %x - Same as %D
6889  * %X - Same as %T
6890  * %r - 12-hour time (%I:%M:%S %p)
6891  * %R - 24-hour time (%H:%M)
6892  * %T - 24-hour time (%H:%M:%S)
6893  * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
6894  *
6895  * This method is similar to the strftime() function defined in ISO C
6896  * and POSIX.
6897  * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
6898  * are locale dependent in the function.
6899  * However, this method is locale independent.
6900  * So, the result may differ even if the same format string is used in other
6901  * systems such as C.
6902  * It is good practice to avoid %x and %X because there are corresponding
6903  * locale independent representations, %D and %T.
6904  *
6905  * Examples:
6906  *
6907  * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
6908  * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
6909  * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
6910  * d.strftime("at %I:%M%p") #=> "at 08:37AM"
6911  *
6912  * Various ISO 8601 formats:
6913  * %Y%m%d => 20071119 Calendar date (basic)
6914  * %F => 2007-11-19 Calendar date (extended)
6915  * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
6916  * %Y => 2007 Calendar date, reduced accuracy, specific year
6917  * %C => 20 Calendar date, reduced accuracy, specific century
6918  * %Y%j => 2007323 Ordinal date (basic)
6919  * %Y-%j => 2007-323 Ordinal date (extended)
6920  * %GW%V%u => 2007W471 Week date (basic)
6921  * %G-W%V-%u => 2007-W47-1 Week date (extended)
6922  * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
6923  * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
6924  * %H%M%S => 083748 Local time (basic)
6925  * %T => 08:37:48 Local time (extended)
6926  * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
6927  * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
6928  * %H => 08 Local time, reduced accuracy, specific hour
6929  * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
6930  * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
6931  * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
6932  * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
6933  * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
6934  * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
6935  * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
6936  * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
6937  * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
6938  * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
6939  * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
6940  * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
6941  * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
6942  * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
6943  * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
6944  * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
6945  * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
6946  * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
6947  *
6948  * See also strftime(3) and ::strptime.
6949  */
6950 static VALUE
6951 d_lite_strftime(int argc, VALUE *argv, VALUE self)
6952 {
6953  return date_strftime_internal(argc, argv, self,
6954  "%Y-%m-%d", set_tmx);
6955 }
6956 
6957 static VALUE
6958 strftimev(const char *fmt, VALUE self,
6959  void (*func)(VALUE, struct tmx *))
6960 {
6961  char buffer[SMALLBUF], *buf = buffer;
6962  struct tmx tmx;
6963  long len;
6964  VALUE str;
6965 
6966  (*func)(self, &tmx);
6967  len = date_strftime_alloc(&buf, fmt, &tmx);
6968  RB_GC_GUARD(self);
6970  if (buf != buffer) xfree(buf);
6971  return str;
6972 }
6973 
6974 /*
6975  * call-seq:
6976  * d.asctime -> string
6977  * d.ctime -> string
6978  *
6979  * Returns a string in asctime(3) format (but without "\n\0" at the
6980  * end). This method is equivalent to strftime('%c').
6981  *
6982  * See also asctime(3) or ctime(3).
6983  */
6984 static VALUE
6985 d_lite_asctime(VALUE self)
6986 {
6987  return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx);
6988 }
6989 
6990 /*
6991  * call-seq:
6992  * d.iso8601 -> string
6993  * d.xmlschema -> string
6994  *
6995  * This method is equivalent to strftime('%F').
6996  */
6997 static VALUE
6998 d_lite_iso8601(VALUE self)
6999 {
7000  return strftimev("%Y-%m-%d", self, set_tmx);
7001 }
7002 
7003 /*
7004  * call-seq:
7005  * d.rfc3339 -> string
7006  *
7007  * This method is equivalent to strftime('%FT%T%:z').
7008  */
7009 static VALUE
7010 d_lite_rfc3339(VALUE self)
7011 {
7012  return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
7013 }
7014 
7015 /*
7016  * call-seq:
7017  * d.rfc2822 -> string
7018  * d.rfc822 -> string
7019  *
7020  * This method is equivalent to strftime('%a, %-d %b %Y %T %z').
7021  */
7022 static VALUE
7023 d_lite_rfc2822(VALUE self)
7024 {
7025  return strftimev("%a, %-d %b %Y %T %z", self, set_tmx);
7026 }
7027 
7028 /*
7029  * call-seq:
7030  * d.httpdate -> string
7031  *
7032  * This method is equivalent to strftime('%a, %d %b %Y %T GMT').
7033  * See also RFC 2616.
7034  */
7035 static VALUE
7036 d_lite_httpdate(VALUE self)
7037 {
7038  volatile VALUE dup = dup_obj_with_new_offset(self, 0);
7039  return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx);
7040 }
7041 
7042 enum {
7045 };
7046 
7047 static const char *
7048 jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
7049 {
7050  if (FIXNUM_P(jd)) {
7051  long d = FIX2INT(jd);
7052  long s;
7053  char c;
7054  if (d < 2405160)
7055  return "%Y-%m-%d";
7056  if (d < 2419614) {
7057  c = 'M';
7058  s = 1867;
7059  }
7060  else if (d < 2424875) {
7061  c = 'T';
7062  s = 1911;
7063  }
7064  else if (d < 2447535) {
7065  c = 'S';
7066  s = 1925;
7067  }
7068  else if (d < 2458605) {
7069  c = 'H';
7070  s = 1988;
7071  }
7072  else {
7073  c = 'R';
7074  s = 2018;
7075  }
7076  snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s);
7077  return fmt;
7078  }
7079  return "%Y-%m-%d";
7080 }
7081 
7082 /*
7083  * call-seq:
7084  * d.jisx0301 -> string
7085  *
7086  * Returns a string in a JIS X 0301 format.
7087  *
7088  * Date.new(2001,2,3).jisx0301 #=> "H13.02.03"
7089  */
7090 static VALUE
7091 d_lite_jisx0301(VALUE self)
7092 {
7093  char fmtbuf[JISX0301_DATE_SIZE];
7094  const char *fmt;
7095 
7096  get_d1(self);
7097  fmt = jisx0301_date_format(fmtbuf, sizeof(fmtbuf),
7098  m_real_local_jd(dat),
7099  m_real_year(dat));
7100  return strftimev(fmt, self, set_tmx);
7101 }
7102 
7103 #ifndef NDEBUG
7104 static VALUE
7105 d_lite_marshal_dump_old(VALUE self)
7106 {
7107  VALUE a;
7108 
7109  get_d1(self);
7110 
7111  a = rb_ary_new3(3,
7112  m_ajd(dat),
7113  m_of_in_day(dat),
7114  DBL2NUM(m_sg(dat)));
7115 
7116  if (FL_TEST(self, FL_EXIVAR)) {
7117  rb_copy_generic_ivar(a, self);
7118  FL_SET(a, FL_EXIVAR);
7119  }
7120 
7121  return a;
7122 }
7123 #endif
7124 
7125 /* :nodoc: */
7126 static VALUE
7127 d_lite_marshal_dump(VALUE self)
7128 {
7129  VALUE a;
7130 
7131  get_d1(self);
7132 
7133  a = rb_ary_new3(6,
7134  m_nth(dat),
7135  INT2FIX(m_jd(dat)),
7136  INT2FIX(m_df(dat)),
7137  m_sf(dat),
7138  INT2FIX(m_of(dat)),
7139  DBL2NUM(m_sg(dat)));
7140 
7141  if (FL_TEST(self, FL_EXIVAR)) {
7142  rb_copy_generic_ivar(a, self);
7143  FL_SET(a, FL_EXIVAR);
7144  }
7145 
7146  return a;
7147 }
7148 
7149 /* :nodoc: */
7150 static VALUE
7151 d_lite_marshal_load(VALUE self, VALUE a)
7152 {
7153  VALUE nth, sf;
7154  int jd, df, of;
7155  double sg;
7156 
7157  get_d1(self);
7158 
7159  rb_check_frozen(self);
7160 
7161  if (!RB_TYPE_P(a, T_ARRAY))
7162  rb_raise(rb_eTypeError, "expected an array");
7163 
7164  switch (RARRAY_LEN(a)) {
7165  case 2: /* 1.6.x */
7166  case 3: /* 1.8.x, 1.9.2 */
7167  {
7168  VALUE ajd, vof, vsg;
7169 
7170  if (RARRAY_LEN(a) == 2) {
7171  ajd = f_sub(RARRAY_AREF(a, 0), half_days_in_day);
7172  vof = INT2FIX(0);
7173  vsg = RARRAY_AREF(a, 1);
7174  if (!k_numeric_p(vsg))
7175  vsg = DBL2NUM(RTEST(vsg) ? GREGORIAN : JULIAN);
7176  }
7177  else {
7178  ajd = RARRAY_AREF(a, 0);
7179  vof = RARRAY_AREF(a, 1);
7180  vsg = RARRAY_AREF(a, 2);
7181  }
7182 
7183  old_to_new(ajd, vof, vsg,
7184  &nth, &jd, &df, &sf, &of, &sg);
7185  }
7186  break;
7187  case 6:
7188  {
7189  nth = RARRAY_AREF(a, 0);
7190  jd = NUM2INT(RARRAY_AREF(a, 1));
7191  df = NUM2INT(RARRAY_AREF(a, 2));
7192  sf = RARRAY_AREF(a, 3);
7193  of = NUM2INT(RARRAY_AREF(a, 4));
7194  sg = NUM2DBL(RARRAY_AREF(a, 5));
7195  }
7196  break;
7197  default:
7198  rb_raise(rb_eTypeError, "invalid size");
7199  break;
7200  }
7201 
7202  if (simple_dat_p(dat)) {
7203  if (df || !f_zero_p(sf) || of) {
7205  "cannot load complex into simple");
7206  }
7207  set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
7208  } else {
7209  set_to_complex(self, &dat->c, nth, jd, df, sf, of, sg,
7210  0, 0, 0, 0, 0, 0,
7211  HAVE_JD | HAVE_DF);
7212  }
7213 
7214  if (FL_TEST(a, FL_EXIVAR)) {
7215  rb_copy_generic_ivar(self, a);
7216  FL_SET(self, FL_EXIVAR);
7217  }
7218 
7219  return self;
7220 }
7221 
7222 /* :nodoc: */
7223 static VALUE
7224 date_s__load(VALUE klass, VALUE s)
7225 {
7226  VALUE a, obj;
7227 
7228  a = rb_marshal_load(s);
7229  obj = d_lite_s_alloc(klass);
7230  return d_lite_marshal_load(obj, a);
7231 }
7232 
7233 /* datetime */
7234 
7235 /*
7236  * call-seq:
7237  * DateTime.jd([jd=0[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]) -> datetime
7238  *
7239  * Creates a DateTime object denoting the given chronological Julian
7240  * day number.
7241  *
7242  * DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7243  * DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...>
7244  * DateTime.jd(Rational('0.5'))
7245  * #=> #<DateTime: -4712-01-01T12:00:00+00:00 ...>
7246  */
7247 static VALUE
7248 datetime_s_jd(int argc, VALUE *argv, VALUE klass)
7249 {
7250  VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
7251  int h, min, s, rof;
7252  double sg;
7253 
7254  rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
7255 
7256  jd = INT2FIX(0);
7257 
7258  h = min = s = 0;
7259  fr2 = INT2FIX(0);
7260  rof = 0;
7261  sg = DEFAULT_SG;
7262 
7263  switch (argc) {
7264  case 6:
7265  val2sg(vsg, sg);
7266  case 5:
7267  val2off(vof, rof);
7268  case 4:
7269  check_numeric(vs, "second");
7270  num2int_with_frac(s, positive_inf);
7271  case 3:
7272  check_numeric(vmin, "minute");
7273  num2int_with_frac(min, 3);
7274  case 2:
7275  check_numeric(vh, "hour");
7276  num2int_with_frac(h, 2);
7277  case 1:
7278  check_numeric(vjd, "jd");
7279  num2num_with_frac(jd, 1);
7280  }
7281 
7282  {
7283  VALUE nth;
7284  int rh, rmin, rs, rjd, rjd2;
7285 
7286  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7287  rb_raise(eDateError, "invalid date");
7288  canon24oc();
7289 
7290  decode_jd(jd, &nth, &rjd);
7291  rjd2 = jd_local_to_utc(rjd,
7292  time_to_df(rh, rmin, rs),
7293  rof);
7294 
7295  ret = d_complex_new_internal(klass,
7296  nth, rjd2,
7297  0, INT2FIX(0),
7298  rof, sg,
7299  0, 0, 0,
7300  rh, rmin, rs,
7301  HAVE_JD | HAVE_TIME);
7302  }
7303  add_frac();
7304  return ret;
7305 }
7306 
7307 /*
7308  * call-seq:
7309  * DateTime.ordinal([year=-4712[, yday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]) -> datetime
7310  *
7311  * Creates a DateTime object denoting the given ordinal date.
7312  *
7313  * DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7314  * DateTime.ordinal(2001,34,4,5,6,'+7')
7315  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7316  * DateTime.ordinal(2001,-332,-20,-55,-54,'+7')
7317  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7318  */
7319 static VALUE
7320 datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
7321 {
7322  VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7323  int d, h, min, s, rof;
7324  double sg;
7325 
7326  rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
7327 
7328  y = INT2FIX(-4712);
7329  d = 1;
7330 
7331  h = min = s = 0;
7332  fr2 = INT2FIX(0);
7333  rof = 0;
7334  sg = DEFAULT_SG;
7335 
7336  switch (argc) {
7337  case 7:
7338  val2sg(vsg, sg);
7339  case 6:
7340  val2off(vof, rof);
7341  case 5:
7342  check_numeric(vs, "second");
7343  num2int_with_frac(s, positive_inf);
7344  case 4:
7345  check_numeric(vmin, "minute");
7346  num2int_with_frac(min, 4);
7347  case 3:
7348  check_numeric(vh, "hour");
7349  num2int_with_frac(h, 3);
7350  case 2:
7351  check_numeric(vd, "yday");
7352  num2int_with_frac(d, 2);
7353  case 1:
7354  check_numeric(vy, "year");
7355  y = vy;
7356  }
7357 
7358  {
7359  VALUE nth;
7360  int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
7361 
7362  if (!valid_ordinal_p(y, d, sg,
7363  &nth, &ry,
7364  &rd, &rjd,
7365  &ns))
7366  rb_raise(eDateError, "invalid date");
7367  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7368  rb_raise(eDateError, "invalid date");
7369  canon24oc();
7370 
7371  rjd2 = jd_local_to_utc(rjd,
7372  time_to_df(rh, rmin, rs),
7373  rof);
7374 
7375  ret = d_complex_new_internal(klass,
7376  nth, rjd2,
7377  0, INT2FIX(0),
7378  rof, sg,
7379  0, 0, 0,
7380  rh, rmin, rs,
7381  HAVE_JD | HAVE_TIME);
7382  }
7383  add_frac();
7384  return ret;
7385 }
7386 
7387 /*
7388  * call-seq:
7389  * DateTime.civil([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7390  * DateTime.new([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7391  *
7392  * Creates a DateTime object denoting the given calendar date.
7393  *
7394  * DateTime.new(2001,2,3) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
7395  * DateTime.new(2001,2,3,4,5,6,'+7')
7396  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7397  * DateTime.new(2001,-11,-26,-20,-55,-54,'+7')
7398  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7399  */
7400 static VALUE
7401 datetime_s_civil(int argc, VALUE *argv, VALUE klass)
7402 {
7403  return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
7404 }
7405 
7406 static VALUE
7407 datetime_initialize(int argc, VALUE *argv, VALUE self)
7408 {
7409  VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7410  int m, d, h, min, s, rof;
7411  double sg;
7412  struct ComplexDateData *dat = rb_check_typeddata(self, &d_lite_type);
7413 
7414  if (!complex_dat_p(dat)) {
7415  rb_raise(rb_eTypeError, "DateTime expected");
7416  }
7417 
7418  rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
7419 
7420  y = INT2FIX(-4712);
7421  m = 1;
7422  d = 1;
7423 
7424  h = min = s = 0;
7425  fr2 = INT2FIX(0);
7426  rof = 0;
7427  sg = DEFAULT_SG;
7428 
7429  switch (argc) {
7430  case 8:
7431  val2sg(vsg, sg);
7432  case 7:
7433  val2off(vof, rof);
7434  case 6:
7435  check_numeric(vs, "second");
7436  num2int_with_frac(s, positive_inf);
7437  case 5:
7438  check_numeric(vmin, "minute");
7439  num2int_with_frac(min, 5);
7440  case 4:
7441  check_numeric(vh, "hour");
7442  num2int_with_frac(h, 4);
7443  case 3:
7444  check_numeric(vd, "day");
7445  num2int_with_frac(d, 3);
7446  case 2:
7447  check_numeric(vm, "month");
7448  m = NUM2INT(vm);
7449  case 1:
7450  check_numeric(vy, "year");
7451  y = vy;
7452  }
7453 
7454  if (guess_style(y, sg) < 0) {
7455  VALUE nth;
7456  int ry, rm, rd, rh, rmin, rs;
7457 
7458  if (!valid_gregorian_p(y, m, d,
7459  &nth, &ry,
7460  &rm, &rd))
7461  rb_raise(eDateError, "invalid date");
7462  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7463  rb_raise(eDateError, "invalid date");
7464  canon24oc();
7465 
7466  set_to_complex(self, dat,
7467  nth, 0,
7468  0, INT2FIX(0),
7469  rof, sg,
7470  ry, rm, rd,
7471  rh, rmin, rs,
7472  HAVE_CIVIL | HAVE_TIME);
7473  }
7474  else {
7475  VALUE nth;
7476  int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns;
7477 
7478  if (!valid_civil_p(y, m, d, sg,
7479  &nth, &ry,
7480  &rm, &rd, &rjd,
7481  &ns))
7482  rb_raise(eDateError, "invalid date");
7483  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7484  rb_raise(eDateError, "invalid date");
7485  canon24oc();
7486 
7487  rjd2 = jd_local_to_utc(rjd,
7488  time_to_df(rh, rmin, rs),
7489  rof);
7490 
7491  set_to_complex(self, dat,
7492  nth, rjd2,
7493  0, INT2FIX(0),
7494  rof, sg,
7495  ry, rm, rd,
7496  rh, rmin, rs,
7498  }
7499  ret = self;
7500  add_frac();
7501  return ret;
7502 }
7503 
7504 /*
7505  * call-seq:
7506  * DateTime.commercial([cwyear=-4712[, cweek=1[, cwday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
7507  *
7508  * Creates a DateTime object denoting the given week date.
7509  *
7510  * DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...>
7511  * DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...>
7512  * DateTime.commercial(2001,5,6,4,5,6,'+7')
7513  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7514  */
7515 static VALUE
7516 datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
7517 {
7518  VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7519  int w, d, h, min, s, rof;
7520  double sg;
7521 
7522  rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
7523 
7524  y = INT2FIX(-4712);
7525  w = 1;
7526  d = 1;
7527 
7528  h = min = s = 0;
7529  fr2 = INT2FIX(0);
7530  rof = 0;
7531  sg = DEFAULT_SG;
7532 
7533  switch (argc) {
7534  case 8:
7535  val2sg(vsg, sg);
7536  case 7:
7537  val2off(vof, rof);
7538  case 6:
7539  check_numeric(vs, "second");
7540  num2int_with_frac(s, positive_inf);
7541  case 5:
7542  check_numeric(vmin, "minute");
7543  num2int_with_frac(min, 5);
7544  case 4:
7545  check_numeric(vh, "hour");
7546  num2int_with_frac(h, 4);
7547  case 3:
7548  check_numeric(vd, "cwday");
7549  num2int_with_frac(d, 3);
7550  case 2:
7551  check_numeric(vw, "cweek");
7552  w = NUM2INT(vw);
7553  case 1:
7554  check_numeric(vy, "year");
7555  y = vy;
7556  }
7557 
7558  {
7559  VALUE nth;
7560  int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
7561 
7562  if (!valid_commercial_p(y, w, d, sg,
7563  &nth, &ry,
7564  &rw, &rd, &rjd,
7565  &ns))
7566  rb_raise(eDateError, "invalid date");
7567  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7568  rb_raise(eDateError, "invalid date");
7569  canon24oc();
7570 
7571  rjd2 = jd_local_to_utc(rjd,
7572  time_to_df(rh, rmin, rs),
7573  rof);
7574 
7575  ret = d_complex_new_internal(klass,
7576  nth, rjd2,
7577  0, INT2FIX(0),
7578  rof, sg,
7579  0, 0, 0,
7580  rh, rmin, rs,
7581  HAVE_JD | HAVE_TIME);
7582  }
7583  add_frac();
7584  return ret;
7585 }
7586 
7587 #ifndef NDEBUG
7588 static VALUE
7589 datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
7590 {
7591  VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7592  int w, d, f, h, min, s, rof;
7593  double sg;
7594 
7595  rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
7596  &vh, &vmin, &vs, &vof, &vsg);
7597 
7598  y = INT2FIX(-4712);
7599  w = 0;
7600  d = 1;
7601  f = 0;
7602 
7603  h = min = s = 0;
7604  fr2 = INT2FIX(0);
7605  rof = 0;
7606  sg = DEFAULT_SG;
7607 
7608  switch (argc) {
7609  case 9:
7610  val2sg(vsg, sg);
7611  case 8:
7612  val2off(vof, rof);
7613  case 7:
7614  num2int_with_frac(s, positive_inf);
7615  case 6:
7616  num2int_with_frac(min, 6);
7617  case 5:
7618  num2int_with_frac(h, 5);
7619  case 4:
7620  f = NUM2INT(vf);
7621  case 3:
7622  num2int_with_frac(d, 4);
7623  case 2:
7624  w = NUM2INT(vw);
7625  case 1:
7626  y = vy;
7627  }
7628 
7629  {
7630  VALUE nth;
7631  int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
7632 
7633  if (!valid_weeknum_p(y, w, d, f, sg,
7634  &nth, &ry,
7635  &rw, &rd, &rjd,
7636  &ns))
7637  rb_raise(eDateError, "invalid date");
7638  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7639  rb_raise(eDateError, "invalid date");
7640  canon24oc();
7641 
7642  rjd2 = jd_local_to_utc(rjd,
7643  time_to_df(rh, rmin, rs),
7644  rof);
7645  ret = d_complex_new_internal(klass,
7646  nth, rjd2,
7647  0, INT2FIX(0),
7648  rof, sg,
7649  0, 0, 0,
7650  rh, rmin, rs,
7651  HAVE_JD | HAVE_TIME);
7652  }
7653  add_frac();
7654  return ret;
7655 }
7656 
7657 static VALUE
7658 datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
7659 {
7660  VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
7661  int m, n, k, h, min, s, rof;
7662  double sg;
7663 
7664  rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
7665  &vh, &vmin, &vs, &vof, &vsg);
7666 
7667  y = INT2FIX(-4712);
7668  m = 1;
7669  n = 1;
7670  k = 1;
7671 
7672  h = min = s = 0;
7673  fr2 = INT2FIX(0);
7674  rof = 0;
7675  sg = DEFAULT_SG;
7676 
7677  switch (argc) {
7678  case 9:
7679  val2sg(vsg, sg);
7680  case 8:
7681  val2off(vof, rof);
7682  case 7:
7683  num2int_with_frac(s, positive_inf);
7684  case 6:
7685  num2int_with_frac(min, 6);
7686  case 5:
7687  num2int_with_frac(h, 5);
7688  case 4:
7689  num2int_with_frac(k, 4);
7690  case 3:
7691  n = NUM2INT(vn);
7692  case 2:
7693  m = NUM2INT(vm);
7694  case 1:
7695  y = vy;
7696  }
7697 
7698  {
7699  VALUE nth;
7700  int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns;
7701 
7702  if (!valid_nth_kday_p(y, m, n, k, sg,
7703  &nth, &ry,
7704  &rm, &rn, &rk, &rjd,
7705  &ns))
7706  rb_raise(eDateError, "invalid date");
7707  if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
7708  rb_raise(eDateError, "invalid date");
7709  canon24oc();
7710 
7711  rjd2 = jd_local_to_utc(rjd,
7712  time_to_df(rh, rmin, rs),
7713  rof);
7714  ret = d_complex_new_internal(klass,
7715  nth, rjd2,
7716  0, INT2FIX(0),
7717  rof, sg,
7718  0, 0, 0,
7719  rh, rmin, rs,
7720  HAVE_JD | HAVE_TIME);
7721  }
7722  add_frac();
7723  return ret;
7724 }
7725 #endif
7726 
7727 /*
7728  * call-seq:
7729  * DateTime.now([start=Date::ITALY]) -> datetime
7730  *
7731  * Creates a DateTime object denoting the present time.
7732  *
7733  * DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>
7734  */
7735 static VALUE
7736 datetime_s_now(int argc, VALUE *argv, VALUE klass)
7737 {
7738  VALUE vsg, nth, ret;
7739  double sg;
7740 #ifdef HAVE_CLOCK_GETTIME
7741  struct timespec ts;
7742 #else
7743  struct timeval tv;
7744 #endif
7745  time_t sec;
7746  struct tm tm;
7747  long sf, of;
7748  int y, ry, m, d, h, min, s;
7749 
7750  rb_scan_args(argc, argv, "01", &vsg);
7751 
7752  if (argc < 1)
7753  sg = DEFAULT_SG;
7754  else
7755  sg = NUM2DBL(vsg);
7756 
7757 #ifdef HAVE_CLOCK_GETTIME
7758  if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
7759  rb_sys_fail("clock_gettime");
7760  sec = ts.tv_sec;
7761 #else
7762  if (gettimeofday(&tv, NULL) == -1)
7763  rb_sys_fail("gettimeofday");
7764  sec = tv.tv_sec;
7765 #endif
7766  tzset();
7767  if (!localtime_r(&sec, &tm))
7768  rb_sys_fail("localtime");
7769 
7770  y = tm.tm_year + 1900;
7771  m = tm.tm_mon + 1;
7772  d = tm.tm_mday;
7773  h = tm.tm_hour;
7774  min = tm.tm_min;
7775  s = tm.tm_sec;
7776  if (s == 60)
7777  s = 59;
7778 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
7779  of = tm.tm_gmtoff;
7780 #elif defined(HAVE_TIMEZONE)
7781 #ifdef HAVE_ALTZONE
7782  of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
7783 #else
7784  of = (long)-timezone;
7785  if (tm.tm_isdst) {
7786  time_t sec2;
7787 
7788  tm.tm_isdst = 0;
7789  sec2 = mktime(&tm);
7790  of += (long)difftime(sec2, sec);
7791  }
7792 #endif
7793 #elif defined(HAVE_TIMEGM)
7794  {
7795  time_t sec2;
7796 
7797  sec2 = timegm(&tm);
7798  of = (long)difftime(sec2, sec);
7799  }
7800 #else
7801  {
7802  struct tm tm2;
7803  time_t sec2;
7804 
7805  if (!gmtime_r(&sec, &tm2))
7806  rb_sys_fail("gmtime");
7807  tm2.tm_isdst = tm.tm_isdst;
7808  sec2 = mktime(&tm2);
7809  of = (long)difftime(sec, sec2);
7810  }
7811 #endif
7812 #ifdef HAVE_CLOCK_GETTIME
7813  sf = ts.tv_nsec;
7814 #else
7815  sf = tv.tv_usec * 1000;
7816 #endif
7817 
7818  if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
7819  of = 0;
7820  rb_warning("invalid offset is ignored");
7821  }
7822 
7823  decode_year(INT2FIX(y), -1, &nth, &ry);
7824 
7825  ret = d_complex_new_internal(klass,
7826  nth, 0,
7827  0, LONG2NUM(sf),
7828  (int)of, GREGORIAN,
7829  ry, m, d,
7830  h, min, s,
7831  HAVE_CIVIL | HAVE_TIME);
7832  {
7833  get_d1(ret);
7834  set_sg(dat, sg);
7835  }
7836  return ret;
7837 }
7838 
7839 static VALUE
7840 dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
7841 {
7842  VALUE jd, sf, t;
7843  int df, of;
7844 
7845  if (!c_valid_start_p(NUM2DBL(sg))) {
7846  sg = INT2FIX(DEFAULT_SG);
7847  rb_warning("invalid start is ignored");
7848  }
7849 
7850  if (NIL_P(hash))
7851  rb_raise(eDateError, "invalid date");
7852 
7853  if (NIL_P(ref_hash("jd")) &&
7854  NIL_P(ref_hash("yday")) &&
7855  !NIL_P(ref_hash("year")) &&
7856  !NIL_P(ref_hash("mon")) &&
7857  !NIL_P(ref_hash("mday"))) {
7858  jd = rt__valid_civil_p(ref_hash("year"),
7859  ref_hash("mon"),
7860  ref_hash("mday"), sg);
7861 
7862  if (NIL_P(ref_hash("hour")))
7863  set_hash("hour", INT2FIX(0));
7864  if (NIL_P(ref_hash("min")))
7865  set_hash("min", INT2FIX(0));
7866  if (NIL_P(ref_hash("sec")))
7867  set_hash("sec", INT2FIX(0));
7868  else if (f_eqeq_p(ref_hash("sec"), INT2FIX(60)))
7869  set_hash("sec", INT2FIX(59));
7870  }
7871  else {
7872  hash = rt_rewrite_frags(hash);
7873  hash = rt_complete_frags(klass, hash);
7874  jd = rt__valid_date_frags_p(hash, sg);
7875  }
7876 
7877  if (NIL_P(jd))
7878  rb_raise(eDateError, "invalid date");
7879 
7880  {
7881  int rh, rmin, rs;
7882 
7883  if (!c_valid_time_p(NUM2INT(ref_hash("hour")),
7884  NUM2INT(ref_hash("min")),
7885  NUM2INT(ref_hash("sec")),
7886  &rh, &rmin, &rs))
7887  rb_raise(eDateError, "invalid date");
7888 
7889  df = time_to_df(rh, rmin, rs);
7890  }
7891 
7892  t = ref_hash("sec_fraction");
7893  if (NIL_P(t))
7894  sf = INT2FIX(0);
7895  else
7896  sf = sec_to_ns(t);
7897 
7898  t = ref_hash("offset");
7899  if (NIL_P(t))
7900  of = 0;
7901  else {
7902  of = NUM2INT(t);
7903  if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
7904  of = 0;
7905  rb_warning("invalid offset is ignored");
7906  }
7907  }
7908  {
7909  VALUE nth;
7910  int rjd, rjd2;
7911 
7912  decode_jd(jd, &nth, &rjd);
7913  rjd2 = jd_local_to_utc(rjd, df, of);
7914  df = df_local_to_utc(df, of);
7915 
7916  return d_complex_new_internal(klass,
7917  nth, rjd2,
7918  df, sf,
7919  of, NUM2DBL(sg),
7920  0, 0, 0,
7921  0, 0, 0,
7922  HAVE_JD | HAVE_DF);
7923  }
7924 }
7925 
7926 /*
7927  * call-seq:
7928  * DateTime._strptime(string[, format='%FT%T%z']) -> hash
7929  *
7930  * Parses the given representation of date and time with the given
7931  * template, and returns a hash of parsed elements. _strptime does
7932  * not support specification of flags and width unlike strftime.
7933  *
7934  * See also strptime(3) and #strftime.
7935  */
7936 static VALUE
7937 datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
7938 {
7939  return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
7940 }
7941 
7942 /*
7943  * call-seq:
7944  * DateTime.strptime([string='-4712-01-01T00:00:00+00:00'[, format='%FT%T%z'[ ,start=Date::ITALY]]]) -> datetime
7945  *
7946  * Parses the given representation of date and time with the given
7947  * template, and creates a DateTime object. strptime does not support
7948  * specification of flags and width unlike strftime.
7949  *
7950  * DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z')
7951  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7952  * DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p')
7953  * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
7954  * DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z')
7955  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7956  * DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z')
7957  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7958  * DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z')
7959  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
7960  * DateTime.strptime('-1', '%s')
7961  * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
7962  * DateTime.strptime('-1000', '%Q')
7963  * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
7964  * DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z')
7965  * #=> #<DateTime: 2001-02-03T16:00:00+07:00 ...>
7966  *
7967  * See also strptime(3) and #strftime.
7968  */
7969 static VALUE
7970 datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
7971 {
7972  VALUE str, fmt, sg;
7973 
7974  rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
7975 
7976  switch (argc) {
7977  case 0:
7978  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
7979  case 1:
7980  fmt = rb_str_new2("%FT%T%z");
7981  case 2:
7982  sg = INT2FIX(DEFAULT_SG);
7983  }
7984 
7985  {
7986  VALUE argv2[2], hash;
7987 
7988  argv2[0] = str;
7989  argv2[1] = fmt;
7990  hash = date_s__strptime(2, argv2, klass);
7991  return dt_new_by_frags(klass, hash, sg);
7992  }
7993 }
7994 
7995 /*
7996  * call-seq:
7997  * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime
7998  *
7999  * Parses the given representation of date and time, and creates a
8000  * DateTime object. This method does not function as a validator.
8001  *
8002  * If the optional second argument is true and the detected year is in
8003  * the range "00" to "99", makes it full.
8004  *
8005  * DateTime.parse('2001-02-03T04:05:06+07:00')
8006  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8007  * DateTime.parse('20010203T040506+0700')
8008  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8009  * DateTime.parse('3rd Feb 2001 04:05:06 PM')
8010  * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
8011  */
8012 static VALUE
8013 datetime_s_parse(int argc, VALUE *argv, VALUE klass)
8014 {
8015  VALUE str, comp, sg;
8016 
8017  rb_scan_args(argc, argv, "03", &str, &comp, &sg);
8018 
8019  switch (argc) {
8020  case 0:
8021  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8022  case 1:
8023  comp = Qtrue;
8024  case 2:
8025  sg = INT2FIX(DEFAULT_SG);
8026  }
8027 
8028  {
8029  VALUE argv2[2], hash;
8030 
8031  argv2[0] = str;
8032  argv2[1] = comp;
8033  hash = date_s__parse(2, argv2, klass);
8034  return dt_new_by_frags(klass, hash, sg);
8035  }
8036 }
8037 
8038 /*
8039  * call-seq:
8040  * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8041  *
8042  * Creates a new DateTime object by parsing from a string according to
8043  * some typical ISO 8601 formats.
8044  *
8045  * DateTime.iso8601('2001-02-03T04:05:06+07:00')
8046  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8047  * DateTime.iso8601('20010203T040506+0700')
8048  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8049  * DateTime.iso8601('2001-W05-6T04:05:06+07:00')
8050  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8051  */
8052 static VALUE
8053 datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
8054 {
8055  VALUE str, sg;
8056 
8057  rb_scan_args(argc, argv, "02", &str, &sg);
8058 
8059  switch (argc) {
8060  case 0:
8061  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8062  case 1:
8063  sg = INT2FIX(DEFAULT_SG);
8064  }
8065 
8066  {
8067  VALUE hash = date_s__iso8601(klass, str);
8068  return dt_new_by_frags(klass, hash, sg);
8069  }
8070 }
8071 
8072 /*
8073  * call-seq:
8074  * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8075  *
8076  * Creates a new DateTime object by parsing from a string according to
8077  * some typical RFC 3339 formats.
8078  *
8079  * DateTime.rfc3339('2001-02-03T04:05:06+07:00')
8080  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8081  */
8082 static VALUE
8083 datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
8084 {
8085  VALUE str, sg;
8086 
8087  rb_scan_args(argc, argv, "02", &str, &sg);
8088 
8089  switch (argc) {
8090  case 0:
8091  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8092  case 1:
8093  sg = INT2FIX(DEFAULT_SG);
8094  }
8095 
8096  {
8097  VALUE hash = date_s__rfc3339(klass, str);
8098  return dt_new_by_frags(klass, hash, sg);
8099  }
8100 }
8101 
8102 /*
8103  * call-seq:
8104  * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8105  *
8106  * Creates a new DateTime object by parsing from a string according to
8107  * some typical XML Schema formats.
8108  *
8109  * DateTime.xmlschema('2001-02-03T04:05:06+07:00')
8110  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8111  */
8112 static VALUE
8113 datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
8114 {
8115  VALUE str, sg;
8116 
8117  rb_scan_args(argc, argv, "02", &str, &sg);
8118 
8119  switch (argc) {
8120  case 0:
8121  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8122  case 1:
8123  sg = INT2FIX(DEFAULT_SG);
8124  }
8125 
8126  {
8127  VALUE hash = date_s__xmlschema(klass, str);
8128  return dt_new_by_frags(klass, hash, sg);
8129  }
8130 }
8131 
8132 /*
8133  * call-seq:
8134  * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8135  * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
8136  *
8137  * Creates a new DateTime object by parsing from a string according to
8138  * some typical RFC 2822 formats.
8139  *
8140  * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
8141  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8142  */
8143 static VALUE
8144 datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
8145 {
8146  VALUE str, sg;
8147 
8148  rb_scan_args(argc, argv, "02", &str, &sg);
8149 
8150  switch (argc) {
8151  case 0:
8152  str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
8153  case 1:
8154  sg = INT2FIX(DEFAULT_SG);
8155  }
8156 
8157  {
8158  VALUE hash = date_s__rfc2822(klass, str);
8159  return dt_new_by_frags(klass, hash, sg);
8160  }
8161 }
8162 
8163 /*
8164  * call-seq:
8165  * DateTime.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> datetime
8166  *
8167  * Creates a new DateTime object by parsing from a string according to
8168  * some RFC 2616 format.
8169  *
8170  * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
8171  * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
8172  */
8173 static VALUE
8174 datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
8175 {
8176  VALUE str, sg;
8177 
8178  rb_scan_args(argc, argv, "02", &str, &sg);
8179 
8180  switch (argc) {
8181  case 0:
8182  str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
8183  case 1:
8184  sg = INT2FIX(DEFAULT_SG);
8185  }
8186 
8187  {
8188  VALUE hash = date_s__httpdate(klass, str);
8189  return dt_new_by_frags(klass, hash, sg);
8190  }
8191 }
8192 
8193 /*
8194  * call-seq:
8195  * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
8196  *
8197  * Creates a new DateTime object by parsing from a string according to
8198  * some typical JIS X 0301 formats.
8199  *
8200  * DateTime.jisx0301('H13.02.03T04:05:06+07:00')
8201  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8202  *
8203  * For no-era year, legacy format, Heisei is assumed.
8204  *
8205  * DateTime.jisx0301('13.02.03T04:05:06+07:00')
8206  * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
8207  */
8208 static VALUE
8209 datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
8210 {
8211  VALUE str, sg;
8212 
8213  rb_scan_args(argc, argv, "02", &str, &sg);
8214 
8215  switch (argc) {
8216  case 0:
8217  str = rb_str_new2("-4712-01-01T00:00:00+00:00");
8218  case 1:
8219  sg = INT2FIX(DEFAULT_SG);
8220  }
8221 
8222  {
8223  VALUE hash = date_s__jisx0301(klass, str);
8224  return dt_new_by_frags(klass, hash, sg);
8225  }
8226 }
8227 
8228 /*
8229  * call-seq:
8230  * dt.to_s -> string
8231  *
8232  * Returns a string in an ISO 8601 format. (This method doesn't use the
8233  * expanded representations.)
8234  *
8235  * DateTime.new(2001,2,3,4,5,6,'-7').to_s
8236  * #=> "2001-02-03T04:05:06-07:00"
8237  */
8238 static VALUE
8239 dt_lite_to_s(VALUE self)
8240 {
8241  return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
8242 }
8243 
8244 /*
8245  * call-seq:
8246  * dt.strftime([format='%FT%T%:z']) -> string
8247  *
8248  * Formats date according to the directives in the given format
8249  * string.
8250  * The directives begin with a percent (%) character.
8251  * Any text not listed as a directive will be passed through to the
8252  * output string.
8253  *
8254  * A directive consists of a percent (%) character,
8255  * zero or more flags, an optional minimum field width,
8256  * an optional modifier, and a conversion specifier
8257  * as follows.
8258  *
8259  * %<flags><width><modifier><conversion>
8260  *
8261  * Flags:
8262  * - don't pad a numerical output.
8263  * _ use spaces for padding.
8264  * 0 use zeros for padding.
8265  * ^ upcase the result string.
8266  * # change case.
8267  * : use colons for %z.
8268  *
8269  * The minimum field width specifies the minimum width.
8270  *
8271  * The modifiers are "E" and "O".
8272  * They are ignored.
8273  *
8274  * Format directives:
8275  *
8276  * Date (Year, Month, Day):
8277  * %Y - Year with century (can be negative, 4 digits at least)
8278  * -0001, 0000, 1995, 2009, 14292, etc.
8279  * %C - year / 100 (round down. 20 in 2009)
8280  * %y - year % 100 (00..99)
8281  *
8282  * %m - Month of the year, zero-padded (01..12)
8283  * %_m blank-padded ( 1..12)
8284  * %-m no-padded (1..12)
8285  * %B - The full month name (``January'')
8286  * %^B uppercased (``JANUARY'')
8287  * %b - The abbreviated month name (``Jan'')
8288  * %^b uppercased (``JAN'')
8289  * %h - Equivalent to %b
8290  *
8291  * %d - Day of the month, zero-padded (01..31)
8292  * %-d no-padded (1..31)
8293  * %e - Day of the month, blank-padded ( 1..31)
8294  *
8295  * %j - Day of the year (001..366)
8296  *
8297  * Time (Hour, Minute, Second, Subsecond):
8298  * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
8299  * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
8300  * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
8301  * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
8302  * %P - Meridian indicator, lowercase (``am'' or ``pm'')
8303  * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
8304  *
8305  * %M - Minute of the hour (00..59)
8306  *
8307  * %S - Second of the minute (00..60)
8308  *
8309  * %L - Millisecond of the second (000..999)
8310  * %N - Fractional seconds digits, default is 9 digits (nanosecond)
8311  * %3N millisecond (3 digits) %15N femtosecond (15 digits)
8312  * %6N microsecond (6 digits) %18N attosecond (18 digits)
8313  * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
8314  * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
8315  *
8316  * Time zone:
8317  * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
8318  * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
8319  * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
8320  * %:::z - hour, minute and second offset from UTC
8321  * (e.g. +09, +09:30, +09:30:30)
8322  * %Z - Equivalent to %:z (e.g. +09:00)
8323  *
8324  * Weekday:
8325  * %A - The full weekday name (``Sunday'')
8326  * %^A uppercased (``SUNDAY'')
8327  * %a - The abbreviated name (``Sun'')
8328  * %^a uppercased (``SUN'')
8329  * %u - Day of the week (Monday is 1, 1..7)
8330  * %w - Day of the week (Sunday is 0, 0..6)
8331  *
8332  * ISO 8601 week-based year and week number:
8333  * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
8334  * The days in the year before the first week are in the last week of
8335  * the previous year.
8336  * %G - The week-based year
8337  * %g - The last 2 digits of the week-based year (00..99)
8338  * %V - Week number of the week-based year (01..53)
8339  *
8340  * Week number:
8341  * The week 1 of YYYY starts with a Sunday or Monday (according to %U
8342  * or %W). The days in the year before the first week are in week 0.
8343  * %U - Week number of the year. The week starts with Sunday. (00..53)
8344  * %W - Week number of the year. The week starts with Monday. (00..53)
8345  *
8346  * Seconds since the Unix Epoch:
8347  * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
8348  * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
8349  *
8350  * Literal string:
8351  * %n - Newline character (\n)
8352  * %t - Tab character (\t)
8353  * %% - Literal ``%'' character
8354  *
8355  * Combination:
8356  * %c - date and time (%a %b %e %T %Y)
8357  * %D - Date (%m/%d/%y)
8358  * %F - The ISO 8601 date format (%Y-%m-%d)
8359  * %v - VMS date (%e-%b-%Y)
8360  * %x - Same as %D
8361  * %X - Same as %T
8362  * %r - 12-hour time (%I:%M:%S %p)
8363  * %R - 24-hour time (%H:%M)
8364  * %T - 24-hour time (%H:%M:%S)
8365  * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
8366  *
8367  * This method is similar to the strftime() function defined in ISO C
8368  * and POSIX.
8369  * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
8370  * are locale dependent in the function.
8371  * However, this method is locale independent.
8372  * So, the result may differ even if the same format string is used in other
8373  * systems such as C.
8374  * It is good practice to avoid %x and %X because there are corresponding
8375  * locale independent representations, %D and %T.
8376  *
8377  * Examples:
8378  *
8379  * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
8380  * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
8381  * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
8382  * d.strftime("at %I:%M%p") #=> "at 08:37AM"
8383  *
8384  * Various ISO 8601 formats:
8385  * %Y%m%d => 20071119 Calendar date (basic)
8386  * %F => 2007-11-19 Calendar date (extended)
8387  * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
8388  * %Y => 2007 Calendar date, reduced accuracy, specific year
8389  * %C => 20 Calendar date, reduced accuracy, specific century
8390  * %Y%j => 2007323 Ordinal date (basic)
8391  * %Y-%j => 2007-323 Ordinal date (extended)
8392  * %GW%V%u => 2007W471 Week date (basic)
8393  * %G-W%V-%u => 2007-W47-1 Week date (extended)
8394  * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
8395  * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
8396  * %H%M%S => 083748 Local time (basic)
8397  * %T => 08:37:48 Local time (extended)
8398  * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
8399  * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
8400  * %H => 08 Local time, reduced accuracy, specific hour
8401  * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
8402  * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
8403  * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
8404  * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
8405  * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
8406  * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
8407  * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
8408  * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
8409  * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
8410  * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
8411  * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
8412  * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
8413  * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
8414  * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
8415  * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
8416  * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
8417  * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
8418  * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
8419  *
8420  * See also strftime(3) and ::strptime.
8421  */
8422 static VALUE
8423 dt_lite_strftime(int argc, VALUE *argv, VALUE self)
8424 {
8425  return date_strftime_internal(argc, argv, self,
8426  "%Y-%m-%dT%H:%M:%S%:z", set_tmx);
8427 }
8428 
8429 static VALUE
8430 iso8601_timediv(VALUE self, long n)
8431 {
8432  static const char timefmt[] = "T%H:%M:%S";
8433  static const char zone[] = "%:z";
8434  char fmt[sizeof(timefmt) + sizeof(zone) + rb_strlen_lit(".%N") +
8436  char *p = fmt;
8437 
8438  memcpy(p, timefmt, sizeof(timefmt)-1);
8439  p += sizeof(timefmt)-1;
8440  if (n > 0) p += snprintf(p, fmt+sizeof(fmt)-p, ".%%%ldN", n);
8441  memcpy(p, zone, sizeof(zone));
8442  return strftimev(fmt, self, set_tmx);
8443 }
8444 
8445 /*
8446  * call-seq:
8447  * dt.iso8601([n=0]) -> string
8448  * dt.xmlschema([n=0]) -> string
8449  *
8450  * This method is equivalent to strftime('%FT%T%:z').
8451  * The optional argument +n+ is the number of digits for fractional seconds.
8452  *
8453  * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
8454  * #=> "2001-02-03T04:05:06.123456789+07:00"
8455  */
8456 static VALUE
8457 dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
8458 {
8459  long n = 0;
8460 
8461  rb_check_arity(argc, 0, 1);
8462  if (argc >= 1)
8463  n = NUM2LONG(argv[0]);
8464 
8465  return rb_str_append(strftimev("%Y-%m-%d", self, set_tmx),
8466  iso8601_timediv(self, n));
8467 }
8468 
8469 /*
8470  * call-seq:
8471  * dt.rfc3339([n=0]) -> string
8472  *
8473  * This method is equivalent to strftime('%FT%T%:z').
8474  * The optional argument +n+ is the number of digits for fractional seconds.
8475  *
8476  * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9)
8477  * #=> "2001-02-03T04:05:06.123456789+07:00"
8478  */
8479 static VALUE
8480 dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
8481 {
8482  return dt_lite_iso8601(argc, argv, self);
8483 }
8484 
8485 /*
8486  * call-seq:
8487  * dt.jisx0301([n=0]) -> string
8488  *
8489  * Returns a string in a JIS X 0301 format.
8490  * The optional argument +n+ is the number of digits for fractional seconds.
8491  *
8492  * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9)
8493  * #=> "H13.02.03T04:05:06.123456789+07:00"
8494  */
8495 static VALUE
8496 dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
8497 {
8498  long n = 0;
8499 
8500  rb_check_arity(argc, 0, 1);
8501  if (argc >= 1)
8502  n = NUM2LONG(argv[0]);
8503 
8504  return rb_str_append(d_lite_jisx0301(self),
8505  iso8601_timediv(self, n));
8506 }
8507 
8508 /* conversions */
8509 
8510 #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
8511 #define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
8512 #define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
8513 
8514 /*
8515  * call-seq:
8516  * t.to_time -> time
8517  *
8518  * Returns self.
8519  */
8520 static VALUE
8521 time_to_time(VALUE self)
8522 {
8523  return self;
8524 }
8525 
8526 /*
8527  * call-seq:
8528  * t.to_date -> date
8529  *
8530  * Returns a Date object which denotes self.
8531  */
8532 static VALUE
8533 time_to_date(VALUE self)
8534 {
8535  VALUE y, nth, ret;
8536  int ry, m, d;
8537 
8538  y = f_year(self);
8539  m = FIX2INT(f_mon(self));
8540  d = FIX2INT(f_mday(self));
8541 
8542  decode_year(y, -1, &nth, &ry);
8543 
8544  ret = d_simple_new_internal(cDate,
8545  nth, 0,
8546  GREGORIAN,
8547  ry, m, d,
8548  HAVE_CIVIL);
8549  {
8550  get_d1(ret);
8551  set_sg(dat, DEFAULT_SG);
8552  }
8553  return ret;
8554 }
8555 
8556 /*
8557  * call-seq:
8558  * t.to_datetime -> datetime
8559  *
8560  * Returns a DateTime object which denotes self.
8561  */
8562 static VALUE
8563 time_to_datetime(VALUE self)
8564 {
8565  VALUE y, sf, nth, ret;
8566  int ry, m, d, h, min, s, of;
8567 
8568  y = f_year(self);
8569  m = FIX2INT(f_mon(self));
8570  d = FIX2INT(f_mday(self));
8571 
8572  h = FIX2INT(f_hour(self));
8573  min = FIX2INT(f_min(self));
8574  s = FIX2INT(f_sec(self));
8575  if (s == 60)
8576  s = 59;
8577 
8578  sf = sec_to_ns(f_subsec(self));
8579  of = FIX2INT(f_utc_offset(self));
8580 
8581  decode_year(y, -1, &nth, &ry);
8582 
8583  ret = d_complex_new_internal(cDateTime,
8584  nth, 0,
8585  0, sf,
8586  of, DEFAULT_SG,
8587  ry, m, d,
8588  h, min, s,
8589  HAVE_CIVIL | HAVE_TIME);
8590  {
8591  get_d1(ret);
8592  set_sg(dat, DEFAULT_SG);
8593  }
8594  return ret;
8595 }
8596 
8597 /*
8598  * call-seq:
8599  * d.to_time -> time
8600  *
8601  * Returns a Time object which denotes self. If self is a julian date,
8602  * convert it to a gregorian date before converting it to Time.
8603  */
8604 static VALUE
8605 date_to_time(VALUE self)
8606 {
8607  get_d1a(self);
8608 
8609  if (m_julian_p(adat)) {
8610  VALUE tmp = d_lite_gregorian(self);
8611  get_d1b(tmp);
8612  adat = bdat;
8613  }
8614 
8615  return f_local3(rb_cTime,
8616  m_real_year(adat),
8617  INT2FIX(m_mon(adat)),
8618  INT2FIX(m_mday(adat)));
8619 }
8620 
8621 /*
8622  * call-seq:
8623  * d.to_date -> self
8624  *
8625  * Returns self.
8626  */
8627 static VALUE
8628 date_to_date(VALUE self)
8629 {
8630  return self;
8631 }
8632 
8633 /*
8634  * call-seq:
8635  * d.to_datetime -> datetime
8636  *
8637  * Returns a DateTime object which denotes self.
8638  */
8639 static VALUE
8640 date_to_datetime(VALUE self)
8641 {
8642  get_d1a(self);
8643 
8644  if (simple_dat_p(adat)) {
8645  VALUE new = d_lite_s_alloc_simple(cDateTime);
8646  {
8647  get_d1b(new);
8648  bdat->s = adat->s;
8649  return new;
8650  }
8651  }
8652  else {
8653  VALUE new = d_lite_s_alloc_complex(cDateTime);
8654  {
8655  get_d1b(new);
8656  bdat->c = adat->c;
8657  bdat->c.df = 0;
8658  RB_OBJ_WRITE(new, &bdat->c.sf, INT2FIX(0));
8659 #ifndef USE_PACK
8660  bdat->c.hour = 0;
8661  bdat->c.min = 0;
8662  bdat->c.sec = 0;
8663 #else
8664  bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
8665  0, 0, 0);
8666  bdat->c.flags |= HAVE_DF | HAVE_TIME;
8667 #endif
8668  return new;
8669  }
8670  }
8671 }
8672 
8673 /*
8674  * call-seq:
8675  * dt.to_time -> time
8676  *
8677  * Returns a Time object which denotes self.
8678  */
8679 static VALUE
8680 datetime_to_time(VALUE self)
8681 {
8682  volatile VALUE dup = dup_obj(self);
8683  {
8684  VALUE t;
8685 
8686  get_d1(dup);
8687 
8688  t = rb_funcall(rb_cTime,
8689  rb_intern("new"),
8690  7,
8691  m_real_year(dat),
8692  INT2FIX(m_mon(dat)),
8693  INT2FIX(m_mday(dat)),
8694  INT2FIX(m_hour(dat)),
8695  INT2FIX(m_min(dat)),
8696  f_add(INT2FIX(m_sec(dat)),
8697  m_sf_in_sec(dat)),
8698  INT2FIX(m_of(dat)));
8699  return t;
8700  }
8701 }
8702 
8703 /*
8704  * call-seq:
8705  * dt.to_date -> date
8706  *
8707  * Returns a Date object which denotes self.
8708  */
8709 static VALUE
8710 datetime_to_date(VALUE self)
8711 {
8712  get_d1a(self);
8713 
8714  if (simple_dat_p(adat)) {
8715  VALUE new = d_lite_s_alloc_simple(cDate);
8716  {
8717  get_d1b(new);
8718  bdat->s = adat->s;
8719  bdat->s.jd = m_local_jd(adat);
8720  return new;
8721  }
8722  }
8723  else {
8724  VALUE new = d_lite_s_alloc_simple(cDate);
8725  {
8726  get_d1b(new);
8727  copy_complex_to_simple(new, &bdat->s, &adat->c);
8728  bdat->s.jd = m_local_jd(adat);
8729  bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
8730  return new;
8731  }
8732  }
8733 }
8734 
8735 /*
8736  * call-seq:
8737  * dt.to_datetime -> self
8738  *
8739  * Returns self.
8740  */
8741 static VALUE
8742 datetime_to_datetime(VALUE self)
8743 {
8744  return self;
8745 }
8746 
8747 #ifndef NDEBUG
8748 /* tests */
8749 
8750 #define MIN_YEAR -4713
8751 #define MAX_YEAR 1000000
8752 #define MIN_JD -327
8753 #define MAX_JD 366963925
8754 
8755 static int
8756 test_civil(int from, int to, double sg)
8757 {
8758  int j;
8759 
8760  fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n",
8761  from, to, to - from, sg);
8762  for (j = from; j <= to; j++) {
8763  int y, m, d, rj, ns;
8764 
8765  c_jd_to_civil(j, sg, &y, &m, &d);
8766  c_civil_to_jd(y, m, d, sg, &rj, &ns);
8767  if (j != rj) {
8768  fprintf(stderr, "%d != %d\n", j, rj);
8769  return 0;
8770  }
8771  }
8772  return 1;
8773 }
8774 
8775 static VALUE
8776 date_s_test_civil(VALUE klass)
8777 {
8778  if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN))
8779  return Qfalse;
8780  if (!test_civil(2305814, 2598007, GREGORIAN))
8781  return Qfalse;
8782  if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN))
8783  return Qfalse;
8784 
8785  if (!test_civil(MIN_JD, MIN_JD + 366, ITALY))
8786  return Qfalse;
8787  if (!test_civil(2305814, 2598007, ITALY))
8788  return Qfalse;
8789  if (!test_civil(MAX_JD - 366, MAX_JD, ITALY))
8790  return Qfalse;
8791 
8792  return Qtrue;
8793 }
8794 
8795 static int
8796 test_ordinal(int from, int to, double sg)
8797 {
8798  int j;
8799 
8800  fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n",
8801  from, to, to - from, sg);
8802  for (j = from; j <= to; j++) {
8803  int y, d, rj, ns;
8804 
8805  c_jd_to_ordinal(j, sg, &y, &d);
8806  c_ordinal_to_jd(y, d, sg, &rj, &ns);
8807  if (j != rj) {
8808  fprintf(stderr, "%d != %d\n", j, rj);
8809  return 0;
8810  }
8811  }
8812  return 1;
8813 }
8814 
8815 static VALUE
8816 date_s_test_ordinal(VALUE klass)
8817 {
8818  if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN))
8819  return Qfalse;
8820  if (!test_ordinal(2305814, 2598007, GREGORIAN))
8821  return Qfalse;
8822  if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN))
8823  return Qfalse;
8824 
8825  if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY))
8826  return Qfalse;
8827  if (!test_ordinal(2305814, 2598007, ITALY))
8828  return Qfalse;
8829  if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY))
8830  return Qfalse;
8831 
8832  return Qtrue;
8833 }
8834 
8835 static int
8836 test_commercial(int from, int to, double sg)
8837 {
8838  int j;
8839 
8840  fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n",
8841  from, to, to - from, sg);
8842  for (j = from; j <= to; j++) {
8843  int y, w, d, rj, ns;
8844 
8845  c_jd_to_commercial(j, sg, &y, &w, &d);
8846  c_commercial_to_jd(y, w, d, sg, &rj, &ns);
8847  if (j != rj) {
8848  fprintf(stderr, "%d != %d\n", j, rj);
8849  return 0;
8850  }
8851  }
8852  return 1;
8853 }
8854 
8855 static VALUE
8856 date_s_test_commercial(VALUE klass)
8857 {
8858  if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN))
8859  return Qfalse;
8860  if (!test_commercial(2305814, 2598007, GREGORIAN))
8861  return Qfalse;
8862  if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN))
8863  return Qfalse;
8864 
8865  if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY))
8866  return Qfalse;
8867  if (!test_commercial(2305814, 2598007, ITALY))
8868  return Qfalse;
8869  if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY))
8870  return Qfalse;
8871 
8872  return Qtrue;
8873 }
8874 
8875 static int
8876 test_weeknum(int from, int to, int f, double sg)
8877 {
8878  int j;
8879 
8880  fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n",
8881  from, to, to - from, sg);
8882  for (j = from; j <= to; j++) {
8883  int y, w, d, rj, ns;
8884 
8885  c_jd_to_weeknum(j, f, sg, &y, &w, &d);
8886  c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns);
8887  if (j != rj) {
8888  fprintf(stderr, "%d != %d\n", j, rj);
8889  return 0;
8890  }
8891  }
8892  return 1;
8893 }
8894 
8895 static VALUE
8896 date_s_test_weeknum(VALUE klass)
8897 {
8898  int f;
8899 
8900  for (f = 0; f <= 1; f++) {
8901  if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN))
8902  return Qfalse;
8903  if (!test_weeknum(2305814, 2598007, f, GREGORIAN))
8904  return Qfalse;
8905  if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN))
8906  return Qfalse;
8907 
8908  if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY))
8909  return Qfalse;
8910  if (!test_weeknum(2305814, 2598007, f, ITALY))
8911  return Qfalse;
8912  if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY))
8913  return Qfalse;
8914  }
8915 
8916  return Qtrue;
8917 }
8918 
8919 static int
8920 test_nth_kday(int from, int to, double sg)
8921 {
8922  int j;
8923 
8924  fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n",
8925  from, to, to - from, sg);
8926  for (j = from; j <= to; j++) {
8927  int y, m, n, k, rj, ns;
8928 
8929  c_jd_to_nth_kday(j, sg, &y, &m, &n, &k);
8930  c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns);
8931  if (j != rj) {
8932  fprintf(stderr, "%d != %d\n", j, rj);
8933  return 0;
8934  }
8935  }
8936  return 1;
8937 }
8938 
8939 static VALUE
8940 date_s_test_nth_kday(VALUE klass)
8941 {
8942  if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN))
8943  return Qfalse;
8944  if (!test_nth_kday(2305814, 2598007, GREGORIAN))
8945  return Qfalse;
8946  if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN))
8947  return Qfalse;
8948 
8949  if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY))
8950  return Qfalse;
8951  if (!test_nth_kday(2305814, 2598007, ITALY))
8952  return Qfalse;
8953  if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY))
8954  return Qfalse;
8955 
8956  return Qtrue;
8957 }
8958 
8959 static int
8960 test_unit_v2v(VALUE i,
8961  VALUE (* conv1)(VALUE),
8962  VALUE (* conv2)(VALUE))
8963 {
8964  VALUE c, o;
8965  c = (*conv1)(i);
8966  o = (*conv2)(c);
8967  return f_eqeq_p(o, i);
8968 }
8969 
8970 static int
8971 test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
8972  VALUE (* conv2)(VALUE))
8973 {
8974  if (!test_unit_v2v(INT2FIX(0), conv1, conv2))
8975  return 0;
8976  if (!test_unit_v2v(INT2FIX(1), conv1, conv2))
8977  return 0;
8978  if (!test_unit_v2v(INT2FIX(2), conv1, conv2))
8979  return 0;
8980  if (!test_unit_v2v(INT2FIX(3), conv1, conv2))
8981  return 0;
8982  if (!test_unit_v2v(INT2FIX(11), conv1, conv2))
8983  return 0;
8984  if (!test_unit_v2v(INT2FIX(65535), conv1, conv2))
8985  return 0;
8986  if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2))
8987  return 0;
8988  if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2))
8989  return 0;
8990  if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2))
8991  return 0;
8992  if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2))
8993  return 0;
8994  if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2))
8995  return 0;
8996  if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2))
8997  return 0;
8998  return 1;
8999 }
9000 
9001 static int
9002 test_unit_v2v_iter(VALUE (* conv1)(VALUE),
9003  VALUE (* conv2)(VALUE))
9004 {
9005  if (!test_unit_v2v_iter2(conv1, conv2))
9006  return 0;
9007  if (!test_unit_v2v_iter2(conv2, conv1))
9008  return 0;
9009  return 1;
9010 }
9011 
9012 static VALUE
9013 date_s_test_unit_conv(VALUE klass)
9014 {
9015  if (!test_unit_v2v_iter(sec_to_day, day_to_sec))
9016  return Qfalse;
9017  if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms))
9018  return Qfalse;
9019  if (!test_unit_v2v_iter(ns_to_day, day_to_ns))
9020  return Qfalse;
9021  if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns))
9022  return Qfalse;
9023  return Qtrue;
9024 }
9025 
9026 static VALUE
9027 date_s_test_all(VALUE klass)
9028 {
9029  if (date_s_test_civil(klass) == Qfalse)
9030  return Qfalse;
9031  if (date_s_test_ordinal(klass) == Qfalse)
9032  return Qfalse;
9033  if (date_s_test_commercial(klass) == Qfalse)
9034  return Qfalse;
9035  if (date_s_test_weeknum(klass) == Qfalse)
9036  return Qfalse;
9037  if (date_s_test_nth_kday(klass) == Qfalse)
9038  return Qfalse;
9039  if (date_s_test_unit_conv(klass) == Qfalse)
9040  return Qfalse;
9041  return Qtrue;
9042 }
9043 #endif
9044 
9045 static const char *monthnames[] = {
9046  NULL,
9047  "January", "February", "March",
9048  "April", "May", "June",
9049  "July", "August", "September",
9050  "October", "November", "December"
9051 };
9052 
9053 static const char *abbr_monthnames[] = {
9054  NULL,
9055  "Jan", "Feb", "Mar", "Apr",
9056  "May", "Jun", "Jul", "Aug",
9057  "Sep", "Oct", "Nov", "Dec"
9058 };
9059 
9060 static const char *daynames[] = {
9061  "Sunday", "Monday", "Tuesday", "Wednesday",
9062  "Thursday", "Friday", "Saturday"
9063 };
9064 
9065 static const char *abbr_daynames[] = {
9066  "Sun", "Mon", "Tue", "Wed",
9067  "Thu", "Fri", "Sat"
9068 };
9069 
9070 static VALUE
9071 mk_ary_of_str(long len, const char *a[])
9072 {
9073  VALUE o;
9074  long i;
9075 
9076  o = rb_ary_new2(len);
9077  for (i = 0; i < len; i++) {
9078  VALUE e;
9079 
9080  if (!a[i])
9081  e = Qnil;
9082  else {
9083  e = rb_usascii_str_new2(a[i]);
9084  rb_obj_freeze(e);
9085  }
9086  rb_ary_push(o, e);
9087  }
9088  rb_obj_freeze(o);
9089  return o;
9090 }
9091 
9092 static VALUE
9093 d_lite_zero(VALUE x)
9094 {
9095  return INT2FIX(0);
9096 }
9097 
9098 void
9100 {
9101 #undef rb_intern
9102 #define rb_intern(str) rb_intern_const(str)
9103 
9104  id_cmp = rb_intern("<=>");
9105  id_le_p = rb_intern("<=");
9106  id_ge_p = rb_intern(">=");
9107  id_eqeq_p = rb_intern("==");
9108 
9109  half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
9110 
9111 #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
9112  day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
9114 #elif defined HAVE_LONG_LONG
9115  day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS *
9117 #else
9118  day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
9120 #endif
9121 
9122  rb_gc_register_mark_object(half_days_in_day);
9123  rb_gc_register_mark_object(day_in_nanoseconds);
9124 
9125  positive_inf = +INFINITY;
9126  negative_inf = -INFINITY;
9127 
9128  /*
9129  * date and datetime class - Tadayoshi Funaba 1998-2011
9130  *
9131  * 'date' provides two classes: Date and DateTime.
9132  *
9133  * == Terms and Definitions
9134  *
9135  * Some terms and definitions are based on ISO 8601 and JIS X 0301.
9136  *
9137  * === Calendar Date
9138  *
9139  * The calendar date is a particular day of a calendar year,
9140  * identified by its ordinal number within a calendar month within
9141  * that year.
9142  *
9143  * In those classes, this is so-called "civil".
9144  *
9145  * === Ordinal Date
9146  *
9147  * The ordinal date is a particular day of a calendar year identified
9148  * by its ordinal number within the year.
9149  *
9150  * In those classes, this is so-called "ordinal".
9151  *
9152  * === Week Date
9153  *
9154  * The week date is a date identified by calendar week and day numbers.
9155  *
9156  * The calendar week is a seven day period within a calendar year,
9157  * starting on a Monday and identified by its ordinal number within
9158  * the year; the first calendar week of the year is the one that
9159  * includes the first Thursday of that year. In the Gregorian
9160  * calendar, this is equivalent to the week which includes January 4.
9161  *
9162  * In those classes, this is so-called "commercial".
9163  *
9164  * === Julian Day Number
9165  *
9166  * The Julian day number is in elapsed days since noon (Greenwich Mean
9167  * Time) on January 1, 4713 BCE (in the Julian calendar).
9168  *
9169  * In this document, the astronomical Julian day number is the same as
9170  * the original Julian day number. And the chronological Julian day
9171  * number is a variation of the Julian day number. Its days begin at
9172  * midnight on local time.
9173  *
9174  * In this document, when the term "Julian day number" simply appears,
9175  * it just refers to "chronological Julian day number", not the
9176  * original.
9177  *
9178  * In those classes, those are so-called "ajd" and "jd".
9179  *
9180  * === Modified Julian Day Number
9181  *
9182  * The modified Julian day number is in elapsed days since midnight
9183  * (Coordinated Universal Time) on November 17, 1858 CE (in the
9184  * Gregorian calendar).
9185  *
9186  * In this document, the astronomical modified Julian day number is
9187  * the same as the original modified Julian day number. And the
9188  * chronological modified Julian day number is a variation of the
9189  * modified Julian day number. Its days begin at midnight on local
9190  * time.
9191  *
9192  * In this document, when the term "modified Julian day number" simply
9193  * appears, it just refers to "chronological modified Julian day
9194  * number", not the original.
9195  *
9196  * In those classes, those are so-called "amjd" and "mjd".
9197  *
9198  * == Date
9199  *
9200  * A subclass of Object that includes the Comparable module and
9201  * easily handles date.
9202  *
9203  * A Date object is created with Date::new, Date::jd, Date::ordinal,
9204  * Date::commercial, Date::parse, Date::strptime, Date::today,
9205  * Time#to_date, etc.
9206  *
9207  * require 'date'
9208  *
9209  * Date.new(2001,2,3)
9210  * #=> #<Date: 2001-02-03 ...>
9211  * Date.jd(2451944)
9212  * #=> #<Date: 2001-02-03 ...>
9213  * Date.ordinal(2001,34)
9214  * #=> #<Date: 2001-02-03 ...>
9215  * Date.commercial(2001,5,6)
9216  * #=> #<Date: 2001-02-03 ...>
9217  * Date.parse('2001-02-03')
9218  * #=> #<Date: 2001-02-03 ...>
9219  * Date.strptime('03-02-2001', '%d-%m-%Y')
9220  * #=> #<Date: 2001-02-03 ...>
9221  * Time.new(2001,2,3).to_date
9222  * #=> #<Date: 2001-02-03 ...>
9223  *
9224  * All date objects are immutable; hence cannot modify themselves.
9225  *
9226  * The concept of a date object can be represented as a tuple
9227  * of the day count, the offset and the day of calendar reform.
9228  *
9229  * The day count denotes the absolute position of a temporal
9230  * dimension. The offset is relative adjustment, which determines
9231  * decoded local time with the day count. The day of calendar
9232  * reform denotes the start day of the new style. The old style
9233  * of the West is the Julian calendar which was adopted by
9234  * Caesar. The new style is the Gregorian calendar, which is the
9235  * current civil calendar of many countries.
9236  *
9237  * The day count is virtually the astronomical Julian day number.
9238  * The offset in this class is usually zero, and cannot be
9239  * specified directly.
9240  *
9241  * A Date object can be created with an optional argument,
9242  * the day of calendar reform as a Julian day number, which
9243  * should be 2298874 to 2426355 or negative/positive infinity.
9244  * The default value is +Date::ITALY+ (2299161=1582-10-15).
9245  * See also sample/cal.rb.
9246  *
9247  * $ ruby sample/cal.rb -c it 10 1582
9248  * October 1582
9249  * S M Tu W Th F S
9250  * 1 2 3 4 15 16
9251  * 17 18 19 20 21 22 23
9252  * 24 25 26 27 28 29 30
9253  * 31
9254  *
9255  * $ ruby sample/cal.rb -c gb 9 1752
9256  * September 1752
9257  * S M Tu W Th F S
9258  * 1 2 14 15 16
9259  * 17 18 19 20 21 22 23
9260  * 24 25 26 27 28 29 30
9261  *
9262  * A Date object has various methods. See each reference.
9263  *
9264  * d = Date.parse('3rd Feb 2001')
9265  * #=> #<Date: 2001-02-03 ...>
9266  * d.year #=> 2001
9267  * d.mon #=> 2
9268  * d.mday #=> 3
9269  * d.wday #=> 6
9270  * d += 1 #=> #<Date: 2001-02-04 ...>
9271  * d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001"
9272  *
9273  */
9274  cDate = rb_define_class("Date", rb_cObject);
9275  eDateError = rb_define_class_under(cDate, "Error", rb_eArgError);
9276 
9278 
9279  /* An array of strings of full month names in English. The first
9280  * element is nil.
9281  */
9282  rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
9283 
9284  /* An array of strings of abbreviated month names in English. The
9285  * first element is nil.
9286  */
9287  rb_define_const(cDate, "ABBR_MONTHNAMES",
9288  mk_ary_of_str(13, abbr_monthnames));
9289 
9290  /* An array of strings of the full names of days of the week in English.
9291  * The first is "Sunday".
9292  */
9293  rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
9294 
9295  /* An array of strings of abbreviated day names in English. The
9296  * first is "Sun".
9297  */
9298  rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames));
9299 
9300  /* The Julian day number of the day of calendar reform for Italy
9301  * and some catholic countries.
9302  */
9303  rb_define_const(cDate, "ITALY", INT2FIX(ITALY));
9304 
9305  /* The Julian day number of the day of calendar reform for England
9306  * and her colonies.
9307  */
9308  rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND));
9309 
9310  /* The Julian day number of the day of calendar reform for the
9311  * proleptic Julian calendar.
9312  */
9313  rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
9314 
9315  /* The Julian day number of the day of calendar reform for the
9316  * proleptic Gregorian calendar.
9317  */
9318  rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
9319 
9320  rb_define_alloc_func(cDate, d_lite_s_alloc_simple);
9321 
9322 #ifndef NDEBUG
9323  rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
9324  date_s__valid_jd_p, -1);
9325  rb_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
9326  date_s__valid_ordinal_p, -1);
9327  rb_define_private_method(CLASS_OF(cDate), "_valid_civil?",
9328  date_s__valid_civil_p, -1);
9329  rb_define_private_method(CLASS_OF(cDate), "_valid_date?",
9330  date_s__valid_civil_p, -1);
9331  rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
9332  date_s__valid_commercial_p, -1);
9333  rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
9334  date_s__valid_weeknum_p, -1);
9335  rb_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
9336  date_s__valid_nth_kday_p, -1);
9337 #endif
9338 
9339  rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1);
9340  rb_define_singleton_method(cDate, "valid_ordinal?",
9341  date_s_valid_ordinal_p, -1);
9342  rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1);
9343  rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1);
9344  rb_define_singleton_method(cDate, "valid_commercial?",
9345  date_s_valid_commercial_p, -1);
9346 
9347 #ifndef NDEBUG
9348  rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
9349  date_s_valid_weeknum_p, -1);
9350  rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
9351  date_s_valid_nth_kday_p, -1);
9352  rb_define_private_method(CLASS_OF(cDate), "zone_to_diff",
9353  date_s_zone_to_diff, 1);
9354 #endif
9355 
9356  rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1);
9357  rb_define_singleton_method(cDate, "gregorian_leap?",
9358  date_s_gregorian_leap_p, 1);
9359  rb_define_singleton_method(cDate, "leap?",
9360  date_s_gregorian_leap_p, 1);
9361 
9362 #ifndef NDEBUG
9363  rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
9364  rb_define_alias(rb_singleton_class(cDate), "new_l!", "new");
9365 #endif
9366 
9367  rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
9368  rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
9369  rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
9370  rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
9371 
9372 #ifndef NDEBUG
9373  rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
9374  rb_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
9375 #endif
9376 
9377  rb_define_singleton_method(cDate, "today", date_s_today, -1);
9378  rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1);
9379  rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
9380  rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
9381  rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
9382  rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
9383  rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
9384  rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
9385  rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
9386  rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
9387  rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
9388  rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
9389  rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
9390  rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
9391  rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
9392  rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
9393  rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
9394  rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
9395  rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
9396 
9397  rb_define_method(cDate, "initialize", date_initialize, -1);
9398  rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
9399 
9400 #ifndef NDEBUG
9401  rb_define_method(cDate, "fill", d_lite_fill, 0);
9402 #endif
9403 
9404  rb_define_method(cDate, "ajd", d_lite_ajd, 0);
9405  rb_define_method(cDate, "amjd", d_lite_amjd, 0);
9406  rb_define_method(cDate, "jd", d_lite_jd, 0);
9407  rb_define_method(cDate, "mjd", d_lite_mjd, 0);
9408  rb_define_method(cDate, "ld", d_lite_ld, 0);
9409 
9410  rb_define_method(cDate, "year", d_lite_year, 0);
9411  rb_define_method(cDate, "yday", d_lite_yday, 0);
9412  rb_define_method(cDate, "mon", d_lite_mon, 0);
9413  rb_define_method(cDate, "month", d_lite_mon, 0);
9414  rb_define_method(cDate, "mday", d_lite_mday, 0);
9415  rb_define_method(cDate, "day", d_lite_mday, 0);
9416  rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0);
9417 
9418  rb_define_method(cDate, "cwyear", d_lite_cwyear, 0);
9419  rb_define_method(cDate, "cweek", d_lite_cweek, 0);
9420  rb_define_method(cDate, "cwday", d_lite_cwday, 0);
9421 
9422 #ifndef NDEBUG
9423  rb_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
9424  rb_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
9425 #endif
9426 
9427  rb_define_method(cDate, "wday", d_lite_wday, 0);
9428 
9429  rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0);
9430  rb_define_method(cDate, "monday?", d_lite_monday_p, 0);
9431  rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0);
9432  rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0);
9433  rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0);
9434  rb_define_method(cDate, "friday?", d_lite_friday_p, 0);
9435  rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
9436 
9437 #ifndef NDEBUG
9438  rb_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
9439 #endif
9440 
9441  rb_define_private_method(cDate, "hour", d_lite_zero, 0);
9442  rb_define_private_method(cDate, "min", d_lite_zero, 0);
9443  rb_define_private_method(cDate, "minute", d_lite_zero, 0);
9444  rb_define_private_method(cDate, "sec", d_lite_zero, 0);
9445  rb_define_private_method(cDate, "second", d_lite_zero, 0);
9446 
9447  rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
9448  rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
9449  rb_define_method(cDate, "leap?", d_lite_leap_p, 0);
9450 
9451  rb_define_method(cDate, "start", d_lite_start, 0);
9452  rb_define_method(cDate, "new_start", d_lite_new_start, -1);
9453  rb_define_method(cDate, "italy", d_lite_italy, 0);
9454  rb_define_method(cDate, "england", d_lite_england, 0);
9455  rb_define_method(cDate, "julian", d_lite_julian, 0);
9456  rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
9457 
9458  rb_define_method(cDate, "+", d_lite_plus, 1);
9459  rb_define_method(cDate, "-", d_lite_minus, 1);
9460 
9461  rb_define_method(cDate, "next_day", d_lite_next_day, -1);
9462  rb_define_method(cDate, "prev_day", d_lite_prev_day, -1);
9463  rb_define_method(cDate, "next", d_lite_next, 0);
9464  rb_define_method(cDate, "succ", d_lite_next, 0);
9465 
9466  rb_define_method(cDate, ">>", d_lite_rshift, 1);
9467  rb_define_method(cDate, "<<", d_lite_lshift, 1);
9468 
9469  rb_define_method(cDate, "next_month", d_lite_next_month, -1);
9470  rb_define_method(cDate, "prev_month", d_lite_prev_month, -1);
9471  rb_define_method(cDate, "next_year", d_lite_next_year, -1);
9472  rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
9473 
9474  rb_define_method(cDate, "step", d_lite_step, -1);
9475  rb_define_method(cDate, "upto", d_lite_upto, 1);
9476  rb_define_method(cDate, "downto", d_lite_downto, 1);
9477 
9478  rb_define_method(cDate, "<=>", d_lite_cmp, 1);
9479  rb_define_method(cDate, "===", d_lite_equal, 1);
9480  rb_define_method(cDate, "eql?", d_lite_eql_p, 1);
9481  rb_define_method(cDate, "hash", d_lite_hash, 0);
9482 
9483  rb_define_method(cDate, "to_s", d_lite_to_s, 0);
9484 #ifndef NDEBUG
9485  rb_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
9486 #endif
9487  rb_define_method(cDate, "inspect", d_lite_inspect, 0);
9488 
9489  rb_define_method(cDate, "strftime", d_lite_strftime, -1);
9490 
9491  rb_define_method(cDate, "asctime", d_lite_asctime, 0);
9492  rb_define_method(cDate, "ctime", d_lite_asctime, 0);
9493  rb_define_method(cDate, "iso8601", d_lite_iso8601, 0);
9494  rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0);
9495  rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0);
9496  rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0);
9497  rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0);
9498  rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
9499  rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
9500 
9501 #ifndef NDEBUG
9502  rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
9503 #endif
9504  rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
9505  rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
9506  rb_define_singleton_method(cDate, "_load", date_s__load, 1);
9507 
9508  /*
9509  * == DateTime
9510  *
9511  * A subclass of Date that easily handles date, hour, minute, second,
9512  * and offset.
9513  *
9514  * DateTime does not consider any leap seconds, does not track
9515  * any summer time rules.
9516  *
9517  * A DateTime object is created with DateTime::new, DateTime::jd,
9518  * DateTime::ordinal, DateTime::commercial, DateTime::parse,
9519  * DateTime::strptime, DateTime::now, Time#to_datetime, etc.
9520  *
9521  * require 'date'
9522  *
9523  * DateTime.new(2001,2,3,4,5,6)
9524  * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
9525  *
9526  * The last element of day, hour, minute, or second can be a
9527  * fractional number. The fractional number's precision is assumed
9528  * at most nanosecond.
9529  *
9530  * DateTime.new(2001,2,3.5)
9531  * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
9532  *
9533  * An optional argument, the offset, indicates the difference
9534  * between the local time and UTC. For example, <tt>Rational(3,24)</tt>
9535  * represents ahead of 3 hours of UTC, <tt>Rational(-5,24)</tt> represents
9536  * behind of 5 hours of UTC. The offset should be -1 to +1, and
9537  * its precision is assumed at most second. The default value is
9538  * zero (equals to UTC).
9539  *
9540  * DateTime.new(2001,2,3,4,5,6,Rational(3,24))
9541  * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
9542  *
9543  * The offset also accepts string form:
9544  *
9545  * DateTime.new(2001,2,3,4,5,6,'+03:00')
9546  * #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
9547  *
9548  * An optional argument, the day of calendar reform (+start+), denotes
9549  * a Julian day number, which should be 2298874 to 2426355 or
9550  * negative/positive infinity.
9551  * The default value is +Date::ITALY+ (2299161=1582-10-15).
9552  *
9553  * A DateTime object has various methods. See each reference.
9554  *
9555  * d = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
9556  * #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...>
9557  * d.hour #=> 4
9558  * d.min #=> 5
9559  * d.sec #=> 6
9560  * d.offset #=> (7/48)
9561  * d.zone #=> "+03:30"
9562  * d += Rational('1.5')
9563  * #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...>
9564  * d = d.new_offset('+09:00')
9565  * #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...>
9566  * d.strftime('%I:%M:%S %p')
9567  * #=> "09:35:06 PM"
9568  * d > DateTime.new(1999)
9569  * #=> true
9570  *
9571  * === When should you use DateTime and when should you use Time?
9572  *
9573  * It's a common misconception that
9574  * {William Shakespeare}[http://en.wikipedia.org/wiki/William_Shakespeare]
9575  * and
9576  * {Miguel de Cervantes}[http://en.wikipedia.org/wiki/Miguel_de_Cervantes]
9577  * died on the same day in history -
9578  * so much so that UNESCO named April 23 as
9579  * {World Book Day because of this fact}[http://en.wikipedia.org/wiki/World_Book_Day].
9580  * However, because England hadn't yet adopted the
9581  * {Gregorian Calendar Reform}[http://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
9582  * (and wouldn't until {1752}[http://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
9583  * their deaths are actually 10 days apart.
9584  * Since Ruby's Time class implements a
9585  * {proleptic Gregorian calendar}[http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
9586  * and has no concept of calendar reform there's no way
9587  * to express this with Time objects. This is where DateTime steps in:
9588  *
9589  * shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
9590  * #=> Tue, 23 Apr 1616 00:00:00 +0000
9591  * cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
9592  * #=> Sat, 23 Apr 1616 00:00:00 +0000
9593  *
9594  * Already you can see something is weird - the days of the week
9595  * are different. Taking this further:
9596  *
9597  * cervantes == shakespeare
9598  * #=> false
9599  * (shakespeare - cervantes).to_i
9600  * #=> 10
9601  *
9602  * This shows that in fact they died 10 days apart (in reality
9603  * 11 days since Cervantes died a day earlier but was buried on
9604  * the 23rd). We can see the actual date of Shakespeare's death by
9605  * using the #gregorian method to convert it:
9606  *
9607  * shakespeare.gregorian
9608  * #=> Tue, 03 May 1616 00:00:00 +0000
9609  *
9610  * So there's an argument that all the celebrations that take
9611  * place on the 23rd April in Stratford-upon-Avon are actually
9612  * the wrong date since England is now using the Gregorian calendar.
9613  * You can see why when we transition across the reform
9614  * date boundary:
9615  *
9616  * # start off with the anniversary of Shakespeare's birth in 1751
9617  * shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND)
9618  * #=> Tue, 23 Apr 1751 00:00:00 +0000
9619  *
9620  * # add 366 days since 1752 is a leap year and April 23 is after February 29
9621  * shakespeare + 366
9622  * #=> Thu, 23 Apr 1752 00:00:00 +0000
9623  *
9624  * # add another 365 days to take us to the anniversary in 1753
9625  * shakespeare + 366 + 365
9626  * #=> Fri, 04 May 1753 00:00:00 +0000
9627  *
9628  * As you can see, if we're accurately tracking the number of
9629  * {solar years}[http://en.wikipedia.org/wiki/Tropical_year]
9630  * since Shakespeare's birthday then the correct anniversary date
9631  * would be the 4th May and not the 23rd April.
9632  *
9633  * So when should you use DateTime in Ruby and when should
9634  * you use Time? Almost certainly you'll want to use Time
9635  * since your app is probably dealing with current dates and
9636  * times. However, if you need to deal with dates and times in a
9637  * historical context you'll want to use DateTime to avoid
9638  * making the same mistakes as UNESCO. If you also have to deal
9639  * with timezones then best of luck - just bear in mind that
9640  * you'll probably be dealing with
9641  * {local solar times}[http://en.wikipedia.org/wiki/Solar_time],
9642  * since it wasn't until the 19th century that the introduction
9643  * of the railways necessitated the need for
9644  * {Standard Time}[http://en.wikipedia.org/wiki/Standard_time#Great_Britain]
9645  * and eventually timezones.
9646  */
9647 
9648  cDateTime = rb_define_class("DateTime", cDate);
9649  rb_define_alloc_func(cDateTime, d_lite_s_alloc_complex);
9650 
9651  rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
9652  rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
9653  rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
9654  rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
9655  rb_define_singleton_method(cDateTime, "commercial",
9656  datetime_s_commercial, -1);
9657 
9658 #ifndef NDEBUG
9659  rb_define_singleton_method(cDateTime, "weeknum",
9660  datetime_s_weeknum, -1);
9661  rb_define_singleton_method(cDateTime, "nth_kday",
9662  datetime_s_nth_kday, -1);
9663 #endif
9664 
9665  rb_undef_method(CLASS_OF(cDateTime), "today");
9666 
9667  rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
9668  rb_define_singleton_method(cDateTime, "_strptime",
9669  datetime_s__strptime, -1);
9670  rb_define_singleton_method(cDateTime, "strptime",
9671  datetime_s_strptime, -1);
9672  rb_define_singleton_method(cDateTime, "parse",
9673  datetime_s_parse, -1);
9674  rb_define_singleton_method(cDateTime, "iso8601",
9675  datetime_s_iso8601, -1);
9676  rb_define_singleton_method(cDateTime, "rfc3339",
9677  datetime_s_rfc3339, -1);
9678  rb_define_singleton_method(cDateTime, "xmlschema",
9679  datetime_s_xmlschema, -1);
9680  rb_define_singleton_method(cDateTime, "rfc2822",
9681  datetime_s_rfc2822, -1);
9682  rb_define_singleton_method(cDateTime, "rfc822",
9683  datetime_s_rfc2822, -1);
9684  rb_define_singleton_method(cDateTime, "httpdate",
9685  datetime_s_httpdate, -1);
9686  rb_define_singleton_method(cDateTime, "jisx0301",
9687  datetime_s_jisx0301, -1);
9688 
9689  rb_define_method(cDateTime, "hour", d_lite_hour, 0);
9690  rb_define_method(cDateTime, "min", d_lite_min, 0);
9691  rb_define_method(cDateTime, "minute", d_lite_min, 0);
9692  rb_define_method(cDateTime, "sec", d_lite_sec, 0);
9693  rb_define_method(cDateTime, "second", d_lite_sec, 0);
9694  rb_define_method(cDateTime, "sec_fraction", d_lite_sec_fraction, 0);
9695  rb_define_method(cDateTime, "second_fraction", d_lite_sec_fraction, 0);
9696  rb_define_method(cDateTime, "offset", d_lite_offset, 0);
9697  rb_define_method(cDateTime, "zone", d_lite_zone, 0);
9698  rb_define_method(cDateTime, "new_offset", d_lite_new_offset, -1);
9699 
9700  rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
9701 
9702  rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
9703 
9704  rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1);
9705  rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1);
9706  rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
9707  rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
9708 
9709  /* conversions */
9710 
9711  rb_define_method(rb_cTime, "to_time", time_to_time, 0);
9712  rb_define_method(rb_cTime, "to_date", time_to_date, 0);
9713  rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0);
9714 
9715  rb_define_method(cDate, "to_time", date_to_time, 0);
9716  rb_define_method(cDate, "to_date", date_to_date, 0);
9717  rb_define_method(cDate, "to_datetime", date_to_datetime, 0);
9718 
9719  rb_define_method(cDateTime, "to_time", datetime_to_time, 0);
9720  rb_define_method(cDateTime, "to_date", datetime_to_date, 0);
9721  rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0);
9722 
9723 #ifndef NDEBUG
9724  /* tests */
9725 
9726  rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
9727  rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
9728  rb_define_singleton_method(cDate, "test_commercial",
9729  date_s_test_commercial, 0);
9730  rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
9731  rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
9732  rb_define_singleton_method(cDate, "test_unit_conv",
9733  date_s_test_unit_conv, 0);
9734  rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
9735 #endif
9736 }
9737 
9738 /*
9739 Local variables:
9740 c-file-style: "ruby"
9741 End:
9742 */
f_idiv
#define f_idiv(x, y)
Definition: date_core.c:38
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5703
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
f_to_i
#define f_to_i(x)
Definition: date_core.c:47
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2848
f_round
#define f_round(x)
Definition: date_core.c:45
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
GREGORIAN
#define GREGORIAN
Definition: date_core.c:181
timezone
Definition: missing.h:67
get_d1
#define get_d1(x)
Definition: date_core.c:297
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
f_positive_p
#define f_positive_p(x)
Definition: date_core.c:147
f_jd
#define f_jd(x)
Definition: date_core.c:150
assert
#define assert(x)
Definition: dlmalloc.c:1176
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13179
JULIAN
#define JULIAN
Definition: date_core.c:180
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1523
DateData::c
struct ComplexDateData c
Definition: date_core.c:294
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7065
ComplexDateData::flags
unsigned flags
Definition: date_core.c:270
tm::tm_min
int tm_min
Definition: rb_mjit_min_header-2.7.1.h:1929
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
date__jisx0301
VALUE date__jisx0301(VALUE)
EX_MDAY
#define EX_MDAY(x)
Definition: date_core.c:222
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:2037
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.1.h:6546
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
f_sec
#define f_sec(x)
Definition: date_core.c:157
simple_dat_p
#define simple_dat_p(x)
Definition: date_core.c:176
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
set_to_complex
#define set_to_complex(obj, x, _nth, _jd,_df, _sf, _of, _sg, _year, _mon, _mday, _hour, _min, _sec, _flags)
Definition: date_core.c:367
INFINITY
#define INFINITY
Definition: missing.h:149
rb_enc_sprintf
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1178
VALUE
unsigned long VALUE
Definition: ruby.h:102
date_zone_to_diff
VALUE date_zone_to_diff(VALUE)
Definition: date_parse.c:410
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
CM_PERIOD_JCY
#define CM_PERIOD_JCY
Definition: date_core.c:196
ComplexDateData::nth
VALUE nth
Definition: date_core.c:272
encoding.h
modf
double modf(double, double *)
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
set_hash0
#define set_hash0(k, v)
Definition: date_core.c:3712
fmt
const VALUE int int int int int int VALUE char * fmt
Definition: rb_mjit_min_header-2.7.1.h:6423
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:2048
TYPE
#define TYPE(x)
Definition: ruby.h:554
SECOND_IN_NANOSECONDS
#define SECOND_IN_NANOSECONDS
Definition: date_core.c:190
date__rfc3339
VALUE date__rfc3339(VALUE)
val2sg
#define val2sg(vsg, dsg)
Definition: date_core.c:3264
rb_rational_num
VALUE rb_rational_num(VALUE rat)
Definition: rational.c:1960
rb_rational_den
VALUE rb_rational_den(VALUE rat)
Definition: rational.c:1966
CLOCK_REALTIME
#define CLOCK_REALTIME
Definition: win32.h:133
zone
Definition: zonetab.h:35
isinf
#define isinf(__x)
Definition: rb_mjit_min_header-2.7.1.h:3641
assert.h
get_d2
#define get_d2(x, y)
Definition: date_core.c:309
floor
double floor(double)
COMPLEX_DAT
#define COMPLEX_DAT
Definition: date_core.c:169
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:541
valid_sg
#define valid_sg(sg)
Definition: date_core.c:2429
tm::tm_sec
int tm_sec
Definition: rb_mjit_min_header-2.7.1.h:1928
CHAR_BIT
#define CHAR_BIT
Definition: ruby.h:227
canon24oc
#define canon24oc()
Definition: date_core.c:3250
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
ptr
struct RIMemo * ptr
Definition: debug.c:74
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.1.h:6077
SimpleDateData::sg
date_sg_t sg
Definition: date_core.c:253
Qfalse
#define Qfalse
Definition: ruby.h:467
SMALLBUF
#define SMALLBUF
Definition: date_core.c:6608
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:967
rb_cRational
RUBY_EXTERN VALUE rb_cRational
Definition: ruby.h:2041
f_floor
#define f_floor(x)
Definition: date_core.c:42
EX_MON
#define EX_MON(x)
Definition: date_core.c:223
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:104
NULL
#define NULL
Definition: _sdbm.c:101
ComplexDateData::sg
date_sg_t sg
Definition: date_core.c:273
have_jd_p
#define have_jd_p(x)
Definition: date_core.c:171
tm::tm_mon
int tm_mon
Definition: rb_mjit_min_header-2.7.1.h:1932
SimpleDateData::jd
int jd
Definition: date_core.c:251
rb_cmpint
#define rb_cmpint(cmp, a, b)
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
num2num_with_frac
#define num2num_with_frac(s, n)
Definition: date_core.c:3230
tm::tm_mday
int tm_mday
Definition: rb_mjit_min_header-2.7.1.h:1931
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_intern
#define rb_intern(str)
tmx
Definition: date_tmx.h:24
last
unsigned int last
Definition: nkf.c:4324
FL_SET
#define FL_SET(x, f)
Definition: ruby.h:1359
DAY_IN_SECONDS
#define DAY_IN_SECONDS
Definition: date_core.c:188
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
strlen
size_t strlen(const char *)
PACK5
#define PACK5(m, d, h, min, s)
Definition: date_core.c:225
have_time_p
#define have_time_p(x)
Definition: date_core.c:174
REFORM_BEGIN_YEAR
#define REFORM_BEGIN_YEAR
Definition: date_core.c:199
rb_num_coerce_cmp
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:453
tm::tm_hour
int tm_hour
Definition: rb_mjit_min_header-2.7.1.h:1930
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1440
SimpleDateData::flags
unsigned flags
Definition: date_core.c:250
num2int_with_frac
#define num2int_with_frac(s, n)
Definition: date_core.c:3240
strftimev
#define strftimev(fmt, time, enc)
Definition: time.c:4044
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1203
date_strftime
size_t date_strftime(char *s, size_t maxsize, const char *format, const struct tmx *tmx)
Definition: date_strftime.c:628
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
const
#define const
Definition: strftime.c:103
HAVE_CIVIL
#define HAVE_CIVIL
Definition: date_core.c:167
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Definition: rb_mjit_min_header-2.7.1.h:6079
EX_SEC
#define EX_SEC(x)
Definition: date_core.c:219
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
f_mod
#define f_mod(x, y)
Definition: date_core.c:39
CM_PERIOD
#define CM_PERIOD
Definition: date_core.c:195
f_ge_p
#define f_ge_p(x, y)
Definition: date_parse.c:29
JISX0301_DATE_SIZE
@ JISX0301_DATE_SIZE
Definition: date_core.c:7044
rb_rational_new2
#define rb_rational_new2(x, y)
Definition: intern.h:180
get_d1a
#define get_d1a(x)
Definition: date_core.c:301
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
tm::tm_isdst
int tm_isdst
Definition: rb_mjit_min_header-2.7.1.h:1936
round
RUBY_EXTERN double round(double)
Definition: numeric.c:80
f_mul
#define f_mul(x, y)
Definition: date_core.c:35
copy_simple_to_complex
#define copy_simple_to_complex(obj, x, y)
Definition: date_core.c:400
f_min
#define f_min(x)
Definition: date_core.c:156
mktime
time_t mktime(struct tm *_timeptr)
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
f_subsec
#define f_subsec(x)
Definition: date_core.c:8510
USE_PACK
#define USE_PACK
Definition: date_core.c:21
f_div
#define f_div(x, y)
Definition: date_core.c:36
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
f_mon
#define f_mon(x)
Definition: date_core.c:152
FL_EXIVAR
#define FL_EXIVAR
Definition: ruby.h:1286
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.1.h:5423
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
sym
#define sym(x)
Definition: date_core.c:3716
tzset
void tzset(void)
DECIMAL_SIZE_OF_LONG
@ DECIMAL_SIZE_OF_LONG
Definition: date_core.c:7043
REFORM_END_JD
#define REFORM_END_JD
Definition: date_core.c:202
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
DIV
#define DIV(n, d)
Definition: date_core.c:162
st_index_t
st_data_t st_index_t
Definition: st.h:50
f_quo
#define f_quo(x, y)
Definition: date_core.c:37
ruby.h
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
dup
int dup(int __fildes)
f_year
#define f_year(x)
Definition: date_core.c:151
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
set_hash
#define set_hash(k, v)
Definition: date_core.c:3718
isnan
#define isnan(x)
Definition: win32.h:369
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1447
f_ajd
#define f_ajd(x)
Definition: date_core.c:149
ComplexDateData::pc
unsigned pc
Definition: date_core.c:284
date__parse
VALUE date__parse(VALUE str, VALUE comp)
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
EX_HOUR
#define EX_HOUR(x)
Definition: date_core.c:221
PACK2
#define PACK2(m, d)
Definition: date_core.c:229
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
f_lt_p
#define f_lt_p(x, y)
Definition: date_parse.c:26
rb_enc_copy
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:990
size
int size
Definition: encoding.c:58
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
localtime
struct tm * localtime(const time_t *_timer)
have_civil_p
#define have_civil_p(x)
Definition: date_core.c:173
time_t
long time_t
Definition: rb_mjit_min_header-2.7.1.h:1231
MILLISECOND_IN_NANOSECONDS
#define MILLISECOND_IN_NANOSECONDS
Definition: date_core.c:6660
DateData::s
struct SimpleDateData s
Definition: date_core.c:293
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
tmx::dat
void * dat
Definition: date_tmx.h:25
LL2NUM
#define LL2NUM(v)
Definition: rb_mjit_min_header-2.7.1.h:4208
SimpleDateData
Definition: date_core.c:248
f_add
#define f_add(x, y)
Definition: date_core.c:33
set_to_simple
#define set_to_simple(obj, x, _nth, _jd,_sg, _year, _mon, _mday, _flags)
Definition: date_core.c:337
SimpleDateData::pc
unsigned pc
Definition: date_core.c:264
memchr
void * memchr(const void *, int, size_t)
HALF_DAYS_IN_SECONDS
#define HALF_DAYS_IN_SECONDS
Definition: date_core.c:1567
Init_date_core
void Init_date_core(void)
Definition: date_core.c:9099
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
DEFAULT_SG
#define DEFAULT_SG
Definition: date_core.c:182
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
val2off
#define val2off(vof, iof)
Definition: date_core.c:4718
difftime
double difftime(time_t _time2, time_t _time1)
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6333
rb_marshal_load
VALUE rb_marshal_load(VALUE)
Definition: marshal.c:2316
ComplexDateData
Definition: date_core.c:268
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
date__rfc2822
VALUE date__rfc2822(VALUE)
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
f_hour
#define f_hour(x)
Definition: date_core.c:155
tmx::funcs
const struct tmx_funcs * funcs
Definition: date_tmx.h:26
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
HOUR_IN_SECONDS
#define HOUR_IN_SECONDS
Definition: date_core.c:187
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
SECOND_IN_MILLISECONDS
#define SECOND_IN_MILLISECONDS
Definition: date_core.c:189
StringValue
use StringValue() instead")))
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
f
#define f
time
time_t time(time_t *_timer)
ITALY
#define ITALY
Definition: date_core.c:178
LONG_LONG
#define LONG_LONG
Definition: rb_mjit_min_header-2.7.1.h:3907
ref_hash
#define ref_hash(k)
Definition: date_core.c:3719
f_mday
#define f_mday(x)
Definition: date_core.c:153
gmtime
struct tm * gmtime(const time_t *_timer)
tmx_funcs
Definition: date_tmx.h:4
xmalloc
#define xmalloc
Definition: defines.h:211
ref_hash0
#define ref_hash0(k)
Definition: date_core.c:3713
DateData
Definition: date_core.c:291
have_df_p
#define have_df_p(x)
Definition: date_core.c:172
timeval
Definition: missing.h:53
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
date_sg_t
#define date_sg_t
Definition: date_core.c:240
ENGLAND
#define ENGLAND
Definition: date_core.c:179
HAVE_DF
#define HAVE_DF
Definition: date_core.c:166
FIXNUM_MIN
#define FIXNUM_MIN
Definition: ruby.h:260
date__httpdate
VALUE date__httpdate(VALUE)
rb_mComparable
VALUE rb_mComparable
Definition: compar.c:16
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
ComplexDateData::year
int year
Definition: date_core.c:275
ERANGE
#define ERANGE
Definition: rb_mjit_min_header-2.7.1.h:10896
UNIX_EPOCH_IN_CJD
#define UNIX_EPOCH_IN_CJD
Definition: date_core.c:184
get_d1b
#define get_d1b(x)
Definition: date_core.c:305
del_hash
#define del_hash(k)
Definition: date_core.c:3720
add_frac
#define add_frac()
Definition: date_core.c:3258
RETURN_FALSE_UNLESS_NUMERIC
#define RETURN_FALSE_UNLESS_NUMERIC(obj)
Definition: date_core.c:58
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2807
rb_enc_str_asciicompat_p
#define rb_enc_str_asciicompat_p(str)
Definition: encoding.h:257
complex_dat_p
#define complex_dat_p(x)
Definition: date_core.c:175
clock_gettime
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4612
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
SimpleDateData::nth
VALUE nth
Definition: date_core.c:252
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
f_local3
#define f_local3(x, y, m, d)
Definition: date_core.c:8512
argc
int argc
Definition: ruby.c:222
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1725
MOD
#define MOD(n, d)
Definition: date_core.c:163
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
MINUTE_IN_SECONDS
#define MINUTE_IN_SECONDS
Definition: date_core.c:186
id_cmp
#define id_cmp
Definition: array.c:30
tm
Definition: rb_mjit_min_header-2.7.1.h:1926
rb_data_type_struct
Definition: ruby.h:1148
tm::tm_year
int tm_year
Definition: rb_mjit_min_header-2.7.1.h:1933
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:966
xfree
#define xfree
Definition: defines.h:216
FIXNUM_MAX
#define FIXNUM_MAX
Definition: ruby.h:259
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12257
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5214
f_boolcast
#define f_boolcast(x)
Definition: date_core.c:29
REFORM_END_YEAR
#define REFORM_END_YEAR
Definition: date_core.c:200
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:889
Qtrue
#define Qtrue
Definition: ruby.h:468
errno
int errno
SimpleDateData::year
int year
Definition: date_core.c:255
ComplexDateData::of
int of
Definition: date_core.c:287
date_tmx.h
len
uint8_t len
Definition: escape.c:17
f_add3
#define f_add3(x, y, z)
Definition: date_core.c:52
date__iso8601
VALUE date__iso8601(VALUE)
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:909
f_negate
#define f_negate(x)
Definition: date_core.c:32
f_gt_p
#define f_gt_p(x, y)
Definition: date_parse.c:27
HAVE_JD
#define HAVE_JD
Definition: date_core.c:165
timespec
Definition: missing.h:60
EX_MIN
#define EX_MIN(x)
Definition: date_core.c:220
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
T_STRING
#define T_STRING
Definition: ruby.h:528
ComplexDateData::df
int df
Definition: date_core.c:286
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_rational_new1
#define rb_rational_new1(x)
Definition: intern.h:179
f_nonzero_p
#define f_nonzero_p(x)
Definition: date_core.c:137
date__xmlschema
VALUE date__xmlschema(VALUE)
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.1.h:1479
ComplexDateData::jd
int jd
Definition: date_core.c:271
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
DECIMAL_SIZE_OF_BITS
#define DECIMAL_SIZE_OF_BITS(n)
Definition: util.h:50
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
f_sub
#define f_sub(x, y)
Definition: date_core.c:34
f_utc_offset
#define f_utc_offset(x)
Definition: date_core.c:8511
ComplexDateData::sf
VALUE sf
Definition: date_core.c:288
CM_PERIOD_GCY
#define CM_PERIOD_GCY
Definition: date_core.c:197
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
DateData::flags
unsigned flags
Definition: date_core.c:292
f_to_r
#define f_to_r(x)
Definition: date_core.c:48
copy_complex_to_simple
#define copy_complex_to_simple(obj, x, y)
Definition: date_core.c:426
NUM2DBL
#define NUM2DBL(x)
Definition: ruby.h:774
canonicalize_jd
#define canonicalize_jd(_nth, _jd)
Definition: date_core.c:1120
tm::tm_gmtoff
long tm_gmtoff
Definition: rb_mjit_min_header-2.7.1.h:1937
util.h
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
rb_strlen_lit
#define rb_strlen_lit(str)
Definition: intern.h:913
gettimeofday
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4598
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
decode_offset
#define decode_offset(of, s, h, m)
Definition: date_core.c:1939
HAVE_TIME
#define HAVE_TIME
Definition: date_core.c:168
f_le_p
#define f_le_p(x, y)
Definition: date_parse.c:28
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1569
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
RTEST
#define RTEST(v)
Definition: ruby.h:481
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:415
date__strptime
VALUE date__strptime(const char *str, size_t slen, const char *fmt, size_t flen, VALUE hash)
RUBY_TYPED_WB_PROTECTED
#define RUBY_TYPED_WB_PROTECTED
Definition: ruby.h:1208
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.1.h:7826