Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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