00001
00002
00003
00004
00005 #include "ruby.h"
00006 #include "ruby/encoding.h"
00007 #include <math.h>
00008 #include <time.h>
00009
00010 #define NDEBUG
00011 #include <assert.h>
00012
00013 #ifdef RUBY_EXTCONF_H
00014 #include RUBY_EXTCONF_H
00015 #endif
00016
00017 #define USE_PACK
00018
00019 static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p;
00020 static VALUE cDate, cDateTime;
00021 static VALUE half_days_in_day, day_in_nanoseconds;
00022 static double positive_inf, negative_inf;
00023
00024 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
00025
00026 #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
00027 #define f_negate(x) rb_funcall(x, rb_intern("-@"), 0)
00028 #define f_add(x,y) rb_funcall(x, '+', 1, y)
00029 #define f_sub(x,y) rb_funcall(x, '-', 1, y)
00030 #define f_mul(x,y) rb_funcall(x, '*', 1, y)
00031 #define f_div(x,y) rb_funcall(x, '/', 1, y)
00032 #define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y)
00033 #define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y)
00034 #define f_mod(x,y) rb_funcall(x, '%', 1, y)
00035 #define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y)
00036 #define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y)
00037 #define f_floor(x) rb_funcall(x, rb_intern("floor"), 0)
00038 #define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0)
00039 #define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0)
00040 #define f_round(x) rb_funcall(x, rb_intern("round"), 0)
00041
00042 #define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0)
00043 #define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0)
00044 #define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0)
00045 #define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0)
00046
00047 #define f_add3(x,y,z) f_add(f_add(x, y), z)
00048 #define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
00049
00050 inline static VALUE
00051 f_cmp(VALUE x, VALUE y)
00052 {
00053 if (FIXNUM_P(x) && FIXNUM_P(y)) {
00054 long c = FIX2LONG(x) - FIX2LONG(y);
00055 if (c > 0)
00056 c = 1;
00057 else if (c < 0)
00058 c = -1;
00059 return INT2FIX(c);
00060 }
00061 return rb_funcall(x, id_cmp, 1, y);
00062 }
00063
00064 inline static VALUE
00065 f_lt_p(VALUE x, VALUE y)
00066 {
00067 if (FIXNUM_P(x) && FIXNUM_P(y))
00068 return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
00069 return rb_funcall(x, '<', 1, y);
00070 }
00071
00072 inline static VALUE
00073 f_gt_p(VALUE x, VALUE y)
00074 {
00075 if (FIXNUM_P(x) && FIXNUM_P(y))
00076 return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
00077 return rb_funcall(x, '>', 1, y);
00078 }
00079
00080 inline static VALUE
00081 f_le_p(VALUE x, VALUE y)
00082 {
00083 if (FIXNUM_P(x) && FIXNUM_P(y))
00084 return f_boolcast(FIX2LONG(x) <= FIX2LONG(y));
00085 return rb_funcall(x, id_le_p, 1, y);
00086 }
00087
00088 inline static VALUE
00089 f_ge_p(VALUE x, VALUE y)
00090 {
00091 if (FIXNUM_P(x) && FIXNUM_P(y))
00092 return f_boolcast(FIX2LONG(x) >= FIX2LONG(y));
00093 return rb_funcall(x, rb_intern(">="), 1, y);
00094 }
00095
00096 inline static VALUE
00097 f_eqeq_p(VALUE x, VALUE y)
00098 {
00099 if (FIXNUM_P(x) && FIXNUM_P(y))
00100 return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
00101 return rb_funcall(x, rb_intern("=="), 1, y);
00102 }
00103
00104 inline static VALUE
00105 f_zero_p(VALUE x)
00106 {
00107 switch (TYPE(x)) {
00108 case T_FIXNUM:
00109 return f_boolcast(FIX2LONG(x) == 0);
00110 case T_BIGNUM:
00111 return Qfalse;
00112 case T_RATIONAL:
00113 {
00114 VALUE num = RRATIONAL(x)->num;
00115 return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
00116 }
00117 }
00118 return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0));
00119 }
00120
00121 #define f_nonzero_p(x) (!f_zero_p(x))
00122
00123 inline static VALUE
00124 f_negative_p(VALUE x)
00125 {
00126 if (FIXNUM_P(x))
00127 return f_boolcast(FIX2LONG(x) < 0);
00128 return rb_funcall(x, '<', 1, INT2FIX(0));
00129 }
00130
00131 #define f_positive_p(x) (!f_negative_p(x))
00132
00133 #define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0)
00134 #define f_jd(x) rb_funcall(x, rb_intern("jd"), 0)
00135 #define f_year(x) rb_funcall(x, rb_intern("year"), 0)
00136 #define f_mon(x) rb_funcall(x, rb_intern("mon"), 0)
00137 #define f_mday(x) rb_funcall(x, rb_intern("mday"), 0)
00138 #define f_wday(x) rb_funcall(x, rb_intern("wday"), 0)
00139 #define f_hour(x) rb_funcall(x, rb_intern("hour"), 0)
00140 #define f_min(x) rb_funcall(x, rb_intern("min"), 0)
00141 #define f_sec(x) rb_funcall(x, rb_intern("sec"), 0)
00142
00143
00144 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
00145 #define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
00146 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
00147 #define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
00148
00149 #define HAVE_JD (1 << 0)
00150 #define HAVE_DF (1 << 1)
00151 #define HAVE_CIVIL (1 << 2)
00152 #define HAVE_TIME (1 << 3)
00153 #define COMPLEX_DAT (1 << 7)
00154
00155 #define have_jd_p(x) ((x)->flags & HAVE_JD)
00156 #define have_df_p(x) ((x)->flags & HAVE_DF)
00157 #define have_civil_p(x) ((x)->flags & HAVE_CIVIL)
00158 #define have_time_p(x) ((x)->flags & HAVE_TIME)
00159 #define complex_dat_p(x) ((x)->flags & COMPLEX_DAT)
00160 #define simple_dat_p(x) (!complex_dat_p(x))
00161
00162 #define ITALY 2299161
00163 #define ENGLAND 2361222
00164 #define JULIAN positive_inf
00165 #define GREGORIAN negative_inf
00166 #define DEFAULT_SG ITALY
00167
00168 #define UNIX_EPOCH_IN_CJD INT2FIX(2440588)
00169
00170 #define MINUTE_IN_SECONDS 60
00171 #define HOUR_IN_SECONDS 3600
00172 #define DAY_IN_SECONDS 86400
00173 #define SECOND_IN_MILLISECONDS 1000
00174 #define SECOND_IN_NANOSECONDS 1000000000
00175
00176 #define JC_PERIOD0 1461
00177 #define GC_PERIOD0 146097
00178 #define CM_PERIOD0 71149239
00179 #define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0)
00180 #define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4)
00181 #define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400)
00182
00183 #define REFORM_BEGIN_YEAR 1582
00184 #define REFORM_END_YEAR 1930
00185 #define REFORM_BEGIN_JD 2298874
00186 #define REFORM_END_JD 2426355
00187
00188 #ifdef USE_PACK
00189 #define SEC_WIDTH 6
00190 #define MIN_WIDTH 6
00191 #define HOUR_WIDTH 5
00192 #define MDAY_WIDTH 5
00193 #define MON_WIDTH 4
00194
00195 #define SEC_SHIFT 0
00196 #define MIN_SHIFT SEC_WIDTH
00197 #define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH)
00198 #define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
00199 #define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH)
00200
00201 #define PK_MASK(x) ((1 << (x)) - 1)
00202
00203 #define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH))
00204 #define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH))
00205 #define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH))
00206 #define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH))
00207 #define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH))
00208
00209 #define PACK5(m,d,h,min,s) \
00210 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\
00211 ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT))
00212
00213 #define PACK2(m,d) \
00214 (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT))
00215 #endif
00216
00217 #ifdef HAVE_FLOAT_H
00218 #include <float.h>
00219 #endif
00220
00221 #if defined(FLT_RADIX) && defined(FLT_MANT_DIG)
00222 #if FLT_RADIX == 2 && FLT_MANT_DIG > 22
00223 #define USE_FLOAT
00224 #define sg_cast float
00225 #else
00226 #define sg_cast double
00227 #endif
00228 #endif
00229
00230
00231
00232
00233
00234
00235 struct SimpleDateData
00236 {
00237 unsigned flags;
00238 VALUE nth;
00239 int jd;
00240
00241
00242
00243 #ifndef USE_FLOAT
00244 double sg;
00245 #else
00246 float sg;
00247 #endif
00248
00249 int year;
00250 #ifndef USE_PACK
00251 int mon;
00252 int mday;
00253
00254
00255
00256 #else
00257
00258 unsigned pc;
00259 #endif
00260 };
00261
00262 struct ComplexDateData
00263 {
00264 unsigned flags;
00265 VALUE nth;
00266 int jd;
00267 int df;
00268 VALUE sf;
00269 int of;
00270 #ifndef USE_FLOAT
00271 double sg;
00272 #else
00273 float sg;
00274 #endif
00275
00276 int year;
00277 #ifndef USE_PACK
00278 int mon;
00279 int mday;
00280 int hour;
00281 int min;
00282 int sec;
00283 #else
00284
00285 unsigned pc;
00286 #endif
00287 };
00288
00289 union DateData {
00290 unsigned flags;
00291 struct SimpleDateData s;
00292 struct ComplexDateData c;
00293 };
00294
00295 #define get_d1(x)\
00296 union DateData *dat;\
00297 Data_Get_Struct(x, union DateData, dat);
00298
00299 #define get_d1a(x)\
00300 union DateData *adat;\
00301 Data_Get_Struct(x, union DateData, adat);
00302
00303 #define get_d1b(x)\
00304 union DateData *bdat;\
00305 Data_Get_Struct(x, union DateData, bdat);
00306
00307 #define get_d2(x,y)\
00308 union DateData *adat, *bdat;\
00309 Data_Get_Struct(x, union DateData, adat);\
00310 Data_Get_Struct(y, union DateData, bdat);
00311
00312 inline static VALUE
00313 canon(VALUE x)
00314 {
00315 if (TYPE(x) == T_RATIONAL) {
00316 VALUE den = RRATIONAL(x)->den;
00317 if (FIXNUM_P(den) && FIX2LONG(den) == 1)
00318 return RRATIONAL(x)->num;
00319 }
00320 return x;
00321 }
00322
00323 #ifndef USE_PACK
00324 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
00325 {\
00326 (x)->nth = canon(_nth);\
00327 (x)->jd = _jd;\
00328 (x)->sg = (sg_cast)(_sg);\
00329 (x)->year = _year;\
00330 (x)->mon = _mon;\
00331 (x)->mday = _mday;\
00332 (x)->flags = _flags;\
00333 }
00334 #else
00335 #define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \
00336 {\
00337 (x)->nth = canon(_nth);\
00338 (x)->jd = _jd;\
00339 (x)->sg = (sg_cast)(_sg);\
00340 (x)->year = _year;\
00341 (x)->pc = PACK2(_mon, _mday);\
00342 (x)->flags = _flags;\
00343 }
00344 #endif
00345
00346 #ifndef USE_PACK
00347 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
00348 _year, _mon, _mday, _hour, _min, _sec, _flags) \
00349 {\
00350 (x)->nth = canon(_nth);\
00351 (x)->jd = _jd;\
00352 (x)->df = _df;\
00353 (x)->sf = canon(_sf);\
00354 (x)->of = _of;\
00355 (x)->sg = (sg_cast)(_sg);\
00356 (x)->year = _year;\
00357 (x)->mon = _mon;\
00358 (x)->mday = _mday;\
00359 (x)->hour = _hour;\
00360 (x)->min = _min;\
00361 (x)->sec = _sec;\
00362 (x)->flags = _flags;\
00363 }
00364 #else
00365 #define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\
00366 _year, _mon, _mday, _hour, _min, _sec, _flags) \
00367 {\
00368 (x)->nth = canon(_nth);\
00369 (x)->jd = _jd;\
00370 (x)->df = _df;\
00371 (x)->sf = canon(_sf);\
00372 (x)->of = _of;\
00373 (x)->sg = (sg_cast)(_sg);\
00374 (x)->year = _year;\
00375 (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\
00376 (x)->flags = _flags;\
00377 }
00378 #endif
00379
00380 #ifndef USE_PACK
00381 #define copy_simple_to_complex(x, y) \
00382 {\
00383 (x)->nth = (y)->nth;\
00384 (x)->jd = (y)->jd;\
00385 (x)->df = 0;\
00386 (x)->sf = INT2FIX(0);\
00387 (x)->of = 0;\
00388 (x)->sg = (sg_cast)((y)->sg);\
00389 (x)->year = (y)->year;\
00390 (x)->mon = (y)->mon;\
00391 (x)->mday = (y)->mday;\
00392 (x)->hour = 0;\
00393 (x)->min = 0;\
00394 (x)->sec = 0;\
00395 (x)->flags = (y)->flags;\
00396 }
00397 #else
00398 #define copy_simple_to_complex(x, y) \
00399 {\
00400 (x)->nth = (y)->nth;\
00401 (x)->jd = (y)->jd;\
00402 (x)->df = 0;\
00403 (x)->sf = INT2FIX(0);\
00404 (x)->of = 0;\
00405 (x)->sg = (sg_cast)((y)->sg);\
00406 (x)->year = (y)->year;\
00407 (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\
00408 (x)->flags = (y)->flags;\
00409 }
00410 #endif
00411
00412 #ifndef USE_PACK
00413 #define copy_complex_to_simple(x, y) \
00414 {\
00415 (x)->nth = (y)->nth;\
00416 (x)->jd = (y)->jd;\
00417 (x)->sg = (sg_cast)((y)->sg);\
00418 (x)->year = (y)->year;\
00419 (x)->mon = (y)->mon;\
00420 (x)->mday = (y)->mday;\
00421 (x)->flags = (y)->flags;\
00422 }
00423 #else
00424 #define copy_complex_to_simple(x, y) \
00425 {\
00426 (x)->nth = (y)->nth;\
00427 (x)->jd = (y)->jd;\
00428 (x)->sg = (sg_cast)((y)->sg);\
00429 (x)->year = (y)->year;\
00430 (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\
00431 (x)->flags = (y)->flags;\
00432 }
00433 #endif
00434
00435
00436
00437 static int c_valid_civil_p(int, int, int, double,
00438 int *, int *, int *, int *);
00439
00440 static int
00441 c_find_fdoy(int y, double sg, int *rjd, int *ns)
00442 {
00443 int d, rm, rd;
00444
00445 for (d = 1; d < 31; d++)
00446 if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
00447 return 1;
00448 return 0;
00449 }
00450
00451 static int
00452 c_find_ldoy(int y, double sg, int *rjd, int *ns)
00453 {
00454 int i, rm, rd;
00455
00456 for (i = 0; i < 30; i++)
00457 if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
00458 return 1;
00459 return 0;
00460 }
00461
00462 #ifndef NDEBUG
00463 static int
00464 c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
00465 {
00466 int d, rm, rd;
00467
00468 for (d = 1; d < 31; d++)
00469 if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns))
00470 return 1;
00471 return 0;
00472 }
00473 #endif
00474
00475 static int
00476 c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
00477 {
00478 int i, rm, rd;
00479
00480 for (i = 0; i < 30; i++)
00481 if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
00482 return 1;
00483 return 0;
00484 }
00485
00486 static void
00487 c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
00488 {
00489 double a, b, jd;
00490
00491 if (m <= 2) {
00492 y -= 1;
00493 m += 12;
00494 }
00495 a = floor(y / 100.0);
00496 b = 2 - a + floor(a / 4.0);
00497 jd = floor(365.25 * (y + 4716)) +
00498 floor(30.6001 * (m + 1)) +
00499 d + b - 1524;
00500 if (jd < sg) {
00501 jd -= b;
00502 *ns = 0;
00503 }
00504 else
00505 *ns = 1;
00506
00507 *rjd = (int)jd;
00508 }
00509
00510 static void
00511 c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
00512 {
00513 double x, a, b, c, d, e, y, m, dom;
00514
00515 if (jd < sg)
00516 a = jd;
00517 else {
00518 x = floor((jd - 1867216.25) / 36524.25);
00519 a = jd + 1 + x - floor(x / 4.0);
00520 }
00521 b = a + 1524;
00522 c = floor((b - 122.1) / 365.25);
00523 d = floor(365.25 * c);
00524 e = floor((b - d) / 30.6001);
00525 dom = b - d - floor(30.6001 * e);
00526 if (e <= 13) {
00527 m = e - 1;
00528 y = c - 4716;
00529 }
00530 else {
00531 m = e - 13;
00532 y = c - 4715;
00533 }
00534
00535 *ry = (int)y;
00536 *rm = (int)m;
00537 *rdom = (int)dom;
00538 }
00539
00540 static void
00541 c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns)
00542 {
00543 int ns2;
00544
00545 c_find_fdoy(y, sg, rjd, &ns2);
00546 *rjd += d - 1;
00547 *ns = (*rjd < sg) ? 0 : 1;
00548 }
00549
00550 static void
00551 c_jd_to_ordinal(int jd, double sg, int *ry, int *rd)
00552 {
00553 int rm2, rd2, rjd, ns;
00554
00555 c_jd_to_civil(jd, sg, ry, &rm2, &rd2);
00556 c_find_fdoy(*ry, sg, &rjd, &ns);
00557 *rd = (jd - rjd) + 1;
00558 }
00559
00560 static void
00561 c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns)
00562 {
00563 int rjd2, ns2;
00564
00565 c_find_fdoy(y, sg, &rjd2, &ns2);
00566 rjd2 += 3;
00567 *rjd =
00568 (rjd2 - MOD((rjd2 - 1) + 1, 7)) +
00569 7 * (w - 1) +
00570 (d - 1);
00571 *ns = (*rjd < sg) ? 0 : 1;
00572 }
00573
00574 static void
00575 c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd)
00576 {
00577 int ry2, rm2, rd2, a, rjd2, ns2;
00578
00579 c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2);
00580 a = ry2;
00581 c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2);
00582 if (jd >= rjd2)
00583 *ry = a + 1;
00584 else {
00585 c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2);
00586 *ry = a;
00587 }
00588 *rw = 1 + DIV(jd - rjd2, 7);
00589 *rd = MOD(jd + 1, 7);
00590 if (*rd == 0)
00591 *rd = 7;
00592 }
00593
00594 static void
00595 c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns)
00596 {
00597 int rjd2, ns2;
00598
00599 c_find_fdoy(y, sg, &rjd2, &ns2);
00600 rjd2 += 6;
00601 *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d;
00602 *ns = (*rjd < sg) ? 0 : 1;
00603 }
00604
00605 static void
00606 c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
00607 {
00608 int rm, rd2, rjd, ns, j;
00609
00610 c_jd_to_civil(jd, sg, ry, &rm, &rd2);
00611 c_find_fdoy(*ry, sg, &rjd, &ns);
00612 rjd += 6;
00613 j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7;
00614 *rw = (int)DIV(j, 7);
00615 *rd = (int)MOD(j, 7);
00616 }
00617
00618 #ifndef NDEBUG
00619 static void
00620 c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
00621 {
00622 int rjd2, ns2;
00623
00624 if (n > 0) {
00625 c_find_fdom(y, m, sg, &rjd2, &ns2);
00626 rjd2 -= 1;
00627 }
00628 else {
00629 c_find_ldom(y, m, sg, &rjd2, &ns2);
00630 rjd2 += 7;
00631 }
00632 *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n;
00633 *ns = (*rjd < sg) ? 0 : 1;
00634 }
00635 #endif
00636
00637 inline static int
00638 c_jd_to_wday(int jd)
00639 {
00640 return MOD(jd + 1, 7);
00641 }
00642
00643 #ifndef NDEBUG
00644 static void
00645 c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
00646 {
00647 int rd, rjd, ns2;
00648
00649 c_jd_to_civil(jd, sg, ry, rm, &rd);
00650 c_find_fdom(*ry, *rm, sg, &rjd, &ns2);
00651 *rn = DIV(jd - rjd, 7) + 1;
00652 *rk = c_jd_to_wday(jd);
00653 }
00654 #endif
00655
00656 static int
00657 c_valid_ordinal_p(int y, int d, double sg,
00658 int *rd, int *rjd, int *ns)
00659 {
00660 int ry2, rd2;
00661
00662 if (d < 0) {
00663 int rjd2, ns2;
00664
00665 if (!c_find_ldoy(y, sg, &rjd2, &ns2))
00666 return 0;
00667 c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2);
00668 if (ry2 != y)
00669 return 0;
00670 d = rd2;
00671 }
00672 c_ordinal_to_jd(y, d, sg, rjd, ns);
00673 c_jd_to_ordinal(*rjd, sg, &ry2, &rd2);
00674 if (ry2 != y || rd2 != d)
00675 return 0;
00676 return 1;
00677 }
00678
00679 static const int monthtab[2][13] = {
00680 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00681 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00682 };
00683
00684 inline static int
00685 c_julian_leap_p(int y)
00686 {
00687 return MOD(y, 4) == 0;
00688 }
00689
00690 inline static int
00691 c_gregorian_leap_p(int y)
00692 {
00693 return MOD(y, 4) == 0 && y % 100 != 0 || MOD(y, 400) == 0;
00694 }
00695
00696 static int
00697 c_julian_last_day_of_month(int y, int m)
00698 {
00699 assert(m >= 1 && m <= 12);
00700 return monthtab[c_julian_leap_p(y) ? 1 : 0][m];
00701 }
00702
00703 static int
00704 c_gregorian_last_day_of_month(int y, int m)
00705 {
00706 assert(m >= 1 && m <= 12);
00707 return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
00708 }
00709
00710 static int
00711 c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
00712 {
00713 int last;
00714
00715 if (m < 0)
00716 m += 13;
00717 if (m < 1 || m > 12)
00718 return 0;
00719 last = c_julian_last_day_of_month(y, m);
00720 if (d < 0)
00721 d = last + d + 1;
00722 if (d < 1 || d > last)
00723 return 0;
00724 *rm = m;
00725 *rd = d;
00726 return 1;
00727 }
00728
00729 static int
00730 c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd)
00731 {
00732 int last;
00733
00734 if (m < 0)
00735 m += 13;
00736 if (m < 1 || m > 12)
00737 return 0;
00738 last = c_gregorian_last_day_of_month(y, m);
00739 if (d < 0)
00740 d = last + d + 1;
00741 if (d < 1 || d > last)
00742 return 0;
00743 *rm = m;
00744 *rd = d;
00745 return 1;
00746 }
00747
00748 static int
00749 c_valid_civil_p(int y, int m, int d, double sg,
00750 int *rm, int *rd, int *rjd, int *ns)
00751 {
00752 int ry;
00753
00754 if (m < 0)
00755 m += 13;
00756 if (d < 0) {
00757 if (!c_find_ldom(y, m, sg, rjd, ns))
00758 return 0;
00759 c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd);
00760 if (ry != y || *rm != m)
00761 return 0;
00762 d = *rd;
00763 }
00764 c_civil_to_jd(y, m, d, sg, rjd, ns);
00765 c_jd_to_civil(*rjd, sg, &ry, rm, rd);
00766 if (ry != y || *rm != m || *rd != d)
00767 return 0;
00768 return 1;
00769 }
00770
00771 static int
00772 c_valid_commercial_p(int y, int w, int d, double sg,
00773 int *rw, int *rd, int *rjd, int *ns)
00774 {
00775 int ns2, ry2, rw2, rd2;
00776
00777 if (d < 0)
00778 d += 8;
00779 if (w < 0) {
00780 int rjd2;
00781
00782 c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
00783 c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
00784 if (ry2 != y)
00785 return 0;
00786 w = rw2;
00787 }
00788 c_commercial_to_jd(y, w, d, sg, rjd, ns);
00789 c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
00790 if (y != ry2 || w != *rw || d != *rd)
00791 return 0;
00792 return 1;
00793 }
00794
00795 static int
00796 c_valid_weeknum_p(int y, int w, int d, int f, double sg,
00797 int *rw, int *rd, int *rjd, int *ns)
00798 {
00799 int ns2, ry2, rw2, rd2;
00800
00801 if (d < 0)
00802 d += 7;
00803 if (w < 0) {
00804 int rjd2;
00805
00806 c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
00807 c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
00808 if (ry2 != y)
00809 return 0;
00810 w = rw2;
00811 }
00812 c_weeknum_to_jd(y, w, d, f, sg, rjd, ns);
00813 c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
00814 if (y != ry2 || w != *rw || d != *rd)
00815 return 0;
00816 return 1;
00817 }
00818
00819 #ifndef NDEBUG
00820 static int
00821 c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
00822 int *rm, int *rn, int *rk, int *rjd, int *ns)
00823 {
00824 int ns2, ry2, rm2, rn2, rk2;
00825
00826 if (k < 0)
00827 k += 7;
00828 if (n < 0) {
00829 int t, ny, nm, rjd2;
00830
00831 t = y * 12 + m;
00832 ny = DIV(t, 12);
00833 nm = MOD(t, 12) + 1;
00834
00835 c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
00836 c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
00837 if (ry2 != y || rm2 != m)
00838 return 0;
00839 n = rn2;
00840 }
00841 c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
00842 c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk);
00843 if (y != ry2 || m != *rm || n != *rn || k != *rk)
00844 return 0;
00845 return 1;
00846 }
00847 #endif
00848
00849 static int
00850 c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
00851 {
00852 if (h < 0)
00853 h += 24;
00854 if (min < 0)
00855 min += 60;
00856 if (s < 0)
00857 s += 60;
00858 *rh = h;
00859 *rmin = min;
00860 *rs = s;
00861 return !(h < 0 || h > 24 ||
00862 min < 0 || min > 59 ||
00863 s < 0 || s > 59 ||
00864 (h == 24 && (min > 0 || s > 0)));
00865 }
00866
00867 inline static int
00868 c_valid_start_p(double sg)
00869 {
00870 if (isnan(sg))
00871 return 0;
00872 if (isinf(sg))
00873 return 1;
00874 if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD)
00875 return 0;
00876 return 1;
00877 }
00878
00879 inline static int
00880 df_local_to_utc(int df, int of)
00881 {
00882 df -= of;
00883 if (df < 0)
00884 df += DAY_IN_SECONDS;
00885 else if (df >= DAY_IN_SECONDS)
00886 df -= DAY_IN_SECONDS;
00887 return df;
00888 }
00889
00890 inline static int
00891 df_utc_to_local(int df, int of)
00892 {
00893 df += of;
00894 if (df < 0)
00895 df += DAY_IN_SECONDS;
00896 else if (df >= DAY_IN_SECONDS)
00897 df -= DAY_IN_SECONDS;
00898 return df;
00899 }
00900
00901 inline static int
00902 jd_local_to_utc(int jd, int df, int of)
00903 {
00904 df -= of;
00905 if (df < 0)
00906 jd -= 1;
00907 else if (df >= DAY_IN_SECONDS)
00908 jd += 1;
00909 return jd;
00910 }
00911
00912 inline static int
00913 jd_utc_to_local(int jd, int df, int of)
00914 {
00915 df += of;
00916 if (df < 0)
00917 jd -= 1;
00918 else if (df >= DAY_IN_SECONDS)
00919 jd += 1;
00920 return jd;
00921 }
00922
00923 inline static int
00924 time_to_df(int h, int min, int s)
00925 {
00926 return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
00927 }
00928
00929 inline static void
00930 df_to_time(int df, int *h, int *min, int *s)
00931 {
00932 *h = df / HOUR_IN_SECONDS;
00933 df %= HOUR_IN_SECONDS;
00934 *min = df / MINUTE_IN_SECONDS;
00935 *s = df % MINUTE_IN_SECONDS;
00936 }
00937
00938 static VALUE
00939 sec_to_day(VALUE s)
00940 {
00941 if (FIXNUM_P(s))
00942 return rb_rational_new2(s, INT2FIX(DAY_IN_SECONDS));
00943 return f_quo(s, INT2FIX(DAY_IN_SECONDS));
00944 }
00945
00946 inline static VALUE
00947 isec_to_day(int s)
00948 {
00949 return sec_to_day(INT2FIX(s));
00950 }
00951
00952 static VALUE
00953 ns_to_day(VALUE n)
00954 {
00955 if (FIXNUM_P(n))
00956 return rb_rational_new2(n, day_in_nanoseconds);
00957 return f_quo(n, day_in_nanoseconds);
00958 }
00959
00960 #ifndef NDEBUG
00961 static VALUE
00962 ms_to_sec(VALUE m)
00963 {
00964 if (FIXNUM_P(m))
00965 return rb_rational_new2(m, INT2FIX(SECOND_IN_MILLISECONDS));
00966 return f_quo(m, INT2FIX(SECOND_IN_MILLISECONDS));
00967 }
00968 #endif
00969
00970 static VALUE
00971 ns_to_sec(VALUE n)
00972 {
00973 if (FIXNUM_P(n))
00974 return rb_rational_new2(n, INT2FIX(SECOND_IN_NANOSECONDS));
00975 return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS));
00976 }
00977
00978 #ifndef NDEBUG
00979 inline static VALUE
00980 ins_to_day(int n)
00981 {
00982 return ns_to_day(INT2FIX(n));
00983 }
00984 #endif
00985
00986 static int
00987 safe_mul_p(VALUE x, long m)
00988 {
00989 long ix;
00990
00991 if (!FIXNUM_P(x))
00992 return 0;
00993 ix = FIX2LONG(x);
00994 if (ix >= (FIXNUM_MAX / m))
00995 return 0;
00996 return 1;
00997 }
00998
00999 static VALUE
01000 day_to_sec(VALUE d)
01001 {
01002 if (safe_mul_p(d, DAY_IN_SECONDS))
01003 return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS);
01004 return f_mul(d, INT2FIX(DAY_IN_SECONDS));
01005 }
01006
01007 #ifndef NDEBUG
01008 static VALUE
01009 day_to_ns(VALUE d)
01010 {
01011 return f_mul(d, day_in_nanoseconds);
01012 }
01013 #endif
01014
01015 static VALUE
01016 sec_to_ms(VALUE s)
01017 {
01018 if (safe_mul_p(s, SECOND_IN_MILLISECONDS))
01019 return LONG2FIX(FIX2LONG(s) * SECOND_IN_MILLISECONDS);
01020 return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS));
01021 }
01022
01023 static VALUE
01024 sec_to_ns(VALUE s)
01025 {
01026 if (safe_mul_p(s, SECOND_IN_NANOSECONDS))
01027 return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS);
01028 return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS));
01029 }
01030
01031 #ifndef NDEBUG
01032 static VALUE
01033 isec_to_ns(int s)
01034 {
01035 return sec_to_ns(INT2FIX(s));
01036 }
01037 #endif
01038
01039 static VALUE
01040 div_day(VALUE d, VALUE *f)
01041 {
01042 if (f)
01043 *f = f_mod(d, INT2FIX(1));
01044 return f_floor(d);
01045 }
01046
01047 static VALUE
01048 div_df(VALUE d, VALUE *f)
01049 {
01050 VALUE s = day_to_sec(d);
01051
01052 if (f)
01053 *f = f_mod(s, INT2FIX(1));
01054 return f_floor(s);
01055 }
01056
01057 #ifndef NDEBUG
01058 static VALUE
01059 div_sf(VALUE s, VALUE *f)
01060 {
01061 VALUE n = sec_to_ns(s);
01062
01063 if (f)
01064 *f = f_mod(n, INT2FIX(1));
01065 return f_floor(n);
01066 }
01067 #endif
01068
01069 static void
01070 decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf)
01071 {
01072 VALUE f;
01073
01074 *jd = div_day(d, &f);
01075 *df = div_df(f, &f);
01076 *sf = sec_to_ns(f);
01077 }
01078
01079 inline static double
01080 s_virtual_sg(union DateData *x)
01081 {
01082 if (isinf(x->s.sg))
01083 return x->s.sg;
01084 if (f_zero_p(x->s.nth))
01085 return x->s.sg;
01086 else if (f_negative_p(x->s.nth))
01087 return positive_inf;
01088 return negative_inf;
01089 }
01090
01091 inline static double
01092 c_virtual_sg(union DateData *x)
01093 {
01094 if (isinf(x->c.sg))
01095 return x->c.sg;
01096 if (f_zero_p(x->c.nth))
01097 return x->c.sg;
01098 else if (f_negative_p(x->c.nth))
01099 return positive_inf;
01100 return negative_inf;
01101 }
01102
01103 inline static double
01104 m_virtual_sg(union DateData *x)
01105 {
01106 if (simple_dat_p(x))
01107 return s_virtual_sg(x);
01108 else
01109 return c_virtual_sg(x);
01110 }
01111
01112 inline static void
01113 get_s_jd(union DateData *x)
01114 {
01115 assert(simple_dat_p(x));
01116 if (!have_jd_p(x)) {
01117 int jd, ns;
01118
01119 assert(have_civil_p(x));
01120 #ifndef USE_PACK
01121 c_civil_to_jd(x->s.year, x->s.mon, x->s.mday,
01122 s_virtual_sg(x), &jd, &ns);
01123 #else
01124 c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc),
01125 s_virtual_sg(x), &jd, &ns);
01126 #endif
01127 x->s.jd = jd;
01128 x->s.flags |= HAVE_JD;
01129 }
01130 }
01131
01132 inline static void
01133 get_s_civil(union DateData *x)
01134 {
01135 assert(simple_dat_p(x));
01136 if (!have_civil_p(x)) {
01137 int y, m, d;
01138
01139 assert(have_jd_p(x));
01140 c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d);
01141 x->s.year = y;
01142 #ifndef USE_PACK
01143 x->s.mon = m;
01144 x->s.mday = d;
01145 #else
01146 x->s.pc = PACK2(m, d);
01147 #endif
01148 x->s.flags |= HAVE_CIVIL;
01149 }
01150 }
01151
01152 inline static void
01153 get_c_df(union DateData *x)
01154 {
01155 assert(complex_dat_p(x));
01156 if (!have_df_p(x)) {
01157 assert(have_time_p(x));
01158 #ifndef USE_PACK
01159 x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec),
01160 x->c.of);
01161 #else
01162 x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc),
01163 EX_MIN(x->c.pc),
01164 EX_SEC(x->c.pc)),
01165 x->c.of);
01166 #endif
01167 x->c.flags |= HAVE_DF;
01168 }
01169 }
01170
01171 inline static void
01172 get_c_time(union DateData *x)
01173 {
01174 assert(complex_dat_p(x));
01175 if (!have_time_p(x)) {
01176 #ifndef USE_PACK
01177 int r;
01178 assert(have_df_p(x));
01179 r = df_utc_to_local(x->c.df, x->c.of);
01180 df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec);
01181 x->c.flags |= HAVE_TIME;
01182 #else
01183 int r, m, d, h, min, s;
01184
01185 assert(have_df_p(x));
01186 m = EX_MON(x->c.pc);
01187 d = EX_MDAY(x->c.pc);
01188 r = df_utc_to_local(x->c.df, x->c.of);
01189 df_to_time(r, &h, &min, &s);
01190 x->c.pc = PACK5(m, d, h, min, s);
01191 x->c.flags |= HAVE_TIME;
01192 #endif
01193 }
01194 }
01195
01196 inline static void
01197 get_c_jd(union DateData *x)
01198 {
01199 assert(complex_dat_p(x));
01200 if (!have_jd_p(x)) {
01201 int jd, ns;
01202
01203 assert(have_civil_p(x));
01204 #ifndef USE_PACK
01205 c_civil_to_jd(x->c.year, x->c.mon, x->c.mday,
01206 c_virtual_sg(x), &jd, &ns);
01207 #else
01208 c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc),
01209 c_virtual_sg(x), &jd, &ns);
01210 #endif
01211
01212 get_c_time(x);
01213 #ifndef USE_PACK
01214 x->c.jd = jd_local_to_utc(jd,
01215 time_to_df(x->c.hour, x->c.min, x->c.sec),
01216 x->c.of);
01217 #else
01218 x->c.jd = jd_local_to_utc(jd,
01219 time_to_df(EX_HOUR(x->c.pc),
01220 EX_MIN(x->c.pc),
01221 EX_SEC(x->c.pc)),
01222 x->c.of);
01223 #endif
01224 x->c.flags |= HAVE_JD;
01225 }
01226 }
01227
01228 inline static void
01229 get_c_civil(union DateData *x)
01230 {
01231 assert(complex_dat_p(x));
01232 if (!have_civil_p(x)) {
01233 #ifndef USE_PACK
01234 int jd, y, m, d;
01235 #else
01236 int jd, y, m, d, h, min, s;
01237 #endif
01238
01239 assert(have_jd_p(x));
01240 get_c_df(x);
01241 jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
01242 c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d);
01243 x->c.year = y;
01244 #ifndef USE_PACK
01245 x->c.mon = m;
01246 x->c.mday = d;
01247 #else
01248 h = EX_HOUR(x->c.pc);
01249 min = EX_MIN(x->c.pc);
01250 s = EX_SEC(x->c.pc);
01251 x->c.pc = PACK5(m, d, h, min, s);
01252 #endif
01253 x->c.flags |= HAVE_CIVIL;
01254 }
01255 }
01256
01257 inline static int
01258 local_jd(union DateData *x)
01259 {
01260 assert(complex_dat_p(x));
01261 assert(have_jd_p(x));
01262 assert(have_df_p(x));
01263 return jd_utc_to_local(x->c.jd, x->c.df, x->c.of);
01264 }
01265
01266 inline static int
01267 local_df(union DateData *x)
01268 {
01269 assert(complex_dat_p(x));
01270 assert(have_df_p(x));
01271 return df_utc_to_local(x->c.df, x->c.of);
01272 }
01273
01274 static void
01275 decode_year(VALUE y, double style,
01276 VALUE *nth, int *ry)
01277 {
01278 int period;
01279 VALUE t;
01280
01281 period = (style < 0) ?
01282 CM_PERIOD_GCY :
01283 CM_PERIOD_JCY;
01284 if (FIXNUM_P(y)) {
01285 long iy, it, inth;
01286
01287 iy = FIX2LONG(y);
01288 if (iy >= (FIXNUM_MAX - 4712))
01289 goto big;
01290 it = iy + 4712;
01291 inth = DIV(it, ((long)period));
01292 *nth = LONG2FIX(inth);
01293 if (inth)
01294 it = MOD(it, ((long)period));
01295 *ry = (int)it - 4712;
01296 return;
01297 }
01298 big:
01299 t = f_add(y, INT2FIX(4712));
01300 *nth = f_idiv(t, INT2FIX(period));
01301 if (f_nonzero_p(*nth))
01302 t = f_mod(t, INT2FIX(period));
01303 *ry = FIX2INT(t) - 4712;
01304 }
01305
01306 static void
01307 encode_year(VALUE nth, int y, double style,
01308 VALUE *ry)
01309 {
01310 int period;
01311 VALUE t;
01312
01313 period = (style < 0) ?
01314 CM_PERIOD_GCY :
01315 CM_PERIOD_JCY;
01316 if (f_zero_p(nth))
01317 *ry = INT2FIX(y);
01318 else {
01319 t = f_mul(INT2FIX(period), nth);
01320 t = f_add(t, INT2FIX(y));
01321 *ry = t;
01322 }
01323 }
01324
01325 static void
01326 decode_jd(VALUE jd, VALUE *nth, int *rjd)
01327 {
01328 assert(FIXNUM_P(jd) || RB_TYPE_P(jd, T_BIGNUM));
01329 *nth = f_idiv(jd, INT2FIX(CM_PERIOD));
01330 if (f_zero_p(*nth)) {
01331 assert(FIXNUM_P(jd));
01332 *rjd = FIX2INT(jd);
01333 return;
01334 }
01335 *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD)));
01336 }
01337
01338 static void
01339 encode_jd(VALUE nth, int jd, VALUE *rjd)
01340 {
01341 if (f_zero_p(nth)) {
01342 *rjd = INT2FIX(jd);
01343 return;
01344 }
01345 *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd));
01346 }
01347
01348 inline static double
01349 guess_style(VALUE y, double sg)
01350 {
01351 double style = 0;
01352
01353 if (isinf(sg))
01354 style = sg;
01355 else if (!FIXNUM_P(y))
01356 style = f_positive_p(y) ? negative_inf : positive_inf;
01357 else {
01358 long iy = FIX2LONG(y);
01359
01360 assert(FIXNUM_P(y));
01361 if (iy < REFORM_BEGIN_YEAR)
01362 style = positive_inf;
01363 else if (iy > REFORM_END_YEAR)
01364 style = negative_inf;
01365 }
01366 return style;
01367 }
01368
01369 inline static VALUE
01370 m_nth(union DateData *x)
01371 {
01372 if (simple_dat_p(x))
01373 return x->s.nth;
01374 else {
01375 get_c_civil(x);
01376 return x->c.nth;
01377 }
01378 }
01379
01380 inline static int
01381 m_jd(union DateData *x)
01382 {
01383 if (simple_dat_p(x)) {
01384 get_s_jd(x);
01385 return x->s.jd;
01386 }
01387 else {
01388 get_c_jd(x);
01389 return x->c.jd;
01390 }
01391 }
01392
01393 static VALUE
01394 m_real_jd(union DateData *x)
01395 {
01396 VALUE nth, rjd;
01397 int jd;
01398
01399 nth = m_nth(x);
01400 jd = m_jd(x);
01401
01402 encode_jd(nth, jd, &rjd);
01403 return rjd;
01404 }
01405
01406 static int
01407 m_local_jd(union DateData *x)
01408 {
01409 if (simple_dat_p(x)) {
01410 get_s_jd(x);
01411 return x->s.jd;
01412 }
01413 else {
01414 get_c_jd(x);
01415 get_c_df(x);
01416 return local_jd(x);
01417 }
01418 }
01419
01420 static VALUE
01421 m_real_local_jd(union DateData *x)
01422 {
01423 VALUE nth, rjd;
01424 int jd;
01425
01426 nth = m_nth(x);
01427 jd = m_local_jd(x);
01428
01429 encode_jd(nth, jd, &rjd);
01430 return rjd;
01431 }
01432
01433 inline static int
01434 m_df(union DateData *x)
01435 {
01436 if (simple_dat_p(x))
01437 return 0;
01438 else {
01439 get_c_df(x);
01440 return x->c.df;
01441 }
01442 }
01443
01444 #ifndef NDEBUG
01445 static VALUE
01446 m_df_in_day(union DateData *x)
01447 {
01448 return isec_to_day(m_df(x));
01449 }
01450 #endif
01451
01452 static int
01453 m_local_df(union DateData *x)
01454 {
01455 if (simple_dat_p(x))
01456 return 0;
01457 else {
01458 get_c_df(x);
01459 return local_df(x);
01460 }
01461 }
01462
01463 #ifndef NDEBUG
01464 static VALUE
01465 m_local_df_in_day(union DateData *x)
01466 {
01467 return isec_to_day(m_local_df(x));
01468 }
01469 #endif
01470
01471 inline static VALUE
01472 m_sf(union DateData *x)
01473 {
01474 if (simple_dat_p(x))
01475 return INT2FIX(0);
01476 else
01477 return x->c.sf;
01478 }
01479
01480 #ifndef NDEBUG
01481 static VALUE
01482 m_sf_in_day(union DateData *x)
01483 {
01484 return ns_to_day(m_sf(x));
01485 }
01486 #endif
01487
01488 static VALUE
01489 m_sf_in_sec(union DateData *x)
01490 {
01491 return ns_to_sec(m_sf(x));
01492 }
01493
01494 static VALUE
01495 m_fr(union DateData *x)
01496 {
01497 if (simple_dat_p(x))
01498 return INT2FIX(0);
01499 else {
01500 int df;
01501 VALUE sf, fr;
01502
01503 df = m_local_df(x);
01504 sf = m_sf(x);
01505 fr = isec_to_day(df);
01506 if (f_nonzero_p(sf))
01507 fr = f_add(fr, ns_to_day(sf));
01508 return fr;
01509 }
01510 }
01511
01512 #define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2)
01513
01514 static VALUE
01515 m_ajd(union DateData *x)
01516 {
01517 VALUE r, sf;
01518 int df;
01519
01520 if (simple_dat_p(x)) {
01521 r = m_real_jd(x);
01522 if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
01523 long ir = FIX2LONG(r);
01524 ir = ir * 2 - 1;
01525 return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
01526 }
01527 else
01528 return rb_rational_new2(f_sub(f_mul(r,
01529 INT2FIX(2)),
01530 INT2FIX(1)),
01531 INT2FIX(2));
01532 }
01533
01534 r = m_real_jd(x);
01535 df = m_df(x);
01536 df -= HALF_DAYS_IN_SECONDS;
01537 if (df)
01538 r = f_add(r, isec_to_day(df));
01539 sf = m_sf(x);
01540 if (f_nonzero_p(sf))
01541 r = f_add(r, ns_to_day(sf));
01542
01543 return r;
01544 }
01545
01546 static VALUE
01547 m_amjd(union DateData *x)
01548 {
01549 VALUE r, sf;
01550 int df;
01551
01552 r = m_real_jd(x);
01553 if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) {
01554 long ir = FIX2LONG(r);
01555 ir -= 2400001;
01556 r = rb_rational_new1(LONG2FIX(ir));
01557 }
01558 else
01559 r = rb_rational_new1(f_sub(m_real_jd(x),
01560 INT2FIX(2400001)));
01561
01562 if (simple_dat_p(x))
01563 return r;
01564
01565 df = m_df(x);
01566 if (df)
01567 r = f_add(r, isec_to_day(df));
01568 sf = m_sf(x);
01569 if (f_nonzero_p(sf))
01570 r = f_add(r, ns_to_day(sf));
01571
01572 return r;
01573 }
01574
01575 inline static int
01576 m_of(union DateData *x)
01577 {
01578 if (simple_dat_p(x))
01579 return 0;
01580 else {
01581 get_c_jd(x);
01582 return x->c.of;
01583 }
01584 }
01585
01586 static VALUE
01587 m_of_in_day(union DateData *x)
01588 {
01589 return isec_to_day(m_of(x));
01590 }
01591
01592 inline static double
01593 m_sg(union DateData *x)
01594 {
01595 if (simple_dat_p(x))
01596 return x->s.sg;
01597 else {
01598 get_c_jd(x);
01599 return x->c.sg;
01600 }
01601 }
01602
01603 static int
01604 m_julian_p(union DateData *x)
01605 {
01606 int jd;
01607 double sg;
01608
01609 if (simple_dat_p(x)) {
01610 get_s_jd(x);
01611 jd = x->s.jd;
01612 sg = s_virtual_sg(x);
01613 }
01614 else {
01615 get_c_jd(x);
01616 jd = x->c.jd;
01617 sg = c_virtual_sg(x);
01618 }
01619 if (isinf(sg))
01620 return sg == positive_inf;
01621 return jd < sg;
01622 }
01623
01624 inline static int
01625 m_gregorian_p(union DateData *x)
01626 {
01627 return !m_julian_p(x);
01628 }
01629
01630 inline static int
01631 m_proleptic_julian_p(union DateData *x)
01632 {
01633 double sg;
01634
01635 sg = m_sg(x);
01636 if (isinf(sg) && sg > 0)
01637 return 1;
01638 return 0;
01639 }
01640
01641 inline static int
01642 m_proleptic_gregorian_p(union DateData *x)
01643 {
01644 double sg;
01645
01646 sg = m_sg(x);
01647 if (isinf(sg) && sg < 0)
01648 return 1;
01649 return 0;
01650 }
01651
01652 inline static int
01653 m_year(union DateData *x)
01654 {
01655 if (simple_dat_p(x)) {
01656 get_s_civil(x);
01657 return x->s.year;
01658 }
01659 else {
01660 get_c_civil(x);
01661 return x->c.year;
01662 }
01663 }
01664
01665 static VALUE
01666 m_real_year(union DateData *x)
01667 {
01668 VALUE nth, ry;
01669 int year;
01670
01671 nth = m_nth(x);
01672 year = m_year(x);
01673
01674 if (f_zero_p(nth))
01675 return INT2FIX(year);
01676
01677 encode_year(nth, year,
01678 m_gregorian_p(x) ? -1 : +1,
01679 &ry);
01680 return ry;
01681 }
01682
01683
01684 #ifdef USE_PACK
01685 inline static int
01686 m_pc(union DateData *x)
01687 {
01688 if (simple_dat_p(x)) {
01689 get_s_civil(x);
01690 return x->s.pc;
01691 }
01692 else {
01693 get_c_civil(x);
01694 get_c_time(x);
01695 return x->c.pc;
01696 }
01697 }
01698 #endif
01699
01700 inline static int
01701 m_mon(union DateData *x)
01702 {
01703 if (simple_dat_p(x)) {
01704 get_s_civil(x);
01705 #ifndef USE_PACK
01706 return x->s.mon;
01707 #else
01708 return EX_MON(x->s.pc);
01709 #endif
01710 }
01711 else {
01712 get_c_civil(x);
01713 #ifndef USE_PACK
01714 return x->c.mon;
01715 #else
01716 return EX_MON(x->c.pc);
01717 #endif
01718 }
01719 }
01720
01721 inline static int
01722 m_mday(union DateData *x)
01723 {
01724 if (simple_dat_p(x)) {
01725 get_s_civil(x);
01726 #ifndef USE_PACK
01727 return x->s.mday;
01728 #else
01729 return EX_MDAY(x->s.pc);
01730 #endif
01731 }
01732 else {
01733 get_c_civil(x);
01734 #ifndef USE_PACK
01735 return x->c.mday;
01736 #else
01737 return EX_MDAY(x->c.pc);
01738 #endif
01739 }
01740 }
01741
01742 static const int yeartab[2][13] = {
01743 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
01744 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
01745 };
01746
01747 static int
01748 c_julian_to_yday(int y, int m, int d)
01749 {
01750 assert(m >= 1 && m <= 12);
01751 return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d;
01752 }
01753
01754 static int
01755 c_gregorian_to_yday(int y, int m, int d)
01756 {
01757 assert(m >= 1 && m <= 12);
01758 return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d;
01759 }
01760
01761 static int
01762 m_yday(union DateData *x)
01763 {
01764 int jd, ry, rd;
01765 double sg;
01766
01767 jd = m_local_jd(x);
01768 sg = m_virtual_sg(x);
01769
01770 if (m_proleptic_gregorian_p(x) ||
01771 (jd - sg) > 366)
01772 return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x));
01773 if (m_proleptic_julian_p(x))
01774 return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x));
01775 c_jd_to_ordinal(jd, sg, &ry, &rd);
01776 return rd;
01777 }
01778
01779 static int
01780 m_wday(union DateData *x)
01781 {
01782 return c_jd_to_wday(m_local_jd(x));
01783 }
01784
01785 static int
01786 m_cwyear(union DateData *x)
01787 {
01788 int ry, rw, rd;
01789
01790 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x),
01791 &ry, &rw, &rd);
01792 return ry;
01793 }
01794
01795 static VALUE
01796 m_real_cwyear(union DateData *x)
01797 {
01798 VALUE nth, ry;
01799 int year;
01800
01801 nth = m_nth(x);
01802 year = m_cwyear(x);
01803
01804 if (f_zero_p(nth))
01805 return INT2FIX(year);
01806
01807 encode_year(nth, year,
01808 m_gregorian_p(x) ? -1 : +1,
01809 &ry);
01810 return ry;
01811 }
01812
01813 static int
01814 m_cweek(union DateData *x)
01815 {
01816 int ry, rw, rd;
01817
01818 c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x),
01819 &ry, &rw, &rd);
01820 return rw;
01821 }
01822
01823 static int
01824 m_cwday(union DateData *x)
01825 {
01826 int w;
01827
01828 w = m_wday(x);
01829 if (w == 0)
01830 w = 7;
01831 return w;
01832 }
01833
01834 static int
01835 m_wnumx(union DateData *x, int f)
01836 {
01837 int ry, rw, rd;
01838
01839 c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x),
01840 &ry, &rw, &rd);
01841 return rw;
01842 }
01843
01844 static int
01845 m_wnum0(union DateData *x)
01846 {
01847 return m_wnumx(x, 0);
01848 }
01849
01850 static int
01851 m_wnum1(union DateData *x)
01852 {
01853 return m_wnumx(x, 1);
01854 }
01855
01856 inline static int
01857 m_hour(union DateData *x)
01858 {
01859 if (simple_dat_p(x))
01860 return 0;
01861 else {
01862 get_c_time(x);
01863 #ifndef USE_PACK
01864 return x->c.hour;
01865 #else
01866 return EX_HOUR(x->c.pc);
01867 #endif
01868 }
01869 }
01870
01871 inline static int
01872 m_min(union DateData *x)
01873 {
01874 if (simple_dat_p(x))
01875 return 0;
01876 else {
01877 get_c_time(x);
01878 #ifndef USE_PACK
01879 return x->c.min;
01880 #else
01881 return EX_MIN(x->c.pc);
01882 #endif
01883 }
01884 }
01885
01886 inline static int
01887 m_sec(union DateData *x)
01888 {
01889 if (simple_dat_p(x))
01890 return 0;
01891 else {
01892 get_c_time(x);
01893 #ifndef USE_PACK
01894 return x->c.sec;
01895 #else
01896 return EX_SEC(x->c.pc);
01897 #endif
01898 }
01899 }
01900
01901 #define decode_offset(of,s,h,m)\
01902 {\
01903 int a;\
01904 s = (of < 0) ? '-' : '+';\
01905 a = (of < 0) ? -of : of;\
01906 h = a / HOUR_IN_SECONDS;\
01907 m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
01908 }
01909
01910 static VALUE
01911 of2str(int of)
01912 {
01913 int s, h, m;
01914
01915 decode_offset(of, s, h, m);
01916 return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
01917 }
01918
01919 static VALUE
01920 m_zone(union DateData *x)
01921 {
01922 if (simple_dat_p(x))
01923 return rb_usascii_str_new2("+00:00");
01924 return of2str(m_of(x));
01925 }
01926
01927 inline static VALUE
01928 f_kind_of_p(VALUE x, VALUE c)
01929 {
01930 return rb_obj_is_kind_of(x, c);
01931 }
01932
01933 inline static VALUE
01934 k_date_p(VALUE x)
01935 {
01936 return f_kind_of_p(x, cDate);
01937 }
01938
01939 inline static VALUE
01940 k_datetime_p(VALUE x)
01941 {
01942 return f_kind_of_p(x, cDateTime);
01943 }
01944
01945 inline static VALUE
01946 k_numeric_p(VALUE x)
01947 {
01948 return f_kind_of_p(x, rb_cNumeric);
01949 }
01950
01951 inline static VALUE
01952 k_rational_p(VALUE x)
01953 {
01954 return f_kind_of_p(x, rb_cRational);
01955 }
01956
01957 #ifndef NDEBUG
01958 static void
01959 civil_to_jd(VALUE y, int m, int d, double sg,
01960 VALUE *nth, int *ry,
01961 int *rjd,
01962 int *ns)
01963 {
01964 double style = guess_style(y, sg);
01965
01966 if (style == 0) {
01967 int jd;
01968
01969 c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns);
01970 decode_jd(INT2FIX(jd), nth, rjd);
01971 if (f_zero_p(*nth))
01972 *ry = FIX2INT(y);
01973 else {
01974 VALUE nth2;
01975 decode_year(y, ns ? -1 : +1, &nth2, ry);
01976 }
01977 }
01978 else {
01979 decode_year(y, style, nth, ry);
01980 c_civil_to_jd(*ry, m, d, style, rjd, ns);
01981 }
01982 }
01983
01984 static void
01985 jd_to_civil(VALUE jd, double sg,
01986 VALUE *nth, int *rjd,
01987 int *ry, int *rm, int *rd)
01988 {
01989 decode_jd(jd, nth, rjd);
01990 c_jd_to_civil(*rjd, sg, ry, rm, rd);
01991 }
01992
01993 static void
01994 ordinal_to_jd(VALUE y, int d, double sg,
01995 VALUE *nth, int *ry,
01996 int *rjd,
01997 int *ns)
01998 {
01999 double style = guess_style(y, sg);
02000
02001 if (style == 0) {
02002 int jd;
02003
02004 c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns);
02005 decode_jd(INT2FIX(jd), nth, rjd);
02006 if (f_zero_p(*nth))
02007 *ry = FIX2INT(y);
02008 else {
02009 VALUE nth2;
02010 decode_year(y, ns ? -1 : +1, &nth2, ry);
02011 }
02012 }
02013 else {
02014 decode_year(y, style, nth, ry);
02015 c_ordinal_to_jd(*ry, d, style, rjd, ns);
02016 }
02017 }
02018
02019 static void
02020 jd_to_ordinal(VALUE jd, double sg,
02021 VALUE *nth, int *rjd,
02022 int *ry, int *rd)
02023 {
02024 decode_jd(jd, nth, rjd);
02025 c_jd_to_ordinal(*rjd, sg, ry, rd);
02026 }
02027
02028 static void
02029 commercial_to_jd(VALUE y, int w, int d, double sg,
02030 VALUE *nth, int *ry,
02031 int *rjd,
02032 int *ns)
02033 {
02034 double style = guess_style(y, sg);
02035
02036 if (style == 0) {
02037 int jd;
02038
02039 c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns);
02040 decode_jd(INT2FIX(jd), nth, rjd);
02041 if (f_zero_p(*nth))
02042 *ry = FIX2INT(y);
02043 else {
02044 VALUE nth2;
02045 decode_year(y, ns ? -1 : +1, &nth2, ry);
02046 }
02047 }
02048 else {
02049 decode_year(y, style, nth, ry);
02050 c_commercial_to_jd(*ry, w, d, style, rjd, ns);
02051 }
02052 }
02053
02054 static void
02055 jd_to_commercial(VALUE jd, double sg,
02056 VALUE *nth, int *rjd,
02057 int *ry, int *rw, int *rd)
02058 {
02059 decode_jd(jd, nth, rjd);
02060 c_jd_to_commercial(*rjd, sg, ry, rw, rd);
02061 }
02062
02063 static void
02064 weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
02065 VALUE *nth, int *ry,
02066 int *rjd,
02067 int *ns)
02068 {
02069 double style = guess_style(y, sg);
02070
02071 if (style == 0) {
02072 int jd;
02073
02074 c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns);
02075 decode_jd(INT2FIX(jd), nth, rjd);
02076 if (f_zero_p(*nth))
02077 *ry = FIX2INT(y);
02078 else {
02079 VALUE nth2;
02080 decode_year(y, ns ? -1 : +1, &nth2, ry);
02081 }
02082 }
02083 else {
02084 decode_year(y, style, nth, ry);
02085 c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns);
02086 }
02087 }
02088
02089 static void
02090 jd_to_weeknum(VALUE jd, int f, double sg,
02091 VALUE *nth, int *rjd,
02092 int *ry, int *rw, int *rd)
02093 {
02094 decode_jd(jd, nth, rjd);
02095 c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd);
02096 }
02097
02098 static void
02099 nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
02100 VALUE *nth, int *ry,
02101 int *rjd,
02102 int *ns)
02103 {
02104 double style = guess_style(y, sg);
02105
02106 if (style == 0) {
02107 int jd;
02108
02109 c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns);
02110 decode_jd(INT2FIX(jd), nth, rjd);
02111 if (f_zero_p(*nth))
02112 *ry = FIX2INT(y);
02113 else {
02114 VALUE nth2;
02115 decode_year(y, ns ? -1 : +1, &nth2, ry);
02116 }
02117 }
02118 else {
02119 decode_year(y, style, nth, ry);
02120 c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns);
02121 }
02122 }
02123
02124 static void
02125 jd_to_nth_kday(VALUE jd, double sg,
02126 VALUE *nth, int *rjd,
02127 int *ry, int *rm, int *rn, int *rk)
02128 {
02129 decode_jd(jd, nth, rjd);
02130 c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk);
02131 }
02132 #endif
02133
02134 static int
02135 valid_ordinal_p(VALUE y, int d, double sg,
02136 VALUE *nth, int *ry,
02137 int *rd, int *rjd,
02138 int *ns)
02139 {
02140 double style = guess_style(y, sg);
02141 int r;
02142
02143 if (style == 0) {
02144 int jd;
02145
02146 r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns);
02147 if (!r)
02148 return 0;
02149 decode_jd(INT2FIX(jd), nth, rjd);
02150 if (f_zero_p(*nth))
02151 *ry = FIX2INT(y);
02152 else {
02153 VALUE nth2;
02154 decode_year(y, ns ? -1 : +1, &nth2, ry);
02155 }
02156 }
02157 else {
02158 decode_year(y, style, nth, ry);
02159 r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns);
02160 }
02161 return r;
02162 }
02163
02164 static int
02165 valid_gregorian_p(VALUE y, int m, int d,
02166 VALUE *nth, int *ry,
02167 int *rm, int *rd)
02168 {
02169 decode_year(y, -1, nth, ry);
02170 return c_valid_gregorian_p(*ry, m, d, rm, rd);
02171 }
02172
02173 static int
02174 valid_civil_p(VALUE y, int m, int d, double sg,
02175 VALUE *nth, int *ry,
02176 int *rm, int *rd, int *rjd,
02177 int *ns)
02178 {
02179 double style = guess_style(y, sg);
02180 int r;
02181
02182 if (style == 0) {
02183 int jd;
02184
02185 r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns);
02186 if (!r)
02187 return 0;
02188 decode_jd(INT2FIX(jd), nth, rjd);
02189 if (f_zero_p(*nth))
02190 *ry = FIX2INT(y);
02191 else {
02192 VALUE nth2;
02193 decode_year(y, ns ? -1 : +1, &nth2, ry);
02194 }
02195 }
02196 else {
02197 decode_year(y, style, nth, ry);
02198 if (style < 0)
02199 r = c_valid_gregorian_p(*ry, m, d, rm, rd);
02200 else
02201 r = c_valid_julian_p(*ry, m, d, rm, rd);
02202 if (!r)
02203 return 0;
02204 c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns);
02205 }
02206 return r;
02207 }
02208
02209 static int
02210 valid_commercial_p(VALUE y, int w, int d, double sg,
02211 VALUE *nth, int *ry,
02212 int *rw, int *rd, int *rjd,
02213 int *ns)
02214 {
02215 double style = guess_style(y, sg);
02216 int r;
02217
02218 if (style == 0) {
02219 int jd;
02220
02221 r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns);
02222 if (!r)
02223 return 0;
02224 decode_jd(INT2FIX(jd), nth, rjd);
02225 if (f_zero_p(*nth))
02226 *ry = FIX2INT(y);
02227 else {
02228 VALUE nth2;
02229 decode_year(y, ns ? -1 : +1, &nth2, ry);
02230 }
02231 }
02232 else {
02233 decode_year(y, style, nth, ry);
02234 r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns);
02235 }
02236 return r;
02237 }
02238
02239 static int
02240 valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
02241 VALUE *nth, int *ry,
02242 int *rw, int *rd, int *rjd,
02243 int *ns)
02244 {
02245 double style = guess_style(y, sg);
02246 int r;
02247
02248 if (style == 0) {
02249 int jd;
02250
02251 r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns);
02252 if (!r)
02253 return 0;
02254 decode_jd(INT2FIX(jd), nth, rjd);
02255 if (f_zero_p(*nth))
02256 *ry = FIX2INT(y);
02257 else {
02258 VALUE nth2;
02259 decode_year(y, ns ? -1 : +1, &nth2, ry);
02260 }
02261 }
02262 else {
02263 decode_year(y, style, nth, ry);
02264 r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns);
02265 }
02266 return r;
02267 }
02268
02269 #ifndef NDEBUG
02270 static int
02271 valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
02272 VALUE *nth, int *ry,
02273 int *rm, int *rn, int *rk, int *rjd,
02274 int *ns)
02275 {
02276 double style = guess_style(y, sg);
02277 int r;
02278
02279 if (style == 0) {
02280 int jd;
02281
02282 r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns);
02283 if (!r)
02284 return 0;
02285 decode_jd(INT2FIX(jd), nth, rjd);
02286 if (f_zero_p(*nth))
02287 *ry = FIX2INT(y);
02288 else {
02289 VALUE nth2;
02290 decode_year(y, ns ? -1 : +1, &nth2, ry);
02291 }
02292 }
02293 else {
02294 decode_year(y, style, nth, ry);
02295 r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns);
02296 }
02297 return r;
02298 }
02299 #endif
02300
02301 VALUE date_zone_to_diff(VALUE);
02302
02303 static int
02304 offset_to_sec(VALUE vof, int *rof)
02305 {
02306 switch (TYPE(vof)) {
02307 case T_FIXNUM:
02308 {
02309 long n;
02310
02311 n = FIX2LONG(vof);
02312 if (n != -1 && n != 0 && n != 1)
02313 return 0;
02314 *rof = (int)n * DAY_IN_SECONDS;
02315 return 1;
02316 }
02317 case T_FLOAT:
02318 {
02319 double n;
02320
02321 n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS;
02322 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02323 return 0;
02324 *rof = (int)round(n);
02325 if (*rof != n)
02326 rb_warning("fraction of offset is ignored");
02327 return 1;
02328 }
02329 default:
02330 if (!k_numeric_p(vof))
02331 rb_raise(rb_eTypeError, "expected numeric");
02332 vof = f_to_r(vof);
02333 #ifdef CANONICALIZATION_FOR_MATHN
02334 if (!k_rational_p(vof))
02335 return offset_to_sec(vof, rof);
02336 #endif
02337
02338 case T_RATIONAL:
02339 {
02340 VALUE vs, vn, vd;
02341 long n;
02342
02343 vs = day_to_sec(vof);
02344
02345 #ifdef CANONICALIZATION_FOR_MATHN
02346 if (!k_rational_p(vs)) {
02347 if (!FIXNUM_P(vs))
02348 return 0;
02349 n = FIX2LONG(vs);
02350 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02351 return 0;
02352 *rof = (int)n;
02353 return 1;
02354 }
02355 #endif
02356 vn = RRATIONAL(vs)->num;
02357 vd = RRATIONAL(vs)->den;
02358
02359 if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1))
02360 n = FIX2LONG(vn);
02361 else {
02362 vn = f_round(vs);
02363 if (!f_eqeq_p(vn, vs))
02364 rb_warning("fraction of offset is ignored");
02365 if (!FIXNUM_P(vn))
02366 return 0;
02367 n = FIX2LONG(vn);
02368 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02369 return 0;
02370 }
02371 *rof = (int)n;
02372 return 1;
02373 }
02374 case T_STRING:
02375 {
02376 VALUE vs = date_zone_to_diff(vof);
02377 long n;
02378
02379 if (!FIXNUM_P(vs))
02380 return 0;
02381 n = FIX2LONG(vs);
02382 if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
02383 return 0;
02384 *rof = (int)n;
02385 return 1;
02386 }
02387 }
02388 return 0;
02389 }
02390
02391
02392
02393 #define valid_sg(sg) \
02394 {\
02395 if (!c_valid_start_p(sg)) {\
02396 sg = 0;\
02397 rb_warning("invalid start is ignored");\
02398 }\
02399 }
02400
02401 static VALUE
02402 valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02403 {
02404 double sg = NUM2DBL(argv[1]);
02405 valid_sg(sg);
02406 return argv[0];
02407 }
02408
02409 #ifndef NDEBUG
02410 static VALUE
02411 date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
02412 {
02413 VALUE vjd, vsg;
02414 VALUE argv2[2];
02415
02416 rb_scan_args(argc, argv, "11", &vjd, &vsg);
02417
02418 argv2[0] = vjd;
02419 if (argc < 2)
02420 argv2[1] = DBL2NUM(GREGORIAN);
02421 else
02422 argv2[1] = vsg;
02423
02424 return valid_jd_sub(2, argv2, klass, 1);
02425 }
02426 #endif
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440 static VALUE
02441 date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
02442 {
02443 VALUE vjd, vsg;
02444 VALUE argv2[2];
02445
02446 rb_scan_args(argc, argv, "11", &vjd, &vsg);
02447
02448 argv2[0] = vjd;
02449 if (argc < 2)
02450 argv2[1] = INT2FIX(DEFAULT_SG);
02451 else
02452 argv2[1] = vsg;
02453
02454 if (NIL_P(valid_jd_sub(2, argv2, klass, 0)))
02455 return Qfalse;
02456 return Qtrue;
02457 }
02458
02459 static VALUE
02460 valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02461 {
02462 VALUE nth, y;
02463 int m, d, ry, rm, rd;
02464 double sg;
02465
02466 y = argv[0];
02467 m = NUM2INT(argv[1]);
02468 d = NUM2INT(argv[2]);
02469 sg = NUM2DBL(argv[3]);
02470
02471 valid_sg(sg);
02472
02473 if (!need_jd && (guess_style(y, sg) < 0)) {
02474 if (!valid_gregorian_p(y, m, d,
02475 &nth, &ry,
02476 &rm, &rd))
02477 return Qnil;
02478 return INT2FIX(0);
02479 }
02480 else {
02481 int rjd, ns;
02482 VALUE rjd2;
02483
02484 if (!valid_civil_p(y, m, d, sg,
02485 &nth, &ry,
02486 &rm, &rd, &rjd,
02487 &ns))
02488 return Qnil;
02489 if (!need_jd)
02490 return INT2FIX(0);
02491 encode_jd(nth, rjd, &rjd2);
02492 return rjd2;
02493 }
02494 }
02495
02496 #ifndef NDEBUG
02497 static VALUE
02498 date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
02499 {
02500 VALUE vy, vm, vd, vsg;
02501 VALUE argv2[4];
02502
02503 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
02504
02505 argv2[0] = vy;
02506 argv2[1] = vm;
02507 argv2[2] = vd;
02508 if (argc < 4)
02509 argv2[3] = DBL2NUM(GREGORIAN);
02510 else
02511 argv2[3] = vsg;
02512
02513 return valid_civil_sub(4, argv2, klass, 1);
02514 }
02515 #endif
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531 static VALUE
02532 date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
02533 {
02534 VALUE vy, vm, vd, vsg;
02535 VALUE argv2[4];
02536
02537 rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg);
02538
02539 argv2[0] = vy;
02540 argv2[1] = vm;
02541 argv2[2] = vd;
02542 if (argc < 4)
02543 argv2[3] = INT2FIX(DEFAULT_SG);
02544 else
02545 argv2[3] = vsg;
02546
02547 if (NIL_P(valid_civil_sub(4, argv2, klass, 0)))
02548 return Qfalse;
02549 return Qtrue;
02550 }
02551
02552 static VALUE
02553 valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02554 {
02555 VALUE nth, y;
02556 int d, ry, rd;
02557 double sg;
02558
02559 y = argv[0];
02560 d = NUM2INT(argv[1]);
02561 sg = NUM2DBL(argv[2]);
02562
02563 valid_sg(sg);
02564
02565 {
02566 int rjd, ns;
02567 VALUE rjd2;
02568
02569 if (!valid_ordinal_p(y, d, sg,
02570 &nth, &ry,
02571 &rd, &rjd,
02572 &ns))
02573 return Qnil;
02574 if (!need_jd)
02575 return INT2FIX(0);
02576 encode_jd(nth, rjd, &rjd2);
02577 return rjd2;
02578 }
02579 }
02580
02581 #ifndef NDEBUG
02582 static VALUE
02583 date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
02584 {
02585 VALUE vy, vd, vsg;
02586 VALUE argv2[3];
02587
02588 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
02589
02590 argv2[0] = vy;
02591 argv2[1] = vd;
02592 if (argc < 3)
02593 argv2[2] = DBL2NUM(GREGORIAN);
02594 else
02595 argv2[2] = vsg;
02596
02597 return valid_ordinal_sub(3, argv2, klass, 1);
02598 }
02599 #endif
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614 static VALUE
02615 date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
02616 {
02617 VALUE vy, vd, vsg;
02618 VALUE argv2[3];
02619
02620 rb_scan_args(argc, argv, "21", &vy, &vd, &vsg);
02621
02622 argv2[0] = vy;
02623 argv2[1] = vd;
02624 if (argc < 3)
02625 argv2[2] = INT2FIX(DEFAULT_SG);
02626 else
02627 argv2[2] = vsg;
02628
02629 if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0)))
02630 return Qfalse;
02631 return Qtrue;
02632 }
02633
02634 static VALUE
02635 valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02636 {
02637 VALUE nth, y;
02638 int w, d, ry, rw, rd;
02639 double sg;
02640
02641 y = argv[0];
02642 w = NUM2INT(argv[1]);
02643 d = NUM2INT(argv[2]);
02644 sg = NUM2DBL(argv[3]);
02645
02646 valid_sg(sg);
02647
02648 {
02649 int rjd, ns;
02650 VALUE rjd2;
02651
02652 if (!valid_commercial_p(y, w, d, sg,
02653 &nth, &ry,
02654 &rw, &rd, &rjd,
02655 &ns))
02656 return Qnil;
02657 if (!need_jd)
02658 return INT2FIX(0);
02659 encode_jd(nth, rjd, &rjd2);
02660 return rjd2;
02661 }
02662 }
02663
02664 #ifndef NDEBUG
02665 static VALUE
02666 date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
02667 {
02668 VALUE vy, vw, vd, vsg;
02669 VALUE argv2[4];
02670
02671 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
02672
02673 argv2[0] = vy;
02674 argv2[1] = vw;
02675 argv2[2] = vd;
02676 if (argc < 4)
02677 argv2[3] = DBL2NUM(GREGORIAN);
02678 else
02679 argv2[3] = vsg;
02680
02681 return valid_commercial_sub(4, argv2, klass, 1);
02682 }
02683 #endif
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698 static VALUE
02699 date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
02700 {
02701 VALUE vy, vw, vd, vsg;
02702 VALUE argv2[4];
02703
02704 rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg);
02705
02706 argv2[0] = vy;
02707 argv2[1] = vw;
02708 argv2[2] = vd;
02709 if (argc < 4)
02710 argv2[3] = INT2FIX(DEFAULT_SG);
02711 else
02712 argv2[3] = vsg;
02713
02714 if (NIL_P(valid_commercial_sub(4, argv2, klass, 0)))
02715 return Qfalse;
02716 return Qtrue;
02717 }
02718
02719 #ifndef NDEBUG
02720 static VALUE
02721 valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02722 {
02723 VALUE nth, y;
02724 int w, d, f, ry, rw, rd;
02725 double sg;
02726
02727 y = argv[0];
02728 w = NUM2INT(argv[1]);
02729 d = NUM2INT(argv[2]);
02730 f = NUM2INT(argv[3]);
02731 sg = NUM2DBL(argv[4]);
02732
02733 valid_sg(sg);
02734
02735 {
02736 int rjd, ns;
02737 VALUE rjd2;
02738
02739 if (!valid_weeknum_p(y, w, d, f, sg,
02740 &nth, &ry,
02741 &rw, &rd, &rjd,
02742 &ns))
02743 return Qnil;
02744 if (!need_jd)
02745 return INT2FIX(0);
02746 encode_jd(nth, rjd, &rjd2);
02747 return rjd2;
02748 }
02749 }
02750
02751 static VALUE
02752 date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
02753 {
02754 VALUE vy, vw, vd, vf, vsg;
02755 VALUE argv2[5];
02756
02757 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
02758
02759 argv2[0] = vy;
02760 argv2[1] = vw;
02761 argv2[2] = vd;
02762 argv2[3] = vf;
02763 if (argc < 5)
02764 argv2[4] = DBL2NUM(GREGORIAN);
02765 else
02766 argv2[4] = vsg;
02767
02768 return valid_weeknum_sub(5, argv2, klass, 1);
02769 }
02770
02771 static VALUE
02772 date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
02773 {
02774 VALUE vy, vw, vd, vf, vsg;
02775 VALUE argv2[5];
02776
02777 rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg);
02778
02779 argv2[0] = vy;
02780 argv2[1] = vw;
02781 argv2[2] = vd;
02782 argv2[3] = vf;
02783 if (argc < 5)
02784 argv2[4] = INT2FIX(DEFAULT_SG);
02785 else
02786 argv2[4] = vsg;
02787
02788 if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0)))
02789 return Qfalse;
02790 return Qtrue;
02791 }
02792
02793 static VALUE
02794 valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
02795 {
02796 VALUE nth, y;
02797 int m, n, k, ry, rm, rn, rk;
02798 double sg;
02799
02800 y = argv[0];
02801 m = NUM2INT(argv[1]);
02802 n = NUM2INT(argv[2]);
02803 k = NUM2INT(argv[3]);
02804 sg = NUM2DBL(argv[4]);
02805
02806 {
02807 int rjd, ns;
02808 VALUE rjd2;
02809
02810 if (!valid_nth_kday_p(y, m, n, k, sg,
02811 &nth, &ry,
02812 &rm, &rn, &rk, &rjd,
02813 &ns))
02814 return Qnil;
02815 if (!need_jd)
02816 return INT2FIX(0);
02817 encode_jd(nth, rjd, &rjd2);
02818 return rjd2;
02819 }
02820 }
02821
02822 static VALUE
02823 date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
02824 {
02825 VALUE vy, vm, vn, vk, vsg;
02826 VALUE argv2[5];
02827
02828 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
02829
02830 argv2[0] = vy;
02831 argv2[1] = vm;
02832 argv2[2] = vn;
02833 argv2[3] = vk;
02834 if (argc < 5)
02835 argv2[4] = DBL2NUM(GREGORIAN);
02836 else
02837 argv2[4] = vsg;
02838
02839 return valid_nth_kday_sub(5, argv2, klass, 1);
02840 }
02841
02842 static VALUE
02843 date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
02844 {
02845 VALUE vy, vm, vn, vk, vsg;
02846 VALUE argv2[5];
02847
02848 rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg);
02849
02850 argv2[0] = vy;
02851 argv2[1] = vm;
02852 argv2[2] = vn;
02853 argv2[3] = vk;
02854 if (argc < 5)
02855 argv2[4] = INT2FIX(DEFAULT_SG);
02856 else
02857 argv2[4] = vsg;
02858
02859 if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0)))
02860 return Qfalse;
02861 return Qtrue;
02862 }
02863
02864 static VALUE
02865 date_s_zone_to_diff(VALUE klass, VALUE str)
02866 {
02867 return date_zone_to_diff(str);
02868 }
02869 #endif
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883 static VALUE
02884 date_s_julian_leap_p(VALUE klass, VALUE y)
02885 {
02886 VALUE nth;
02887 int ry;
02888
02889 decode_year(y, +1, &nth, &ry);
02890 return f_boolcast(c_julian_leap_p(ry));
02891 }
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906 static VALUE
02907 date_s_gregorian_leap_p(VALUE klass, VALUE y)
02908 {
02909 VALUE nth;
02910 int ry;
02911
02912 decode_year(y, -1, &nth, &ry);
02913 return f_boolcast(c_gregorian_leap_p(ry));
02914 }
02915
02916 static void
02917 d_lite_gc_mark(union DateData *dat)
02918 {
02919 if (simple_dat_p(dat))
02920 rb_gc_mark(dat->s.nth);
02921 else {
02922 rb_gc_mark(dat->c.nth);
02923 rb_gc_mark(dat->c.sf);
02924
02925 }
02926 }
02927
02928 inline static VALUE
02929 d_simple_new_internal(VALUE klass,
02930 VALUE nth, int jd,
02931 double sg,
02932 int y, int m, int d,
02933 unsigned flags)
02934 {
02935 struct SimpleDateData *dat;
02936 VALUE obj;
02937
02938 obj = Data_Make_Struct(klass, struct SimpleDateData,
02939 d_lite_gc_mark, -1, dat);
02940 set_to_simple(dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT);
02941
02942 assert(have_jd_p(dat) || have_civil_p(dat));
02943
02944 return obj;
02945 }
02946
02947 inline static VALUE
02948 d_complex_new_internal(VALUE klass,
02949 VALUE nth, int jd,
02950 int df, VALUE sf,
02951 int of, double sg,
02952 int y, int m, int d,
02953 int h, int min, int s,
02954 unsigned flags)
02955 {
02956 struct ComplexDateData *dat;
02957 VALUE obj;
02958
02959 obj = Data_Make_Struct(klass, struct ComplexDateData,
02960 d_lite_gc_mark, -1, dat);
02961 set_to_complex(dat, nth, jd, df, sf, of, sg,
02962 y, m, d, h, min, s, flags | COMPLEX_DAT);
02963
02964 assert(have_jd_p(dat) || have_civil_p(dat));
02965 assert(have_df_p(dat) || have_time_p(dat));
02966
02967 return obj;
02968 }
02969
02970 static VALUE
02971 d_lite_s_alloc_simple(VALUE klass)
02972 {
02973 return d_simple_new_internal(klass,
02974 INT2FIX(0), 0,
02975 DEFAULT_SG,
02976 0, 0, 0,
02977 HAVE_JD);
02978 }
02979
02980 static VALUE
02981 d_lite_s_alloc_complex(VALUE klass)
02982 {
02983 return d_complex_new_internal(klass,
02984 INT2FIX(0), 0,
02985 0, INT2FIX(0),
02986 0, DEFAULT_SG,
02987 0, 0, 0,
02988 0, 0, 0,
02989 HAVE_JD | HAVE_DF);
02990 }
02991
02992 static VALUE
02993 d_lite_s_alloc(VALUE klass)
02994 {
02995 return d_lite_s_alloc_complex(klass);
02996 }
02997
02998 static void
02999 old_to_new(VALUE ajd, VALUE of, VALUE sg,
03000 VALUE *rnth, int *rjd, int *rdf, VALUE *rsf,
03001 int *rof, double *rsg)
03002 {
03003 VALUE jd, df, sf, of2, t;
03004
03005 decode_day(f_add(ajd, half_days_in_day),
03006 &jd, &df, &sf);
03007 t = day_to_sec(of);
03008 of2 = f_round(t);
03009
03010 if (!f_eqeq_p(of2, t))
03011 rb_warning("fraction of offset is ignored");
03012
03013 decode_jd(jd, rnth, rjd);
03014
03015 *rdf = NUM2INT(df);
03016 *rsf = sf;
03017 *rof = NUM2INT(of2);
03018 *rsg = NUM2DBL(sg);
03019
03020 if (*rdf < 0 || *rdf >= DAY_IN_SECONDS)
03021 rb_raise(rb_eArgError, "invalid day fraction");
03022
03023 if (f_lt_p(*rsf, INT2FIX(0)) ||
03024 f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS)))
03025
03026 if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) {
03027 *rof = 0;
03028 rb_warning("invalid offset is ignored");
03029 }
03030
03031 if (!c_valid_start_p(*rsg)) {
03032 *rsg = DEFAULT_SG;
03033 rb_warning("invalid start is ignored");
03034 }
03035 }
03036
03037 #ifndef NDEBUG
03038 static VALUE
03039 date_s_new_bang(int argc, VALUE *argv, VALUE klass)
03040 {
03041 VALUE ajd, of, sg, nth, sf;
03042 int jd, df, rof;
03043 double rsg;
03044
03045 rb_scan_args(argc, argv, "03", &ajd, &of, &sg);
03046
03047 switch (argc) {
03048 case 0:
03049 ajd = INT2FIX(0);
03050 case 1:
03051 of = INT2FIX(0);
03052 case 2:
03053 sg = INT2FIX(DEFAULT_SG);
03054 }
03055
03056 old_to_new(ajd, of, sg,
03057 &nth, &jd, &df, &sf, &rof, &rsg);
03058
03059 if (!df && f_zero_p(sf) && !rof)
03060 return d_simple_new_internal(klass,
03061 nth, jd,
03062 rsg,
03063 0, 0, 0,
03064 HAVE_JD);
03065 else
03066 return d_complex_new_internal(klass,
03067 nth, jd,
03068 df, sf,
03069 rof, rsg,
03070 0, 0, 0,
03071 0, 0, 0,
03072 HAVE_JD | HAVE_DF);
03073 }
03074 #endif
03075
03076 inline static int
03077 wholenum_p(VALUE x)
03078 {
03079 if (FIXNUM_P(x))
03080 return 1;
03081 switch (TYPE(x)) {
03082 case T_BIGNUM:
03083 return 1;
03084 case T_FLOAT:
03085 {
03086 double d = RFLOAT_VALUE(x);
03087 return round(d) == d;
03088 }
03089 break;
03090 case T_RATIONAL:
03091 {
03092 VALUE den = RRATIONAL(x)->den;
03093 return FIXNUM_P(den) && FIX2LONG(den) == 1;
03094 }
03095 break;
03096 }
03097 return 0;
03098 }
03099
03100 inline static VALUE
03101 to_integer(VALUE x)
03102 {
03103 if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
03104 return x;
03105 return f_to_i(x);
03106 }
03107
03108 inline static VALUE
03109 d_trunc(VALUE d, VALUE *fr)
03110 {
03111 VALUE rd;
03112
03113 if (wholenum_p(d)) {
03114 rd = to_integer(d);
03115 *fr = INT2FIX(0);
03116 }
03117 else {
03118 rd = f_idiv(d, INT2FIX(1));
03119 *fr = f_mod(d, INT2FIX(1));
03120 }
03121 return rd;
03122 }
03123
03124 #define jd_trunc d_trunc
03125 #define k_trunc d_trunc
03126
03127 inline static VALUE
03128 h_trunc(VALUE h, VALUE *fr)
03129 {
03130 VALUE rh;
03131
03132 if (wholenum_p(h)) {
03133 rh = to_integer(h);
03134 *fr = INT2FIX(0);
03135 }
03136 else {
03137 rh = f_idiv(h, INT2FIX(1));
03138 *fr = f_mod(h, INT2FIX(1));
03139 *fr = f_quo(*fr, INT2FIX(24));
03140 }
03141 return rh;
03142 }
03143
03144 inline static VALUE
03145 min_trunc(VALUE min, VALUE *fr)
03146 {
03147 VALUE rmin;
03148
03149 if (wholenum_p(min)) {
03150 rmin = to_integer(min);
03151 *fr = INT2FIX(0);
03152 }
03153 else {
03154 rmin = f_idiv(min, INT2FIX(1));
03155 *fr = f_mod(min, INT2FIX(1));
03156 *fr = f_quo(*fr, INT2FIX(1440));
03157 }
03158 return rmin;
03159 }
03160
03161 inline static VALUE
03162 s_trunc(VALUE s, VALUE *fr)
03163 {
03164 VALUE rs;
03165
03166 if (wholenum_p(s)) {
03167 rs = to_integer(s);
03168 *fr = INT2FIX(0);
03169 }
03170 else {
03171 rs = f_idiv(s, INT2FIX(1));
03172 *fr = f_mod(s, INT2FIX(1));
03173 *fr = f_quo(*fr, INT2FIX(86400));
03174 }
03175 return rs;
03176 }
03177
03178 #define num2num_with_frac(s,n) \
03179 {\
03180 s = s##_trunc(v##s, &fr);\
03181 if (f_nonzero_p(fr)) {\
03182 if (argc > n)\
03183 rb_raise(rb_eArgError, "invalid fraction");\
03184 fr2 = fr;\
03185 }\
03186 }
03187
03188 #define num2int_with_frac(s,n) \
03189 {\
03190 s = NUM2INT(s##_trunc(v##s, &fr));\
03191 if (f_nonzero_p(fr)) {\
03192 if (argc > n)\
03193 rb_raise(rb_eArgError, "invalid fraction");\
03194 fr2 = fr;\
03195 }\
03196 }
03197
03198 #define canon24oc() \
03199 {\
03200 if (rh == 24) {\
03201 rh = 0;\
03202 fr2 = f_add(fr2, INT2FIX(1));\
03203 }\
03204 }
03205
03206 #define add_frac() \
03207 {\
03208 if (f_nonzero_p(fr2))\
03209 ret = d_lite_plus(ret, fr2);\
03210 }
03211
03212 #define val2sg(vsg,dsg) \
03213 {\
03214 dsg = NUM2DBL(vsg);\
03215 if (!c_valid_start_p(dsg)) {\
03216 dsg = DEFAULT_SG;\
03217 rb_warning("invalid start is ignored");\
03218 }\
03219 }
03220
03221 static VALUE d_lite_plus(VALUE, VALUE);
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238 static VALUE
03239 date_s_jd(int argc, VALUE *argv, VALUE klass)
03240 {
03241 VALUE vjd, vsg, jd, fr, fr2, ret;
03242 double sg;
03243
03244 rb_scan_args(argc, argv, "02", &vjd, &vsg);
03245
03246 jd = INT2FIX(0);
03247 fr2 = INT2FIX(0);
03248 sg = DEFAULT_SG;
03249
03250 switch (argc) {
03251 case 2:
03252 val2sg(vsg, sg);
03253 case 1:
03254 num2num_with_frac(jd, positive_inf);
03255 }
03256
03257 {
03258 VALUE nth;
03259 int rjd;
03260
03261 decode_jd(jd, &nth, &rjd);
03262 ret = d_simple_new_internal(klass,
03263 nth, rjd,
03264 sg,
03265 0, 0, 0,
03266 HAVE_JD);
03267 }
03268 add_frac();
03269 return ret;
03270 }
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290 static VALUE
03291 date_s_ordinal(int argc, VALUE *argv, VALUE klass)
03292 {
03293 VALUE vy, vd, vsg, y, fr, fr2, ret;
03294 int d;
03295 double sg;
03296
03297 rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
03298
03299 y = INT2FIX(-4712);
03300 d = 1;
03301 fr2 = INT2FIX(0);
03302 sg = DEFAULT_SG;
03303
03304 switch (argc) {
03305 case 3:
03306 val2sg(vsg, sg);
03307 case 2:
03308 num2int_with_frac(d, positive_inf);
03309 case 1:
03310 y = vy;
03311 }
03312
03313 {
03314 VALUE nth;
03315 int ry, rd, rjd, ns;
03316
03317 if (!valid_ordinal_p(y, d, sg,
03318 &nth, &ry,
03319 &rd, &rjd,
03320 &ns))
03321 rb_raise(rb_eArgError, "invalid date");
03322
03323 ret = d_simple_new_internal(klass,
03324 nth, rjd,
03325 sg,
03326 0, 0, 0,
03327 HAVE_JD);
03328 }
03329 add_frac();
03330 return ret;
03331 }
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360 static VALUE
03361 date_s_civil(int argc, VALUE *argv, VALUE klass)
03362 {
03363 VALUE vy, vm, vd, vsg, y, fr, fr2, ret;
03364 int m, d;
03365 double sg;
03366
03367 rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
03368
03369 y = INT2FIX(-4712);
03370 m = 1;
03371 d = 1;
03372 fr2 = INT2FIX(0);
03373 sg = DEFAULT_SG;
03374
03375 switch (argc) {
03376 case 4:
03377 val2sg(vsg, sg);
03378 case 3:
03379 num2int_with_frac(d, positive_inf);
03380 case 2:
03381 m = NUM2INT(vm);
03382 case 1:
03383 y = vy;
03384 }
03385
03386 if (guess_style(y, sg) < 0) {
03387 VALUE nth;
03388 int ry, rm, rd;
03389
03390 if (!valid_gregorian_p(y, m, d,
03391 &nth, &ry,
03392 &rm, &rd))
03393 rb_raise(rb_eArgError, "invalid date");
03394
03395 ret = d_simple_new_internal(klass,
03396 nth, 0,
03397 sg,
03398 ry, rm, rd,
03399 HAVE_CIVIL);
03400 }
03401 else {
03402 VALUE nth;
03403 int ry, rm, rd, rjd, ns;
03404
03405 if (!valid_civil_p(y, m, d, sg,
03406 &nth, &ry,
03407 &rm, &rd, &rjd,
03408 &ns))
03409 rb_raise(rb_eArgError, "invalid date");
03410
03411 ret = d_simple_new_internal(klass,
03412 nth, rjd,
03413 sg,
03414 ry, rm, rd,
03415 HAVE_JD | HAVE_CIVIL);
03416 }
03417 add_frac();
03418 return ret;
03419 }
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439 static VALUE
03440 date_s_commercial(int argc, VALUE *argv, VALUE klass)
03441 {
03442 VALUE vy, vw, vd, vsg, y, fr, fr2, ret;
03443 int w, d;
03444 double sg;
03445
03446 rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
03447
03448 y = INT2FIX(-4712);
03449 w = 1;
03450 d = 1;
03451 fr2 = INT2FIX(0);
03452 sg = DEFAULT_SG;
03453
03454 switch (argc) {
03455 case 4:
03456 val2sg(vsg, sg);
03457 case 3:
03458 num2int_with_frac(d, positive_inf);
03459 case 2:
03460 w = NUM2INT(vw);
03461 case 1:
03462 y = vy;
03463 }
03464
03465 {
03466 VALUE nth;
03467 int ry, rw, rd, rjd, ns;
03468
03469 if (!valid_commercial_p(y, w, d, sg,
03470 &nth, &ry,
03471 &rw, &rd, &rjd,
03472 &ns))
03473 rb_raise(rb_eArgError, "invalid date");
03474
03475 ret = d_simple_new_internal(klass,
03476 nth, rjd,
03477 sg,
03478 0, 0, 0,
03479 HAVE_JD);
03480 }
03481 add_frac();
03482 return ret;
03483 }
03484
03485 #ifndef NDEBUG
03486 static VALUE
03487 date_s_weeknum(int argc, VALUE *argv, VALUE klass)
03488 {
03489 VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret;
03490 int w, d, f;
03491 double sg;
03492
03493 rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
03494
03495 y = INT2FIX(-4712);
03496 w = 0;
03497 d = 1;
03498 f = 0;
03499 fr2 = INT2FIX(0);
03500 sg = DEFAULT_SG;
03501
03502 switch (argc) {
03503 case 5:
03504 val2sg(vsg, sg);
03505 case 4:
03506 f = NUM2INT(vf);
03507 case 3:
03508 num2int_with_frac(d, positive_inf);
03509 case 2:
03510 w = NUM2INT(vw);
03511 case 1:
03512 y = vy;
03513 }
03514
03515 {
03516 VALUE nth;
03517 int ry, rw, rd, rjd, ns;
03518
03519 if (!valid_weeknum_p(y, w, d, f, sg,
03520 &nth, &ry,
03521 &rw, &rd, &rjd,
03522 &ns))
03523 rb_raise(rb_eArgError, "invalid date");
03524
03525 ret = d_simple_new_internal(klass,
03526 nth, rjd,
03527 sg,
03528 0, 0, 0,
03529 HAVE_JD);
03530 }
03531 add_frac();
03532 return ret;
03533 }
03534
03535 static VALUE
03536 date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
03537 {
03538 VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret;
03539 int m, n, k;
03540 double sg;
03541
03542 rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
03543
03544 y = INT2FIX(-4712);
03545 m = 1;
03546 n = 1;
03547 k = 1;
03548 fr2 = INT2FIX(0);
03549 sg = DEFAULT_SG;
03550
03551 switch (argc) {
03552 case 5:
03553 val2sg(vsg, sg);
03554 case 4:
03555 num2int_with_frac(k, positive_inf);
03556 case 3:
03557 n = NUM2INT(vn);
03558 case 2:
03559 m = NUM2INT(vm);
03560 case 1:
03561 y = vy;
03562 }
03563
03564 {
03565 VALUE nth;
03566 int ry, rm, rn, rk, rjd, ns;
03567
03568 if (!valid_nth_kday_p(y, m, n, k, sg,
03569 &nth, &ry,
03570 &rm, &rn, &rk, &rjd,
03571 &ns))
03572 rb_raise(rb_eArgError, "invalid date");
03573
03574 ret = d_simple_new_internal(klass,
03575 nth, rjd,
03576 sg,
03577 0, 0, 0,
03578 HAVE_JD);
03579 }
03580 add_frac();
03581 return ret;
03582 }
03583 #endif
03584
03585 #if !defined(HAVE_GMTIME_R)
03586 static struct tm*
03587 gmtime_r(const time_t *t, struct tm *tm)
03588 {
03589 auto struct tm *tmp = gmtime(t);
03590 if (tmp)
03591 *tm = *tmp;
03592 return tmp;
03593 }
03594
03595 static struct tm*
03596 localtime_r(const time_t *t, struct tm *tm)
03597 {
03598 auto struct tm *tmp = localtime(t);
03599 if (tmp)
03600 *tm = *tmp;
03601 return tmp;
03602 }
03603 #endif
03604
03605 static void set_sg(union DateData *, double);
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617 static VALUE
03618 date_s_today(int argc, VALUE *argv, VALUE klass)
03619 {
03620 VALUE vsg, nth, ret;
03621 double sg;
03622 time_t t;
03623 struct tm tm;
03624 int y, ry, m, d;
03625
03626 rb_scan_args(argc, argv, "01", &vsg);
03627
03628 if (argc < 1)
03629 sg = DEFAULT_SG;
03630 else
03631 val2sg(vsg, sg);
03632
03633 if (time(&t) == -1)
03634 rb_sys_fail("time");
03635 tzset();
03636 if (!localtime_r(&t, &tm))
03637 rb_sys_fail("localtime");
03638
03639 y = tm.tm_year + 1900;
03640 m = tm.tm_mon + 1;
03641 d = tm.tm_mday;
03642
03643 decode_year(INT2FIX(y), -1, &nth, &ry);
03644
03645 ret = d_simple_new_internal(klass,
03646 nth, 0,
03647 GREGORIAN,
03648 ry, m, d,
03649 HAVE_CIVIL);
03650 {
03651 get_d1(ret);
03652 set_sg(dat, sg);
03653 }
03654 return ret;
03655 }
03656
03657 #define set_hash0(k,v) rb_hash_aset(hash, k, v)
03658 #define ref_hash0(k) rb_hash_aref(hash, k)
03659 #define del_hash0(k) rb_hash_delete(hash, k)
03660
03661 #define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v)
03662 #define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k)))
03663 #define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k)))
03664
03665 static VALUE
03666 rt_rewrite_frags(VALUE hash)
03667 {
03668 VALUE seconds;
03669
03670 seconds = ref_hash("seconds");
03671 if (!NIL_P(seconds)) {
03672 VALUE d, h, min, s, fr;
03673
03674 d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS));
03675 fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS));
03676
03677 h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS));
03678 fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS));
03679
03680 min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS));
03681 fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS));
03682
03683 s = f_idiv(fr, INT2FIX(1));
03684 fr = f_mod(fr, INT2FIX(1));
03685
03686 set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d));
03687 set_hash("hour", h);
03688 set_hash("min", min);
03689 set_hash("sec", s);
03690 set_hash("sec_fraction", fr);
03691 del_hash("seconds");
03692 del_hash("offset");
03693 }
03694 return hash;
03695 }
03696
03697 #define sym(x) ID2SYM(rb_intern(x))
03698
03699 static VALUE d_lite_year(VALUE);
03700 static VALUE d_lite_wday(VALUE);
03701 static VALUE d_lite_jd(VALUE);
03702
03703 static VALUE
03704 rt_complete_frags(VALUE klass, VALUE hash)
03705 {
03706 static VALUE tab = Qnil;
03707 int g, e;
03708 VALUE k, a, d;
03709
03710 if (NIL_P(tab)) {
03711 tab = rb_ary_new3(11,
03712 rb_ary_new3(2,
03713 sym("time"),
03714 rb_ary_new3(3,
03715 sym("hour"),
03716 sym("min"),
03717 sym("sec"))),
03718 rb_ary_new3(2,
03719 Qnil,
03720 rb_ary_new3(1,
03721 sym("jd"))),
03722 rb_ary_new3(2,
03723 sym("ordinal"),
03724 rb_ary_new3(5,
03725 sym("year"),
03726 sym("yday"),
03727 sym("hour"),
03728 sym("min"),
03729 sym("sec"))),
03730 rb_ary_new3(2,
03731 sym("civil"),
03732 rb_ary_new3(6,
03733 sym("year"),
03734 sym("mon"),
03735 sym("mday"),
03736 sym("hour"),
03737 sym("min"),
03738 sym("sec"))),
03739 rb_ary_new3(2,
03740 sym("commercial"),
03741 rb_ary_new3(6,
03742 sym("cwyear"),
03743 sym("cweek"),
03744 sym("cwday"),
03745 sym("hour"),
03746 sym("min"),
03747 sym("sec"))),
03748 rb_ary_new3(2,
03749 sym("wday"),
03750 rb_ary_new3(4,
03751 sym("wday"),
03752 sym("hour"),
03753 sym("min"),
03754 sym("sec"))),
03755 rb_ary_new3(2,
03756 sym("wnum0"),
03757 rb_ary_new3(6,
03758 sym("year"),
03759 sym("wnum0"),
03760 sym("wday"),
03761 sym("hour"),
03762 sym("min"),
03763 sym("sec"))),
03764 rb_ary_new3(2,
03765 sym("wnum1"),
03766 rb_ary_new3(6,
03767 sym("year"),
03768 sym("wnum1"),
03769 sym("wday"),
03770 sym("hour"),
03771 sym("min"),
03772 sym("sec"))),
03773 rb_ary_new3(2,
03774 Qnil,
03775 rb_ary_new3(6,
03776 sym("cwyear"),
03777 sym("cweek"),
03778 sym("wday"),
03779 sym("hour"),
03780 sym("min"),
03781 sym("sec"))),
03782 rb_ary_new3(2,
03783 Qnil,
03784 rb_ary_new3(6,
03785 sym("year"),
03786 sym("wnum0"),
03787 sym("cwday"),
03788 sym("hour"),
03789 sym("min"),
03790 sym("sec"))),
03791 rb_ary_new3(2,
03792 Qnil,
03793 rb_ary_new3(6,
03794 sym("year"),
03795 sym("wnum1"),
03796 sym("cwday"),
03797 sym("hour"),
03798 sym("min"),
03799 sym("sec"))));
03800 rb_gc_register_mark_object(tab);
03801 }
03802
03803 {
03804 int i, eno = 0, idx = 0;
03805
03806 for (i = 0; i < RARRAY_LENINT(tab); i++) {
03807 VALUE x, a;
03808
03809 x = RARRAY_PTR(tab)[i];
03810 a = RARRAY_PTR(x)[1];
03811
03812 {
03813 int j, n = 0;
03814
03815 for (j = 0; j < RARRAY_LENINT(a); j++)
03816 if (!NIL_P(ref_hash0(RARRAY_PTR(a)[j])))
03817 n++;
03818 if (n > eno) {
03819 eno = n;
03820 idx = i;
03821 }
03822 }
03823 }
03824 if (eno == 0)
03825 g = 0;
03826 else {
03827 g = 1;
03828 k = RARRAY_PTR(RARRAY_PTR(tab)[idx])[0];
03829 a = RARRAY_PTR(RARRAY_PTR(tab)[idx])[1];
03830 e = eno;
03831 }
03832 }
03833
03834 d = Qnil;
03835
03836 if (g && !NIL_P(k) && (RARRAY_LENINT(a) - e)) {
03837 if (k == sym("ordinal")) {
03838 if (NIL_P(ref_hash("year"))) {
03839 if (NIL_P(d))
03840 d = date_s_today(0, (VALUE *)0, cDate);
03841 set_hash("year", d_lite_year(d));
03842 }
03843 if (NIL_P(ref_hash("yday")))
03844 set_hash("yday", INT2FIX(1));
03845 }
03846 else if (k == sym("civil")) {
03847 int i;
03848
03849 for (i = 0; i < RARRAY_LENINT(a); i++) {
03850 VALUE e = RARRAY_PTR(a)[i];
03851
03852 if (!NIL_P(ref_hash0(e)))
03853 break;
03854 if (NIL_P(d))
03855 d = date_s_today(0, (VALUE *)0, cDate);
03856 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03857 }
03858 if (NIL_P(ref_hash("mon")))
03859 set_hash("mon", INT2FIX(1));
03860 if (NIL_P(ref_hash("mday")))
03861 set_hash("mday", INT2FIX(1));
03862 }
03863 else if (k == sym("commercial")) {
03864 int i;
03865
03866 for (i = 0; i < RARRAY_LENINT(a); i++) {
03867 VALUE e = RARRAY_PTR(a)[i];
03868
03869 if (!NIL_P(ref_hash0(e)))
03870 break;
03871 if (NIL_P(d))
03872 d = date_s_today(0, (VALUE *)0, cDate);
03873 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03874 }
03875 if (NIL_P(ref_hash("cweek")))
03876 set_hash("cweek", INT2FIX(1));
03877 if (NIL_P(ref_hash("cwday")))
03878 set_hash("cwday", INT2FIX(1));
03879 }
03880 else if (k == sym("wday")) {
03881 if (NIL_P(d))
03882 d = date_s_today(0, (VALUE *)0, cDate);
03883 set_hash("jd", d_lite_jd(f_add(f_sub(d,
03884 d_lite_wday(d)),
03885 ref_hash("wday"))));
03886 }
03887 else if (k == sym("wnum0")) {
03888 int i;
03889
03890 for (i = 0; i < RARRAY_LENINT(a); i++) {
03891 VALUE e = RARRAY_PTR(a)[i];
03892
03893 if (!NIL_P(ref_hash0(e)))
03894 break;
03895 if (NIL_P(d))
03896 d = date_s_today(0, (VALUE *)0, cDate);
03897 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03898 }
03899 if (NIL_P(ref_hash("wnum0")))
03900 set_hash("wnum0", INT2FIX(0));
03901 if (NIL_P(ref_hash("wday")))
03902 set_hash("wday", INT2FIX(0));
03903 }
03904 else if (k == sym("wnum1")) {
03905 int i;
03906
03907 for (i = 0; i < RARRAY_LENINT(a); i++) {
03908 VALUE e = RARRAY_PTR(a)[i];
03909
03910 if (!NIL_P(ref_hash0(e)))
03911 break;
03912 if (NIL_P(d))
03913 d = date_s_today(0, (VALUE *)0, cDate);
03914 set_hash0(e, rb_funcall(d, SYM2ID(e), 0));
03915 }
03916 if (NIL_P(ref_hash("wnum1")))
03917 set_hash("wnum1", INT2FIX(0));
03918 if (NIL_P(ref_hash("wday")))
03919 set_hash("wday", INT2FIX(1));
03920 }
03921 }
03922
03923 if (g && k == sym("time")) {
03924 if (f_le_p(klass, cDateTime)) {
03925 if (NIL_P(d))
03926 d = date_s_today(0, (VALUE *)0, cDate);
03927 if (NIL_P(ref_hash("jd")))
03928 set_hash("jd", d_lite_jd(d));
03929 }
03930 }
03931
03932 if (NIL_P(ref_hash("hour")))
03933 set_hash("hour", INT2FIX(0));
03934 if (NIL_P(ref_hash("min")))
03935 set_hash("min", INT2FIX(0));
03936 if (NIL_P(ref_hash("sec")))
03937 set_hash("sec", INT2FIX(0));
03938 else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
03939 set_hash("sec", INT2FIX(59));
03940
03941 return hash;
03942 }
03943
03944 static VALUE
03945 rt__valid_jd_p(VALUE jd, VALUE sg)
03946 {
03947 return jd;
03948 }
03949
03950 static VALUE
03951 rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg)
03952 {
03953 VALUE nth, rjd2;
03954 int ry, rd, rjd, ns;
03955
03956 if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg),
03957 &nth, &ry,
03958 &rd, &rjd,
03959 &ns))
03960 return Qnil;
03961 encode_jd(nth, rjd, &rjd2);
03962 return rjd2;
03963 }
03964
03965 static VALUE
03966 rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
03967 {
03968 VALUE nth, rjd2;
03969 int ry, rm, rd, rjd, ns;
03970
03971 if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg),
03972 &nth, &ry,
03973 &rm, &rd, &rjd,
03974 &ns))
03975 return Qnil;
03976 encode_jd(nth, rjd, &rjd2);
03977 return rjd2;
03978 }
03979
03980 static VALUE
03981 rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
03982 {
03983 VALUE nth, rjd2;
03984 int ry, rw, rd, rjd, ns;
03985
03986 if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg),
03987 &nth, &ry,
03988 &rw, &rd, &rjd,
03989 &ns))
03990 return Qnil;
03991 encode_jd(nth, rjd, &rjd2);
03992 return rjd2;
03993 }
03994
03995 static VALUE
03996 rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
03997 {
03998 VALUE nth, rjd2;
03999 int ry, rw, rd, rjd, ns;
04000
04001 if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg),
04002 &nth, &ry,
04003 &rw, &rd, &rjd,
04004 &ns))
04005 return Qnil;
04006 encode_jd(nth, rjd, &rjd2);
04007 return rjd2;
04008 }
04009
04010 static VALUE
04011 rt__valid_date_frags_p(VALUE hash, VALUE sg)
04012 {
04013 {
04014 VALUE vjd;
04015
04016 if (!NIL_P(vjd = ref_hash("jd"))) {
04017 VALUE jd = rt__valid_jd_p(vjd, sg);
04018 if (!NIL_P(jd))
04019 return jd;
04020 }
04021 }
04022
04023 {
04024 VALUE year, yday;
04025
04026 if (!NIL_P(yday = ref_hash("yday")) &&
04027 !NIL_P(year = ref_hash("year"))) {
04028 VALUE jd = rt__valid_ordinal_p(year, yday, sg);
04029 if (!NIL_P(jd))
04030 return jd;
04031 }
04032 }
04033
04034 {
04035 VALUE year, mon, mday;
04036
04037 if (!NIL_P(mday = ref_hash("mday")) &&
04038 !NIL_P(mon = ref_hash("mon")) &&
04039 !NIL_P(year = ref_hash("year"))) {
04040 VALUE jd = rt__valid_civil_p(year, mon, mday, sg);
04041 if (!NIL_P(jd))
04042 return jd;
04043 }
04044 }
04045
04046 {
04047 VALUE year, week, wday;
04048
04049 wday = ref_hash("cwday");
04050 if (NIL_P(wday)) {
04051 wday = ref_hash("wday");
04052 if (!NIL_P(wday))
04053 if (f_zero_p(wday))
04054 wday = INT2FIX(7);
04055 }
04056
04057 if (!NIL_P(wday) &&
04058 !NIL_P(week = ref_hash("cweek")) &&
04059 !NIL_P(year = ref_hash("cwyear"))) {
04060 VALUE jd = rt__valid_commercial_p(year, week, wday, sg);
04061 if (!NIL_P(jd))
04062 return jd;
04063 }
04064 }
04065
04066 {
04067 VALUE year, week, wday;
04068
04069 wday = ref_hash("wday");
04070 if (NIL_P(wday)) {
04071 wday = ref_hash("cwday");
04072 if (!NIL_P(wday))
04073 if (f_eqeq_p(wday, INT2FIX(7)))
04074 wday = INT2FIX(0);
04075 }
04076
04077 if (!NIL_P(wday) &&
04078 !NIL_P(week = ref_hash("wnum0")) &&
04079 !NIL_P(year = ref_hash("year"))) {
04080 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg);
04081 if (!NIL_P(jd))
04082 return jd;
04083 }
04084 }
04085
04086 {
04087 VALUE year, week, wday;
04088
04089 wday = ref_hash("wday");
04090 if (NIL_P(wday))
04091 wday = ref_hash("cwday");
04092 if (!NIL_P(wday))
04093 wday = f_mod(f_sub(wday, INT2FIX(1)),
04094 INT2FIX(7));
04095
04096 if (!NIL_P(wday) &&
04097 !NIL_P(week = ref_hash("wnum1")) &&
04098 !NIL_P(year = ref_hash("year"))) {
04099 VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg);
04100 if (!NIL_P(jd))
04101 return jd;
04102 }
04103 }
04104 return Qnil;
04105 }
04106
04107 static VALUE
04108 d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
04109 {
04110 VALUE jd;
04111
04112 if (!c_valid_start_p(NUM2DBL(sg))) {
04113 sg = INT2FIX(DEFAULT_SG);
04114 rb_warning("invalid start is ignored");
04115 }
04116
04117 if (NIL_P(hash))
04118 rb_raise(rb_eArgError, "invalid date");
04119
04120 if (NIL_P(ref_hash("jd")) &&
04121 NIL_P(ref_hash("yday")) &&
04122 !NIL_P(ref_hash("year")) &&
04123 !NIL_P(ref_hash("mon")) &&
04124 !NIL_P(ref_hash("mday")))
04125 jd = rt__valid_civil_p(ref_hash("year"),
04126 ref_hash("mon"),
04127 ref_hash("mday"), sg);
04128 else {
04129 hash = rt_rewrite_frags(hash);
04130 hash = rt_complete_frags(klass, hash);
04131 jd = rt__valid_date_frags_p(hash, sg);
04132 }
04133
04134 if (NIL_P(jd))
04135 rb_raise(rb_eArgError, "invalid date");
04136 {
04137 VALUE nth;
04138 int rjd;
04139
04140 decode_jd(jd, &nth, &rjd);
04141 return d_simple_new_internal(klass,
04142 nth, rjd,
04143 NUM2DBL(sg),
04144 0, 0, 0,
04145 HAVE_JD);
04146 }
04147 }
04148
04149 VALUE date__strptime(const char *str, size_t slen,
04150 const char *fmt, size_t flen, VALUE hash);
04151
04152 static VALUE
04153 date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
04154 const char *default_fmt)
04155 {
04156 VALUE vstr, vfmt, hash;
04157 const char *str, *fmt;
04158 size_t slen, flen;
04159
04160 rb_scan_args(argc, argv, "11", &vstr, &vfmt);
04161
04162 StringValue(vstr);
04163 if (!rb_enc_str_asciicompat_p(vstr))
04164 rb_raise(rb_eArgError,
04165 "string should have ASCII compatible encoding");
04166 str = RSTRING_PTR(vstr);
04167 slen = RSTRING_LEN(vstr);
04168 if (argc < 2) {
04169 fmt = default_fmt;
04170 flen = strlen(default_fmt);
04171 }
04172 else {
04173 StringValue(vfmt);
04174 if (!rb_enc_str_asciicompat_p(vfmt))
04175 rb_raise(rb_eArgError,
04176 "format should have ASCII compatible encoding");
04177 fmt = RSTRING_PTR(vfmt);
04178 flen = RSTRING_LEN(vfmt);
04179 }
04180 hash = rb_hash_new();
04181 if (NIL_P(date__strptime(str, slen, fmt, flen, hash)))
04182 return Qnil;
04183
04184 {
04185 VALUE zone = ref_hash("zone");
04186 VALUE left = ref_hash("leftover");
04187
04188 if (!NIL_P(zone)) {
04189 rb_enc_copy(zone, vstr);
04190 OBJ_INFECT(zone, vstr);
04191 set_hash("zone", zone);
04192 }
04193 if (!NIL_P(left)) {
04194 rb_enc_copy(left, vstr);
04195 OBJ_INFECT(left, vstr);
04196 set_hash("leftover", left);
04197 }
04198 }
04199
04200 return hash;
04201 }
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217 static VALUE
04218 date_s__strptime(int argc, VALUE *argv, VALUE klass)
04219 {
04220 return date_s__strptime_internal(argc, argv, klass, "%F");
04221 }
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242 static VALUE
04243 date_s_strptime(int argc, VALUE *argv, VALUE klass)
04244 {
04245 VALUE str, fmt, sg;
04246
04247 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
04248
04249 switch (argc) {
04250 case 0:
04251 str = rb_str_new2("-4712-01-01");
04252 case 1:
04253 fmt = rb_str_new2("%F");
04254 case 2:
04255 sg = INT2FIX(DEFAULT_SG);
04256 }
04257
04258 {
04259 VALUE argv2[2], hash;
04260
04261 argv2[0] = str;
04262 argv2[1] = fmt;
04263 hash = date_s__strptime(2, argv2, klass);
04264 return d_new_by_frags(klass, hash, sg);
04265 }
04266 }
04267
04268 VALUE date__parse(VALUE str, VALUE comp);
04269
04270 static VALUE
04271 date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
04272 {
04273 VALUE vstr, vcomp, hash;
04274
04275 rb_scan_args(argc, argv, "11", &vstr, &vcomp);
04276 StringValue(vstr);
04277 if (!rb_enc_str_asciicompat_p(vstr))
04278 rb_raise(rb_eArgError,
04279 "string should have ASCII compatible encoding");
04280 if (argc < 2)
04281 vcomp = Qtrue;
04282
04283 hash = date__parse(vstr, vcomp);
04284
04285 {
04286 VALUE zone = ref_hash("zone");
04287
04288 if (!NIL_P(zone)) {
04289 rb_enc_copy(zone, vstr);
04290 OBJ_INFECT(zone, vstr);
04291 set_hash("zone", zone);
04292 }
04293 }
04294
04295 return hash;
04296 }
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313 static VALUE
04314 date_s__parse(int argc, VALUE *argv, VALUE klass)
04315 {
04316 return date_s__parse_internal(argc, argv, klass);
04317 }
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336 static VALUE
04337 date_s_parse(int argc, VALUE *argv, VALUE klass)
04338 {
04339 VALUE str, comp, sg;
04340
04341 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
04342
04343 switch (argc) {
04344 case 0:
04345 str = rb_str_new2("-4712-01-01");
04346 case 1:
04347 comp = Qtrue;
04348 case 2:
04349 sg = INT2FIX(DEFAULT_SG);
04350 }
04351
04352 {
04353 VALUE argv2[2], hash;
04354
04355 argv2[0] = str;
04356 argv2[1] = comp;
04357 hash = date_s__parse(2, argv2, klass);
04358 return d_new_by_frags(klass, hash, sg);
04359 }
04360 }
04361
04362 VALUE date__iso8601(VALUE);
04363 VALUE date__rfc3339(VALUE);
04364 VALUE date__xmlschema(VALUE);
04365 VALUE date__rfc2822(VALUE);
04366 VALUE date__httpdate(VALUE);
04367 VALUE date__jisx0301(VALUE);
04368
04369
04370
04371
04372
04373
04374
04375 static VALUE
04376 date_s__iso8601(VALUE klass, VALUE str)
04377 {
04378 return date__iso8601(str);
04379 }
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394 static VALUE
04395 date_s_iso8601(int argc, VALUE *argv, VALUE klass)
04396 {
04397 VALUE str, sg;
04398
04399 rb_scan_args(argc, argv, "02", &str, &sg);
04400
04401 switch (argc) {
04402 case 0:
04403 str = rb_str_new2("-4712-01-01");
04404 case 1:
04405 sg = INT2FIX(DEFAULT_SG);
04406 }
04407
04408 {
04409 VALUE hash = date_s__iso8601(klass, str);
04410 return d_new_by_frags(klass, hash, sg);
04411 }
04412 }
04413
04414
04415
04416
04417
04418
04419
04420 static VALUE
04421 date_s__rfc3339(VALUE klass, VALUE str)
04422 {
04423 return date__rfc3339(str);
04424 }
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437 static VALUE
04438 date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
04439 {
04440 VALUE str, sg;
04441
04442 rb_scan_args(argc, argv, "02", &str, &sg);
04443
04444 switch (argc) {
04445 case 0:
04446 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
04447 case 1:
04448 sg = INT2FIX(DEFAULT_SG);
04449 }
04450
04451 {
04452 VALUE hash = date_s__rfc3339(klass, str);
04453 return d_new_by_frags(klass, hash, sg);
04454 }
04455 }
04456
04457
04458
04459
04460
04461
04462
04463 static VALUE
04464 date_s__xmlschema(VALUE klass, VALUE str)
04465 {
04466 return date__xmlschema(str);
04467 }
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480 static VALUE
04481 date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
04482 {
04483 VALUE str, sg;
04484
04485 rb_scan_args(argc, argv, "02", &str, &sg);
04486
04487 switch (argc) {
04488 case 0:
04489 str = rb_str_new2("-4712-01-01");
04490 case 1:
04491 sg = INT2FIX(DEFAULT_SG);
04492 }
04493
04494 {
04495 VALUE hash = date_s__xmlschema(klass, str);
04496 return d_new_by_frags(klass, hash, sg);
04497 }
04498 }
04499
04500
04501
04502
04503
04504
04505
04506
04507 static VALUE
04508 date_s__rfc2822(VALUE klass, VALUE str)
04509 {
04510 return date__rfc2822(str);
04511 }
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526 static VALUE
04527 date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
04528 {
04529 VALUE str, sg;
04530
04531 rb_scan_args(argc, argv, "02", &str, &sg);
04532
04533 switch (argc) {
04534 case 0:
04535 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
04536 case 1:
04537 sg = INT2FIX(DEFAULT_SG);
04538 }
04539
04540 {
04541 VALUE hash = date_s__rfc2822(klass, str);
04542 return d_new_by_frags(klass, hash, sg);
04543 }
04544 }
04545
04546
04547
04548
04549
04550
04551
04552 static VALUE
04553 date_s__httpdate(VALUE klass, VALUE str)
04554 {
04555 return date__httpdate(str);
04556 }
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571 static VALUE
04572 date_s_httpdate(int argc, VALUE *argv, VALUE klass)
04573 {
04574 VALUE str, sg;
04575
04576 rb_scan_args(argc, argv, "02", &str, &sg);
04577
04578 switch (argc) {
04579 case 0:
04580 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
04581 case 1:
04582 sg = INT2FIX(DEFAULT_SG);
04583 }
04584
04585 {
04586 VALUE hash = date_s__httpdate(klass, str);
04587 return d_new_by_frags(klass, hash, sg);
04588 }
04589 }
04590
04591
04592
04593
04594
04595
04596
04597 static VALUE
04598 date_s__jisx0301(VALUE klass, VALUE str)
04599 {
04600 return date__jisx0301(str);
04601 }
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614 static VALUE
04615 date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
04616 {
04617 VALUE str, sg;
04618
04619 rb_scan_args(argc, argv, "02", &str, &sg);
04620
04621 switch (argc) {
04622 case 0:
04623 str = rb_str_new2("-4712-01-01");
04624 case 1:
04625 sg = INT2FIX(DEFAULT_SG);
04626 }
04627
04628 {
04629 VALUE hash = date_s__jisx0301(klass, str);
04630 return d_new_by_frags(klass, hash, sg);
04631 }
04632 }
04633
04634 static VALUE
04635 dup_obj(VALUE self)
04636 {
04637 get_d1a(self);
04638
04639 if (simple_dat_p(adat)) {
04640 VALUE new = d_lite_s_alloc_simple(rb_obj_class(self));
04641 {
04642 get_d1b(new);
04643 bdat->s = adat->s;
04644 return new;
04645 }
04646 }
04647 else {
04648 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04649 {
04650 get_d1b(new);
04651 bdat->c = adat->c;
04652 return new;
04653 }
04654 }
04655 }
04656
04657 static VALUE
04658 dup_obj_as_complex(VALUE self)
04659 {
04660 get_d1a(self);
04661
04662 if (simple_dat_p(adat)) {
04663 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04664 {
04665 get_d1b(new);
04666 copy_simple_to_complex(&bdat->c, &adat->s);
04667 bdat->c.flags |= HAVE_DF | COMPLEX_DAT;
04668 return new;
04669 }
04670 }
04671 else {
04672 VALUE new = d_lite_s_alloc_complex(rb_obj_class(self));
04673 {
04674 get_d1b(new);
04675 bdat->c = adat->c;
04676 return new;
04677 }
04678 }
04679 }
04680
04681 #define val2off(vof,iof) \
04682 {\
04683 if (!offset_to_sec(vof, &iof)) {\
04684 iof = 0;\
04685 rb_warning("invalid offset is ignored");\
04686 }\
04687 }
04688
04689 #ifndef NDEBUG
04690 static VALUE
04691 d_lite_initialize(int argc, VALUE *argv, VALUE self)
04692 {
04693 VALUE jd, vjd, vdf, sf, vsf, vof, vsg;
04694 int df, of;
04695 double sg;
04696
04697 rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
04698
04699 jd = INT2FIX(0);
04700 df = 0;
04701 sf = INT2FIX(0);
04702 of = 0;
04703 sg = DEFAULT_SG;
04704
04705 switch (argc) {
04706 case 5:
04707 val2sg(vsg, sg);
04708 case 4:
04709 val2off(vof, of);
04710 case 3:
04711 sf = vsf;
04712 if (f_lt_p(sf, INT2FIX(0)) ||
04713 f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS)))
04714 rb_raise(rb_eArgError, "invalid second fraction");
04715 case 2:
04716 df = NUM2INT(vdf);
04717 if (df < 0 || df >= DAY_IN_SECONDS)
04718 rb_raise(rb_eArgError, "invalid day fraction");
04719 case 1:
04720 jd = vjd;
04721 }
04722
04723 {
04724 VALUE nth;
04725 int rjd;
04726
04727 get_d1(self);
04728
04729 decode_jd(jd, &nth, &rjd);
04730 if (!df && f_zero_p(sf) && !of) {
04731 set_to_simple(&dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD);
04732 }
04733 else {
04734 if (!complex_dat_p(dat))
04735 rb_raise(rb_eArgError,
04736 "cannot load complex into simple");
04737
04738 set_to_complex(&dat->c, nth, rjd, df, sf, of, sg,
04739 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT);
04740 }
04741 }
04742 return self;
04743 }
04744 #endif
04745
04746
04747 static VALUE
04748 d_lite_initialize_copy(VALUE copy, VALUE date)
04749 {
04750 if (copy == date)
04751 return copy;
04752 {
04753 get_d2(copy, date);
04754 if (simple_dat_p(bdat)) {
04755 adat->s = bdat->s;
04756 adat->s.flags &= ~COMPLEX_DAT;
04757 }
04758 else {
04759 if (!complex_dat_p(adat))
04760 rb_raise(rb_eArgError,
04761 "cannot load complex into simple");
04762
04763 adat->c = bdat->c;
04764 adat->c.flags |= COMPLEX_DAT;
04765 }
04766 }
04767 return copy;
04768 }
04769
04770 #ifndef NDEBUG
04771 static VALUE
04772 d_lite_fill(VALUE self)
04773 {
04774 get_d1(self);
04775
04776 if (simple_dat_p(dat)) {
04777 get_s_jd(dat);
04778 get_s_civil(dat);
04779 }
04780 else {
04781 get_c_jd(dat);
04782 get_c_civil(dat);
04783 get_c_df(dat);
04784 get_c_time(dat);
04785 }
04786 return self;
04787 }
04788 #endif
04789
04790
04791
04792
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802 static VALUE
04803 d_lite_ajd(VALUE self)
04804 {
04805 get_d1(self);
04806 return m_ajd(dat);
04807 }
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821 static VALUE
04822 d_lite_amjd(VALUE self)
04823 {
04824 get_d1(self);
04825 return m_amjd(dat);
04826 }
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838
04839
04840 static VALUE
04841 d_lite_jd(VALUE self)
04842 {
04843 get_d1(self);
04844 return m_real_local_jd(dat);
04845 }
04846
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858
04859 static VALUE
04860 d_lite_mjd(VALUE self)
04861 {
04862 get_d1(self);
04863 return f_sub(m_real_local_jd(dat), INT2FIX(2400001));
04864 }
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877 static VALUE
04878 d_lite_ld(VALUE self)
04879 {
04880 get_d1(self);
04881 return f_sub(m_real_local_jd(dat), INT2FIX(2299160));
04882 }
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895 static VALUE
04896 d_lite_year(VALUE self)
04897 {
04898 get_d1(self);
04899 return m_real_year(dat);
04900 }
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912 static VALUE
04913 d_lite_yday(VALUE self)
04914 {
04915 get_d1(self);
04916 return INT2FIX(m_yday(dat));
04917 }
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930 static VALUE
04931 d_lite_mon(VALUE self)
04932 {
04933 get_d1(self);
04934 return INT2FIX(m_mon(dat));
04935 }
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948 static VALUE
04949 d_lite_mday(VALUE self)
04950 {
04951 get_d1(self);
04952 return INT2FIX(m_mday(dat));
04953 }
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965 static VALUE
04966 d_lite_day_fraction(VALUE self)
04967 {
04968 get_d1(self);
04969 if (simple_dat_p(dat))
04970 return INT2FIX(0);
04971 return m_fr(dat);
04972 }
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985 static VALUE
04986 d_lite_cwyear(VALUE self)
04987 {
04988 get_d1(self);
04989 return m_real_cwyear(dat);
04990 }
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002 static VALUE
05003 d_lite_cweek(VALUE self)
05004 {
05005 get_d1(self);
05006 return INT2FIX(m_cweek(dat));
05007 }
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019 static VALUE
05020 d_lite_cwday(VALUE self)
05021 {
05022 get_d1(self);
05023 return INT2FIX(m_cwday(dat));
05024 }
05025
05026 #ifndef NDEBUG
05027 static VALUE
05028 d_lite_wnum0(VALUE self)
05029 {
05030 get_d1(self);
05031 return INT2FIX(m_wnum0(dat));
05032 }
05033
05034 static VALUE
05035 d_lite_wnum1(VALUE self)
05036 {
05037 get_d1(self);
05038 return INT2FIX(m_wnum1(dat));
05039 }
05040 #endif
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052 static VALUE
05053 d_lite_wday(VALUE self)
05054 {
05055 get_d1(self);
05056 return INT2FIX(m_wday(dat));
05057 }
05058
05059
05060
05061
05062
05063
05064
05065 static VALUE
05066 d_lite_sunday_p(VALUE self)
05067 {
05068 get_d1(self);
05069 return f_boolcast(m_wday(dat) == 0);
05070 }
05071
05072
05073
05074
05075
05076
05077
05078 static VALUE
05079 d_lite_monday_p(VALUE self)
05080 {
05081 get_d1(self);
05082 return f_boolcast(m_wday(dat) == 1);
05083 }
05084
05085
05086
05087
05088
05089
05090
05091 static VALUE
05092 d_lite_tuesday_p(VALUE self)
05093 {
05094 get_d1(self);
05095 return f_boolcast(m_wday(dat) == 2);
05096 }
05097
05098
05099
05100
05101
05102
05103
05104 static VALUE
05105 d_lite_wednesday_p(VALUE self)
05106 {
05107 get_d1(self);
05108 return f_boolcast(m_wday(dat) == 3);
05109 }
05110
05111
05112
05113
05114
05115
05116
05117 static VALUE
05118 d_lite_thursday_p(VALUE self)
05119 {
05120 get_d1(self);
05121 return f_boolcast(m_wday(dat) == 4);
05122 }
05123
05124
05125
05126
05127
05128
05129
05130 static VALUE
05131 d_lite_friday_p(VALUE self)
05132 {
05133 get_d1(self);
05134 return f_boolcast(m_wday(dat) == 5);
05135 }
05136
05137
05138
05139
05140
05141
05142
05143 static VALUE
05144 d_lite_saturday_p(VALUE self)
05145 {
05146 get_d1(self);
05147 return f_boolcast(m_wday(dat) == 6);
05148 }
05149
05150 #ifndef NDEBUG
05151 static VALUE
05152 d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
05153 {
05154 int rjd, ns;
05155
05156 get_d1(self);
05157
05158 if (NUM2INT(k) != m_wday(dat))
05159 return Qfalse;
05160
05161 c_nth_kday_to_jd(m_year(dat), m_mon(dat),
05162 NUM2INT(n), NUM2INT(k), m_virtual_sg(dat),
05163 &rjd, &ns);
05164 if (m_local_jd(dat) != rjd)
05165 return Qfalse;
05166 return Qtrue;
05167 }
05168 #endif
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180 static VALUE
05181 d_lite_hour(VALUE self)
05182 {
05183 get_d1(self);
05184 return INT2FIX(m_hour(dat));
05185 }
05186
05187
05188
05189
05190
05191
05192
05193
05194
05195
05196
05197
05198 static VALUE
05199 d_lite_min(VALUE self)
05200 {
05201 get_d1(self);
05202 return INT2FIX(m_min(dat));
05203 }
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216 static VALUE
05217 d_lite_sec(VALUE self)
05218 {
05219 get_d1(self);
05220 return INT2FIX(m_sec(dat));
05221 }
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234 static VALUE
05235 d_lite_sec_fraction(VALUE self)
05236 {
05237 get_d1(self);
05238 return m_sf_in_sec(dat);
05239 }
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251 static VALUE
05252 d_lite_offset(VALUE self)
05253 {
05254 get_d1(self);
05255 return m_of_in_day(dat);
05256 }
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268 static VALUE
05269 d_lite_zone(VALUE self)
05270 {
05271 get_d1(self);
05272 return m_zone(dat);
05273 }
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286 static VALUE
05287 d_lite_julian_p(VALUE self)
05288 {
05289 get_d1(self);
05290 return f_boolcast(m_julian_p(dat));
05291 }
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304 static VALUE
05305 d_lite_gregorian_p(VALUE self)
05306 {
05307 get_d1(self);
05308 return f_boolcast(m_gregorian_p(dat));
05309 }
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322 static VALUE
05323 d_lite_leap_p(VALUE self)
05324 {
05325 int rjd, ns, ry, rm, rd;
05326
05327 get_d1(self);
05328 if (m_gregorian_p(dat))
05329 return f_boolcast(c_gregorian_leap_p(m_year(dat)));
05330
05331 c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat),
05332 &rjd, &ns);
05333 c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd);
05334 return f_boolcast(rd == 29);
05335 }
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348 static VALUE
05349 d_lite_start(VALUE self)
05350 {
05351 get_d1(self);
05352 return DBL2NUM(m_sg(dat));
05353 }
05354
05355 static void
05356 clear_civil(union DateData *x)
05357 {
05358 if (simple_dat_p(x)) {
05359 x->s.year = 0;
05360 #ifndef USE_PACK
05361 x->s.mon = 0;
05362 x->s.mday = 0;
05363 #else
05364 x->s.pc = 0;
05365 #endif
05366 x->s.flags &= ~HAVE_CIVIL;
05367 }
05368 else {
05369 x->c.year = 0;
05370 #ifndef USE_PACK
05371 x->c.mon = 0;
05372 x->c.mday = 0;
05373 x->c.hour = 0;
05374 x->c.min = 0;
05375 x->c.sec = 0;
05376 #else
05377 x->c.pc = 0;
05378 #endif
05379 x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME);
05380 }
05381 }
05382
05383 static void
05384 set_sg(union DateData *x, double sg)
05385 {
05386 if (simple_dat_p(x)) {
05387 get_s_jd(x);
05388 clear_civil(x);
05389 x->s.sg = (sg_cast)sg;
05390 } else {
05391 get_c_jd(x);
05392 get_c_df(x);
05393 clear_civil(x);
05394 x->c.sg = (sg_cast)sg;
05395 }
05396 }
05397
05398 static VALUE
05399 dup_obj_with_new_start(VALUE obj, double sg)
05400 {
05401 volatile VALUE dup = dup_obj(obj);
05402 {
05403 get_d1(dup);
05404 set_sg(dat, sg);
05405 }
05406 return dup;
05407 }
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420 static VALUE
05421 d_lite_new_start(int argc, VALUE *argv, VALUE self)
05422 {
05423 VALUE vsg;
05424 double sg;
05425
05426 rb_scan_args(argc, argv, "01", &vsg);
05427
05428 sg = DEFAULT_SG;
05429 if (argc >= 1)
05430 val2sg(vsg, sg);
05431
05432 return dup_obj_with_new_start(self, sg);
05433 }
05434
05435
05436
05437
05438
05439
05440
05441 static VALUE
05442 d_lite_italy(VALUE self)
05443 {
05444 return dup_obj_with_new_start(self, ITALY);
05445 }
05446
05447
05448
05449
05450
05451
05452
05453 static VALUE
05454 d_lite_england(VALUE self)
05455 {
05456 return dup_obj_with_new_start(self, ENGLAND);
05457 }
05458
05459
05460
05461
05462
05463
05464
05465 static VALUE
05466 d_lite_julian(VALUE self)
05467 {
05468 return dup_obj_with_new_start(self, JULIAN);
05469 }
05470
05471
05472
05473
05474
05475
05476
05477 static VALUE
05478 d_lite_gregorian(VALUE self)
05479 {
05480 return dup_obj_with_new_start(self, GREGORIAN);
05481 }
05482
05483 static void
05484 set_of(union DateData *x, int of)
05485 {
05486 assert(complex_dat_p(x));
05487 get_c_jd(x);
05488 get_c_df(x);
05489 clear_civil(x);
05490 x->c.of = of;
05491 }
05492
05493 static VALUE
05494 dup_obj_with_new_offset(VALUE obj, int of)
05495 {
05496 volatile VALUE dup = dup_obj_as_complex(obj);
05497 {
05498 get_d1(dup);
05499 set_of(dat, of);
05500 }
05501 return dup;
05502 }
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516 static VALUE
05517 d_lite_new_offset(int argc, VALUE *argv, VALUE self)
05518 {
05519 VALUE vof;
05520 int rof;
05521
05522 rb_scan_args(argc, argv, "01", &vof);
05523
05524 rof = 0;
05525 if (argc >= 1)
05526 val2off(vof, rof);
05527
05528 return dup_obj_with_new_offset(self, rof);
05529 }
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549 static VALUE
05550 d_lite_plus(VALUE self, VALUE other)
05551 {
05552 get_d1(self);
05553
05554 switch (TYPE(other)) {
05555 case T_FIXNUM:
05556 {
05557 VALUE nth;
05558 long t;
05559 int jd;
05560
05561 nth = m_nth(dat);
05562 t = FIX2LONG(other);
05563 if (DIV(t, CM_PERIOD)) {
05564 nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD)));
05565 t = MOD(t, CM_PERIOD);
05566 }
05567
05568 if (!t)
05569 jd = m_jd(dat);
05570 else {
05571 jd = m_jd(dat) + (int)t;
05572
05573 if (jd < 0) {
05574 nth = f_sub(nth, INT2FIX(1));
05575 jd += CM_PERIOD;
05576 }
05577 else if (jd >= CM_PERIOD) {
05578 nth = f_add(nth, INT2FIX(1));
05579 jd -= CM_PERIOD;
05580 }
05581 }
05582
05583 if (simple_dat_p(dat))
05584 return d_simple_new_internal(rb_obj_class(self),
05585 nth, jd,
05586 dat->s.sg,
05587 0, 0, 0,
05588 (dat->s.flags | HAVE_JD) &
05589 ~HAVE_CIVIL);
05590 else
05591 return d_complex_new_internal(rb_obj_class(self),
05592 nth, jd,
05593 dat->c.df, dat->c.sf,
05594 dat->c.of, dat->c.sg,
05595 0, 0, 0,
05596 #ifndef USE_PACK
05597 dat->c.hour,
05598 dat->c.min,
05599 dat->c.sec,
05600 #else
05601 EX_HOUR(dat->c.pc),
05602 EX_MIN(dat->c.pc),
05603 EX_SEC(dat->c.pc),
05604 #endif
05605 (dat->c.flags | HAVE_JD) &
05606 ~HAVE_CIVIL);
05607 }
05608 break;
05609 case T_BIGNUM:
05610 {
05611 VALUE nth;
05612 int jd, s;
05613
05614 if (f_positive_p(other))
05615 s = +1;
05616 else {
05617 s = -1;
05618 other = f_negate(other);
05619 }
05620
05621 nth = f_idiv(other, INT2FIX(CM_PERIOD));
05622 jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD)));
05623
05624 if (s < 0) {
05625 nth = f_negate(nth);
05626 jd = -jd;
05627 }
05628
05629 if (!jd)
05630 jd = m_jd(dat);
05631 else {
05632 jd = m_jd(dat) + jd;
05633 if (jd < 0) {
05634 nth = f_sub(nth, INT2FIX(1));
05635 jd += CM_PERIOD;
05636 }
05637 else if (jd >= CM_PERIOD) {
05638 nth = f_add(nth, INT2FIX(1));
05639 jd -= CM_PERIOD;
05640 }
05641 }
05642
05643 if (f_zero_p(nth))
05644 nth = m_nth(dat);
05645 else
05646 nth = f_add(m_nth(dat), nth);
05647
05648 if (simple_dat_p(dat))
05649 return d_simple_new_internal(rb_obj_class(self),
05650 nth, jd,
05651 dat->s.sg,
05652 0, 0, 0,
05653 (dat->s.flags | HAVE_JD) &
05654 ~HAVE_CIVIL);
05655 else
05656 return d_complex_new_internal(rb_obj_class(self),
05657 nth, jd,
05658 dat->c.df, dat->c.sf,
05659 dat->c.of, dat->c.sg,
05660 0, 0, 0,
05661 #ifndef USE_PACK
05662 dat->c.hour,
05663 dat->c.min,
05664 dat->c.sec,
05665 #else
05666 EX_HOUR(dat->c.pc),
05667 EX_MIN(dat->c.pc),
05668 EX_SEC(dat->c.pc),
05669 #endif
05670 (dat->c.flags | HAVE_JD) &
05671 ~HAVE_CIVIL);
05672 }
05673 break;
05674 case T_FLOAT:
05675 {
05676 double jd, o, tmp;
05677 int s, df;
05678 VALUE nth, sf;
05679
05680 o = RFLOAT_VALUE(other);
05681
05682 if (o > 0)
05683 s = +1;
05684 else {
05685 s = -1;
05686 o = -o;
05687 }
05688
05689 o = modf(o, &tmp);
05690
05691 if (!floor(tmp / CM_PERIOD)) {
05692 nth = INT2FIX(0);
05693 jd = (int)tmp;
05694 }
05695 else {
05696 double i, f;
05697
05698 f = modf(tmp / CM_PERIOD, &i);
05699 nth = f_floor(DBL2NUM(i));
05700 jd = (int)(f * CM_PERIOD);
05701 }
05702
05703 o *= DAY_IN_SECONDS;
05704 o = modf(o, &tmp);
05705 df = (int)tmp;
05706 o *= SECOND_IN_NANOSECONDS;
05707 sf = INT2FIX((int)round(o));
05708
05709 if (s < 0) {
05710 jd = -jd;
05711 df = -df;
05712 sf = f_negate(sf);
05713 }
05714
05715 if (f_zero_p(sf))
05716 sf = m_sf(dat);
05717 else {
05718 sf = f_add(m_sf(dat), sf);
05719 if (f_lt_p(sf, INT2FIX(0))) {
05720 df -= 1;
05721 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05722 }
05723 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05724 df += 1;
05725 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05726 }
05727 }
05728
05729 if (!df)
05730 df = m_df(dat);
05731 else {
05732 df = m_df(dat) + df;
05733 if (df < 0) {
05734 jd -= 1;
05735 df += DAY_IN_SECONDS;
05736 }
05737 else if (df >= DAY_IN_SECONDS) {
05738 jd += 1;
05739 df -= DAY_IN_SECONDS;
05740 }
05741 }
05742
05743 if (!jd)
05744 jd = m_jd(dat);
05745 else {
05746 jd = m_jd(dat) + jd;
05747 if (jd < 0) {
05748 nth = f_sub(nth, INT2FIX(1));
05749 jd += CM_PERIOD;
05750 }
05751 else if (jd >= CM_PERIOD) {
05752 nth = f_add(nth, INT2FIX(1));
05753 jd -= CM_PERIOD;
05754 }
05755 }
05756
05757 if (f_zero_p(nth))
05758 nth = m_nth(dat);
05759 else
05760 nth = f_add(m_nth(dat), nth);
05761
05762 if (!df && f_zero_p(sf) && !m_of(dat))
05763 return d_simple_new_internal(rb_obj_class(self),
05764 nth, (int)jd,
05765 m_sg(dat),
05766 0, 0, 0,
05767 (dat->s.flags | HAVE_JD) &
05768 ~(HAVE_CIVIL | HAVE_TIME |
05769 COMPLEX_DAT));
05770 else
05771 return d_complex_new_internal(rb_obj_class(self),
05772 nth, (int)jd,
05773 df, sf,
05774 m_of(dat), m_sg(dat),
05775 0, 0, 0,
05776 0, 0, 0,
05777 (dat->c.flags |
05778 HAVE_JD | HAVE_DF) &
05779 ~(HAVE_CIVIL | HAVE_TIME));
05780 }
05781 break;
05782 default:
05783 if (!k_numeric_p(other))
05784 rb_raise(rb_eTypeError, "expected numeric");
05785 other = f_to_r(other);
05786 #ifdef CANONICALIZATION_FOR_MATHN
05787 if (!k_rational_p(other))
05788 return d_lite_plus(self, other);
05789 #endif
05790
05791 case T_RATIONAL:
05792 {
05793 VALUE nth, sf, t;
05794 int jd, df, s;
05795
05796 if (wholenum_p(other))
05797 return d_lite_plus(self, RRATIONAL(other)->num);
05798
05799 if (f_positive_p(other))
05800 s = +1;
05801 else {
05802 s = -1;
05803 other = f_negate(other);
05804 }
05805
05806 nth = f_idiv(other, INT2FIX(CM_PERIOD));
05807 t = f_mod(other, INT2FIX(CM_PERIOD));
05808
05809 jd = FIX2INT(f_idiv(t, INT2FIX(1)));
05810 t = f_mod(t, INT2FIX(1));
05811
05812 t = f_mul(t, INT2FIX(DAY_IN_SECONDS));
05813 df = FIX2INT(f_idiv(t, INT2FIX(1)));
05814 t = f_mod(t, INT2FIX(1));
05815
05816 sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS));
05817
05818 if (s < 0) {
05819 nth = f_negate(nth);
05820 jd = -jd;
05821 df = -df;
05822 sf = f_negate(sf);
05823 }
05824
05825 if (f_zero_p(sf))
05826 sf = m_sf(dat);
05827 else {
05828 sf = f_add(m_sf(dat), sf);
05829 if (f_lt_p(sf, INT2FIX(0))) {
05830 df -= 1;
05831 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05832 }
05833 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05834 df += 1;
05835 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05836 }
05837 }
05838
05839 if (!df)
05840 df = m_df(dat);
05841 else {
05842 df = m_df(dat) + df;
05843 if (df < 0) {
05844 jd -= 1;
05845 df += DAY_IN_SECONDS;
05846 }
05847 else if (df >= DAY_IN_SECONDS) {
05848 jd += 1;
05849 df -= DAY_IN_SECONDS;
05850 }
05851 }
05852
05853 if (!jd)
05854 jd = m_jd(dat);
05855 else {
05856 jd = m_jd(dat) + jd;
05857 if (jd < 0) {
05858 nth = f_sub(nth, INT2FIX(1));
05859 jd += CM_PERIOD;
05860 }
05861 else if (jd >= CM_PERIOD) {
05862 nth = f_add(nth, INT2FIX(1));
05863 jd -= CM_PERIOD;
05864 }
05865 }
05866
05867 if (f_zero_p(nth))
05868 nth = m_nth(dat);
05869 else
05870 nth = f_add(m_nth(dat), nth);
05871
05872 if (!df && f_zero_p(sf) && !m_of(dat))
05873 return d_simple_new_internal(rb_obj_class(self),
05874 nth, jd,
05875 m_sg(dat),
05876 0, 0, 0,
05877 (dat->s.flags | HAVE_JD) &
05878 ~(HAVE_CIVIL | HAVE_TIME |
05879 COMPLEX_DAT));
05880 else
05881 return d_complex_new_internal(rb_obj_class(self),
05882 nth, jd,
05883 df, sf,
05884 m_of(dat), m_sg(dat),
05885 0, 0, 0,
05886 0, 0, 0,
05887 (dat->c.flags |
05888 HAVE_JD | HAVE_DF) &
05889 ~(HAVE_CIVIL | HAVE_TIME));
05890 }
05891 break;
05892 }
05893 }
05894
05895 static VALUE
05896 minus_dd(VALUE self, VALUE other)
05897 {
05898 get_d2(self, other);
05899
05900 {
05901 int d, df;
05902 VALUE n, sf, r;
05903
05904 n = f_sub(m_nth(adat), m_nth(bdat));
05905 d = m_jd(adat) - m_jd(bdat);
05906 df = m_df(adat) - m_df(bdat);
05907 sf = f_sub(m_sf(adat), m_sf(bdat));
05908
05909 if (d < 0) {
05910 n = f_sub(n, INT2FIX(1));
05911 d += CM_PERIOD;
05912 }
05913 else if (d >= CM_PERIOD) {
05914 n = f_add(n, INT2FIX(1));
05915 d -= CM_PERIOD;
05916 }
05917
05918 if (df < 0) {
05919 d -= 1;
05920 df += DAY_IN_SECONDS;
05921 }
05922 else if (df >= DAY_IN_SECONDS) {
05923 d += 1;
05924 df -= DAY_IN_SECONDS;
05925 }
05926
05927 if (f_lt_p(sf, INT2FIX(0))) {
05928 df -= 1;
05929 sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05930 }
05931 else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) {
05932 df += 1;
05933 sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS));
05934 }
05935
05936 if (f_zero_p(n))
05937 r = INT2FIX(0);
05938 else
05939 r = f_mul(n, INT2FIX(CM_PERIOD));
05940
05941 if (d)
05942 r = f_add(r, rb_rational_new1(INT2FIX(d)));
05943 if (df)
05944 r = f_add(r, isec_to_day(df));
05945 if (f_nonzero_p(sf))
05946 r = f_add(r, ns_to_day(sf));
05947
05948 if (TYPE(r) == T_RATIONAL)
05949 return r;
05950 return rb_rational_new1(r);
05951 }
05952 }
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973 static VALUE
05974 d_lite_minus(VALUE self, VALUE other)
05975 {
05976 if (k_date_p(other))
05977 return minus_dd(self, other);
05978
05979 switch (TYPE(other)) {
05980 case T_FIXNUM:
05981 return d_lite_plus(self, LONG2NUM(-FIX2LONG(other)));
05982 case T_FLOAT:
05983 return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other)));
05984 default:
05985 if (!k_numeric_p(other))
05986 rb_raise(rb_eTypeError, "expected numeric");
05987
05988 case T_BIGNUM:
05989 case T_RATIONAL:
05990 return d_lite_plus(self, f_negate(other));
05991 }
05992 }
05993
05994
05995
05996
05997
05998
05999
06000 static VALUE
06001 d_lite_next_day(int argc, VALUE *argv, VALUE self)
06002 {
06003 VALUE n;
06004
06005 rb_scan_args(argc, argv, "01", &n);
06006 if (argc < 1)
06007 n = INT2FIX(1);
06008 return d_lite_plus(self, n);
06009 }
06010
06011
06012
06013
06014
06015
06016
06017 static VALUE
06018 d_lite_prev_day(int argc, VALUE *argv, VALUE self)
06019 {
06020 VALUE n;
06021
06022 rb_scan_args(argc, argv, "01", &n);
06023 if (argc < 1)
06024 n = INT2FIX(1);
06025 return d_lite_minus(self, n);
06026 }
06027
06028
06029
06030
06031
06032
06033
06034 static VALUE
06035 d_lite_next(VALUE self)
06036 {
06037 return d_lite_next_day(0, (VALUE *)NULL, self);
06038 }
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052
06053 static VALUE
06054 d_lite_rshift(VALUE self, VALUE other)
06055 {
06056 VALUE t, y, nth, rjd2;
06057 int m, d, rjd;
06058 double sg;
06059
06060 get_d1(self);
06061 t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)),
06062 INT2FIX(m_mon(dat) - 1),
06063 other);
06064 if (FIXNUM_P(t)) {
06065 long it = FIX2LONG(t);
06066 y = LONG2NUM(DIV(it, 12));
06067 it = MOD(it, 12);
06068 m = (int)it + 1;
06069 }
06070 else {
06071 y = f_idiv(t, INT2FIX(12));
06072 t = f_mod(t, INT2FIX(12));
06073 m = FIX2INT(t) + 1;
06074 }
06075 d = m_mday(dat);
06076 sg = m_sg(dat);
06077
06078 while (1) {
06079 int ry, rm, rd, ns;
06080
06081 if (valid_civil_p(y, m, d, sg,
06082 &nth, &ry,
06083 &rm, &rd, &rjd, &ns))
06084 break;
06085 if (--d < 1)
06086 rb_raise(rb_eArgError, "invalid date");
06087 }
06088 encode_jd(nth, rjd, &rjd2);
06089 return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat)));
06090 }
06091
06092
06093
06094
06095
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105 static VALUE
06106 d_lite_lshift(VALUE self, VALUE other)
06107 {
06108 return d_lite_rshift(self, f_negate(other));
06109 }
06110
06111
06112
06113
06114
06115
06116
06117 static VALUE
06118 d_lite_next_month(int argc, VALUE *argv, VALUE self)
06119 {
06120 VALUE n;
06121
06122 rb_scan_args(argc, argv, "01", &n);
06123 if (argc < 1)
06124 n = INT2FIX(1);
06125 return d_lite_rshift(self, n);
06126 }
06127
06128
06129
06130
06131
06132
06133
06134 static VALUE
06135 d_lite_prev_month(int argc, VALUE *argv, VALUE self)
06136 {
06137 VALUE n;
06138
06139 rb_scan_args(argc, argv, "01", &n);
06140 if (argc < 1)
06141 n = INT2FIX(1);
06142 return d_lite_lshift(self, n);
06143 }
06144
06145
06146
06147
06148
06149
06150
06151 static VALUE
06152 d_lite_next_year(int argc, VALUE *argv, VALUE self)
06153 {
06154 VALUE n;
06155
06156 rb_scan_args(argc, argv, "01", &n);
06157 if (argc < 1)
06158 n = INT2FIX(1);
06159 return d_lite_rshift(self, f_mul(n, INT2FIX(12)));
06160 }
06161
06162
06163
06164
06165
06166
06167
06168 static VALUE
06169 d_lite_prev_year(int argc, VALUE *argv, VALUE self)
06170 {
06171 VALUE n;
06172
06173 rb_scan_args(argc, argv, "01", &n);
06174 if (argc < 1)
06175 n = INT2FIX(1);
06176 return d_lite_lshift(self, f_mul(n, INT2FIX(12)));
06177 }
06178
06179 static VALUE d_lite_cmp(VALUE, VALUE);
06180
06181
06182
06183
06184
06185
06186
06187
06188
06189
06190
06191
06192
06193
06194 static VALUE
06195 d_lite_step(int argc, VALUE *argv, VALUE self)
06196 {
06197 VALUE limit, step, date;
06198
06199 rb_scan_args(argc, argv, "11", &limit, &step);
06200
06201 if (argc < 2)
06202 step = INT2FIX(1);
06203
06204 #if 0
06205 if (f_zero_p(step))
06206 rb_raise(rb_eArgError, "step can't be 0");
06207 #endif
06208
06209 RETURN_ENUMERATOR(self, argc, argv);
06210
06211 date = self;
06212 switch (FIX2INT(f_cmp(step, INT2FIX(0)))) {
06213 case -1:
06214 while (FIX2INT(d_lite_cmp(date, limit)) >= 0) {
06215 rb_yield(date);
06216 date = d_lite_plus(date, step);
06217 }
06218 break;
06219 case 0:
06220 while (1)
06221 rb_yield(date);
06222 break;
06223 case 1:
06224 while (FIX2INT(d_lite_cmp(date, limit)) <= 0) {
06225 rb_yield(date);
06226 date = d_lite_plus(date, step);
06227 }
06228 break;
06229 default:
06230 abort();
06231 }
06232 return self;
06233 }
06234
06235
06236
06237
06238
06239
06240
06241
06242 static VALUE
06243 d_lite_upto(VALUE self, VALUE max)
06244 {
06245 VALUE date;
06246
06247 RETURN_ENUMERATOR(self, 1, &max);
06248
06249 date = self;
06250 while (FIX2INT(d_lite_cmp(date, max)) <= 0) {
06251 rb_yield(date);
06252 date = d_lite_plus(date, INT2FIX(1));
06253 }
06254 return self;
06255 }
06256
06257
06258
06259
06260
06261
06262
06263
06264 static VALUE
06265 d_lite_downto(VALUE self, VALUE min)
06266 {
06267 VALUE date;
06268
06269 RETURN_ENUMERATOR(self, 1, &min);
06270
06271 date = self;
06272 while (FIX2INT(d_lite_cmp(date, min)) >= 0) {
06273 rb_yield(date);
06274 date = d_lite_plus(date, INT2FIX(-1));
06275 }
06276 return self;
06277 }
06278
06279 static VALUE
06280 cmp_gen(VALUE self, VALUE other)
06281 {
06282 get_d1(self);
06283
06284 if (k_numeric_p(other))
06285 return f_cmp(m_ajd(dat), other);
06286 else if (k_date_p(other))
06287 return f_cmp(m_ajd(dat), f_ajd(other));
06288 return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
06289 }
06290
06291 static VALUE
06292 cmp_dd(VALUE self, VALUE other)
06293 {
06294 get_d2(self, other);
06295
06296 {
06297 VALUE a_nth, b_nth,
06298 a_sf, b_sf;
06299 int a_jd, b_jd,
06300 a_df, b_df;
06301
06302 a_nth = m_nth(adat);
06303 b_nth = m_nth(bdat);
06304 if (f_eqeq_p(a_nth, b_nth)) {
06305 a_jd = m_jd(adat);
06306 b_jd = m_jd(bdat);
06307 if (a_jd == b_jd) {
06308 a_df = m_df(adat);
06309 b_df = m_df(bdat);
06310 if (a_df == b_df) {
06311 a_sf = m_sf(adat);
06312 b_sf = m_sf(bdat);
06313 if (f_eqeq_p(a_sf, b_sf)) {
06314 return INT2FIX(0);
06315 }
06316 else if (f_lt_p(a_sf, b_sf)) {
06317 return INT2FIX(-1);
06318 }
06319 else {
06320 return INT2FIX(1);
06321 }
06322 }
06323 else if (a_df < b_df) {
06324 return INT2FIX(-1);
06325 }
06326 else {
06327 return INT2FIX(1);
06328 }
06329 }
06330 else if (a_jd < b_jd) {
06331 return INT2FIX(-1);
06332 }
06333 else {
06334 return INT2FIX(1);
06335 }
06336 }
06337 else if (f_lt_p(a_nth, b_nth)) {
06338 return INT2FIX(-1);
06339 }
06340 else {
06341 return INT2FIX(1);
06342 }
06343 }
06344 }
06345
06346
06347
06348
06349
06350
06351
06352
06353
06354
06355
06356
06357
06358
06359
06360
06361
06362
06363
06364 static VALUE
06365 d_lite_cmp(VALUE self, VALUE other)
06366 {
06367 if (!k_date_p(other))
06368 return cmp_gen(self, other);
06369
06370 {
06371 get_d2(self, other);
06372
06373 if (!(simple_dat_p(adat) && simple_dat_p(bdat) &&
06374 m_gregorian_p(adat) == m_gregorian_p(bdat)))
06375 return cmp_dd(self, other);
06376
06377 if (have_jd_p(adat) &&
06378 have_jd_p(bdat)) {
06379 VALUE a_nth, b_nth;
06380 int a_jd, b_jd;
06381
06382 a_nth = m_nth(adat);
06383 b_nth = m_nth(bdat);
06384 if (f_eqeq_p(a_nth, b_nth)) {
06385 a_jd = m_jd(adat);
06386 b_jd = m_jd(bdat);
06387 if (a_jd == b_jd) {
06388 return INT2FIX(0);
06389 }
06390 else if (a_jd < b_jd) {
06391 return INT2FIX(-1);
06392 }
06393 else {
06394 return INT2FIX(1);
06395 }
06396 }
06397 else if (a_nth < b_nth) {
06398 return INT2FIX(-1);
06399 }
06400 else {
06401 return INT2FIX(1);
06402 }
06403 }
06404 else {
06405 #ifndef USE_PACK
06406 VALUE a_nth, b_nth;
06407 int a_year, b_year,
06408 a_mon, b_mon,
06409 a_mday, b_mday;
06410 #else
06411 VALUE a_nth, b_nth;
06412 int a_year, b_year,
06413 a_pd, b_pd;
06414 #endif
06415
06416 a_nth = m_nth(adat);
06417 b_nth = m_nth(bdat);
06418 if (f_eqeq_p(a_nth, b_nth)) {
06419 a_year = m_year(adat);
06420 b_year = m_year(bdat);
06421 if (a_year == b_year) {
06422 #ifndef USE_PACK
06423 a_mon = m_mon(adat);
06424 b_mon = m_mon(bdat);
06425 if (a_mon == b_mon) {
06426 a_mday = m_mday(adat);
06427 b_mday = m_mday(bdat);
06428 if (a_mday == b_mday) {
06429 return INT2FIX(0);
06430 }
06431 else if (a_mday < b_mday) {
06432 return INT2FIX(-1);
06433 }
06434 else {
06435 return INT2FIX(1);
06436 }
06437 }
06438 else if (a_mon < b_mon) {
06439 return INT2FIX(-1);
06440 }
06441 else {
06442 return INT2FIX(1);
06443 }
06444 #else
06445 a_pd = m_pc(adat);
06446 b_pd = m_pc(bdat);
06447 if (a_pd == b_pd) {
06448 return INT2FIX(0);
06449 }
06450 else if (a_pd < b_pd) {
06451 return INT2FIX(-1);
06452 }
06453 else {
06454 return INT2FIX(1);
06455 }
06456 #endif
06457 }
06458 else if (a_year < b_year) {
06459 return INT2FIX(-1);
06460 }
06461 else {
06462 return INT2FIX(1);
06463 }
06464 }
06465 else if (f_lt_p(a_nth, b_nth)) {
06466 return INT2FIX(-1);
06467 }
06468 else {
06469 return INT2FIX(1);
06470 }
06471 }
06472 }
06473 }
06474
06475 static VALUE
06476 equal_gen(VALUE self, VALUE other)
06477 {
06478 get_d1(self);
06479
06480 if (k_numeric_p(other))
06481 return f_eqeq_p(m_real_local_jd(dat), other);
06482 else if (k_date_p(other))
06483 return f_eqeq_p(m_real_local_jd(dat), f_jd(other));
06484 return rb_num_coerce_cmp(self, other, rb_intern("=="));
06485 }
06486
06487
06488
06489
06490
06491
06492
06493
06494
06495
06496
06497
06498
06499
06500
06501
06502
06503
06504
06505
06506 static VALUE
06507 d_lite_equal(VALUE self, VALUE other)
06508 {
06509 if (!k_date_p(other))
06510 return equal_gen(self, other);
06511
06512 {
06513 get_d2(self, other);
06514
06515 if (!(m_gregorian_p(adat) == m_gregorian_p(bdat)))
06516 return equal_gen(self, other);
06517
06518 if (have_jd_p(adat) &&
06519 have_jd_p(bdat)) {
06520 VALUE a_nth, b_nth;
06521 int a_jd, b_jd;
06522
06523 a_nth = m_nth(adat);
06524 b_nth = m_nth(bdat);
06525 a_jd = m_local_jd(adat);
06526 b_jd = m_local_jd(bdat);
06527 if (f_eqeq_p(a_nth, b_nth) &&
06528 a_jd == b_jd)
06529 return Qtrue;
06530 return Qfalse;
06531 }
06532 else {
06533 #ifndef USE_PACK
06534 VALUE a_nth, b_nth;
06535 int a_year, b_year,
06536 a_mon, b_mon,
06537 a_mday, b_mday;
06538 #else
06539 VALUE a_nth, b_nth;
06540 int a_year, b_year,
06541 a_pd, b_pd;
06542 #endif
06543
06544 a_nth = m_nth(adat);
06545 b_nth = m_nth(bdat);
06546 if (f_eqeq_p(a_nth, b_nth)) {
06547 a_year = m_year(adat);
06548 b_year = m_year(bdat);
06549 if (a_year == b_year) {
06550 #ifndef USE_PACK
06551 a_mon = m_mon(adat);
06552 b_mon = m_mon(bdat);
06553 if (a_mon == b_mon) {
06554 a_mday = m_mday(adat);
06555 b_mday = m_mday(bdat);
06556 if (a_mday == b_mday)
06557 return Qtrue;
06558 }
06559 #else
06560
06561 a_pd = (m_pc(adat) >> MDAY_SHIFT);
06562 b_pd = (m_pc(bdat) >> MDAY_SHIFT);
06563 if (a_pd == b_pd) {
06564 return Qtrue;
06565 }
06566 #endif
06567 }
06568 }
06569 return Qfalse;
06570 }
06571 }
06572 }
06573
06574
06575 static VALUE
06576 d_lite_eql_p(VALUE self, VALUE other)
06577 {
06578 if (!k_date_p(other))
06579 return Qfalse;
06580 return f_zero_p(d_lite_cmp(self, other));
06581 }
06582
06583
06584 static VALUE
06585 d_lite_hash(VALUE self)
06586 {
06587 st_index_t v, h[4];
06588
06589 get_d1(self);
06590 h[0] = m_nth(dat);
06591 h[1] = m_jd(dat);
06592 h[2] = m_df(dat);
06593 h[3] = m_sf(dat);
06594 v = rb_memhash(h, sizeof(h));
06595 return LONG2FIX(v);
06596 }
06597
06598 #include "date_tmx.h"
06599 static void set_tmx(VALUE, struct tmx *);
06600 static VALUE strftimev(const char *, VALUE,
06601 void (*)(VALUE, struct tmx *));
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614 static VALUE
06615 d_lite_to_s(VALUE self)
06616 {
06617 return strftimev("%Y-%m-%d", self, set_tmx);
06618 }
06619
06620 #ifndef NDEBUG
06621 static VALUE
06622 mk_inspect_flags(union DateData *x)
06623 {
06624 return rb_enc_sprintf(rb_usascii_encoding(),
06625 "%c%c%c%c%c",
06626 (x->flags & COMPLEX_DAT) ? 'C' : 'S',
06627 (x->flags & HAVE_JD) ? 'j' : '-',
06628 (x->flags & HAVE_DF) ? 'd' : '-',
06629 (x->flags & HAVE_CIVIL) ? 'c' : '-',
06630 (x->flags & HAVE_TIME) ? 't' : '-');
06631 }
06632
06633 static VALUE
06634 mk_inspect_raw(union DateData *x, const char *klass)
06635 {
06636 if (simple_dat_p(x)) {
06637 VALUE nth, flags;
06638
06639 RB_GC_GUARD(nth) = f_inspect(x->s.nth);
06640 RB_GC_GUARD(flags) = mk_inspect_flags(x);
06641
06642 return rb_enc_sprintf(rb_usascii_encoding(),
06643 "#<%s: "
06644 "(%sth,%dj),+0s,%.0fj; "
06645 "%dy%dm%dd; %s>",
06646 klass ? klass : "?",
06647 RSTRING_PTR(nth), x->s.jd, x->s.sg,
06648 #ifndef USE_PACK
06649 x->s.year, x->s.mon, x->s.mday,
06650 #else
06651 x->s.year,
06652 EX_MON(x->s.pc), EX_MDAY(x->s.pc),
06653 #endif
06654 RSTRING_PTR(flags));
06655 }
06656 else {
06657 VALUE nth, sf, flags;
06658
06659 RB_GC_GUARD(nth) = f_inspect(x->c.nth);
06660 RB_GC_GUARD(sf) = f_inspect(x->c.sf);
06661 RB_GC_GUARD(flags) = mk_inspect_flags(x);
06662
06663 return rb_enc_sprintf(rb_usascii_encoding(),
06664 "#<%s: "
06665 "(%sth,%dj,%ds,%sn),%+ds,%.0fj; "
06666 "%dy%dm%dd %dh%dm%ds; %s>",
06667 klass ? klass : "?",
06668 RSTRING_PTR(nth), x->c.jd, x->c.df,
06669 RSTRING_PTR(sf),
06670 x->c.of, x->c.sg,
06671 #ifndef USE_PACK
06672 x->c.year, x->c.mon, x->c.mday,
06673 x->c.hour, x->c.min, x->c.sec,
06674 #else
06675 x->c.year,
06676 EX_MON(x->c.pc), EX_MDAY(x->c.pc),
06677 EX_HOUR(x->c.pc), EX_MIN(x->c.pc),
06678 EX_SEC(x->c.pc),
06679 #endif
06680 RSTRING_PTR(flags));
06681 }
06682 }
06683
06684 static VALUE
06685 d_lite_inspect_raw(VALUE self)
06686 {
06687 get_d1(self);
06688 return mk_inspect_raw(dat, rb_obj_classname(self));
06689 }
06690 #endif
06691
06692 static VALUE
06693 mk_inspect(union DateData *x, const char *klass, const char *to_s)
06694 {
06695 VALUE jd, sf;
06696
06697 RB_GC_GUARD(jd) = f_inspect(m_real_jd(x));
06698 RB_GC_GUARD(sf) = f_inspect(m_sf(x));
06699
06700 return rb_enc_sprintf(rb_usascii_encoding(),
06701 "#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>",
06702 klass ? klass : "?",
06703 to_s ? to_s : "?",
06704 RSTRING_PTR(jd), m_df(x), RSTRING_PTR(sf),
06705 m_of(x), m_sg(x));
06706 }
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
06722 static VALUE
06723 d_lite_inspect(VALUE self)
06724 {
06725 get_d1(self);
06726 {
06727 VALUE to_s;
06728
06729 RB_GC_GUARD(to_s) = f_to_s(self);
06730 return mk_inspect(dat, rb_obj_classname(self), RSTRING_PTR(to_s));
06731 }
06732 }
06733
06734 #include <errno.h>
06735 #include "date_tmx.h"
06736
06737 size_t date_strftime(char *s, size_t maxsize, const char *format,
06738 const struct tmx *tmx);
06739
06740 #define SMALLBUF 100
06741 static size_t
06742 date_strftime_alloc(char **buf, const char *format,
06743 struct tmx *tmx)
06744 {
06745 size_t size, len, flen;
06746
06747 (*buf)[0] = '\0';
06748 flen = strlen(format);
06749 if (flen == 0) {
06750 return 0;
06751 }
06752 errno = 0;
06753 len = date_strftime(*buf, SMALLBUF, format, tmx);
06754 if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
06755 for (size=1024; ; size*=2) {
06756 *buf = xmalloc(size);
06757 (*buf)[0] = '\0';
06758 len = date_strftime(*buf, size, format, tmx);
06759
06760
06761
06762
06763
06764
06765
06766 if (len > 0) break;
06767 xfree(*buf);
06768 if (size >= 1024 * flen) {
06769 rb_sys_fail(format);
06770 break;
06771 }
06772 }
06773 return len;
06774 }
06775
06776 static VALUE
06777 tmx_m_secs(union DateData *x)
06778 {
06779 VALUE s;
06780 int df;
06781
06782 s = day_to_sec(f_sub(m_real_jd(x),
06783 UNIX_EPOCH_IN_CJD));
06784 if (simple_dat_p(x))
06785 return s;
06786 df = m_df(x);
06787 if (df)
06788 s = f_add(s, INT2FIX(df));
06789 return s;
06790 }
06791
06792 #define MILLISECOND_IN_NANOSECONDS 1000000
06793
06794 static VALUE
06795 tmx_m_msecs(union DateData *x)
06796 {
06797 VALUE s, sf;
06798
06799 s = sec_to_ms(tmx_m_secs(x));
06800 if (simple_dat_p(x))
06801 return s;
06802 sf = m_sf(x);
06803 if (f_nonzero_p(sf))
06804 s = f_add(s, f_div(sf, INT2FIX(MILLISECOND_IN_NANOSECONDS)));
06805 return s;
06806 }
06807
06808 static VALUE
06809 tmx_m_of(union DateData *x)
06810 {
06811 return INT2FIX(m_of(x));
06812 }
06813
06814 static char *
06815 tmx_m_zone(union DateData *x)
06816 {
06817 return RSTRING_PTR(m_zone(x));
06818 }
06819
06820 static struct tmx_funcs tmx_funcs = {
06821 (VALUE (*)(void *))m_real_year,
06822 (int (*)(void *))m_yday,
06823 (int (*)(void *))m_mon,
06824 (int (*)(void *))m_mday,
06825 (VALUE (*)(void *))m_real_cwyear,
06826 (int (*)(void *))m_cweek,
06827 (int (*)(void *))m_cwday,
06828 (int (*)(void *))m_wnum0,
06829 (int (*)(void *))m_wnum1,
06830 (int (*)(void *))m_wday,
06831 (int (*)(void *))m_hour,
06832 (int (*)(void *))m_min,
06833 (int (*)(void *))m_sec,
06834 (VALUE (*)(void *))m_sf_in_sec,
06835 (VALUE (*)(void *))tmx_m_secs,
06836 (VALUE (*)(void *))tmx_m_msecs,
06837 (VALUE (*)(void *))tmx_m_of,
06838 (char *(*)(void *))tmx_m_zone
06839 };
06840
06841 static void
06842 set_tmx(VALUE self, struct tmx *tmx)
06843 {
06844 get_d1(self);
06845 tmx->dat = (void *)dat;
06846 tmx->funcs = &tmx_funcs;
06847 }
06848
06849 static VALUE
06850 date_strftime_internal(int argc, VALUE *argv, VALUE self,
06851 const char *default_fmt,
06852 void (*func)(VALUE, struct tmx *))
06853 {
06854 VALUE vfmt;
06855 const char *fmt;
06856 long len;
06857 char buffer[SMALLBUF], *buf = buffer;
06858 struct tmx tmx;
06859 VALUE str;
06860
06861 rb_scan_args(argc, argv, "01", &vfmt);
06862
06863 if (argc < 1)
06864 vfmt = rb_usascii_str_new2(default_fmt);
06865 else {
06866 StringValue(vfmt);
06867 if (!rb_enc_str_asciicompat_p(vfmt)) {
06868 rb_raise(rb_eArgError,
06869 "format should have ASCII compatible encoding");
06870 }
06871 }
06872 fmt = RSTRING_PTR(vfmt);
06873 len = RSTRING_LEN(vfmt);
06874 (*func)(self, &tmx);
06875 if (memchr(fmt, '\0', len)) {
06876
06877 const char *p = fmt, *pe = fmt + len;
06878
06879 str = rb_str_new(0, 0);
06880 while (p < pe) {
06881 len = date_strftime_alloc(&buf, p, &tmx);
06882 rb_str_cat(str, buf, len);
06883 p += strlen(p);
06884 if (buf != buffer) {
06885 xfree(buf);
06886 buf = buffer;
06887 }
06888 for (fmt = p; p < pe && !*p; ++p);
06889 if (p > fmt) rb_str_cat(str, fmt, p - fmt);
06890 }
06891 rb_enc_copy(str, vfmt);
06892 OBJ_INFECT(str, vfmt);
06893 return str;
06894 }
06895 else
06896 len = date_strftime_alloc(&buf, fmt, &tmx);
06897
06898 str = rb_str_new(buf, len);
06899 if (buf != buffer) xfree(buf);
06900 rb_enc_copy(str, vfmt);
06901 OBJ_INFECT(str, vfmt);
06902 return str;
06903 }
06904
06905
06906
06907
06908
06909
06910
06911
06912
06913
06914
06915
06916
06917
06918
06919
06920
06921
06922
06923
06924
06925
06926
06927
06928
06929
06930
06931
06932
06933
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960
06961
06962
06963
06964
06965
06966
06967
06968
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978
06979
06980
06981
06982
06983
06984
06985
06986
06987
06988
06989
06990
06991
06992
06993
06994
06995
06996
06997
06998
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017
07018
07019
07020
07021
07022
07023
07024
07025
07026
07027
07028
07029
07030
07031
07032
07033
07034
07035
07036
07037
07038
07039
07040
07041
07042
07043
07044
07045
07046
07047
07048
07049
07050
07051
07052
07053
07054
07055
07056
07057
07058
07059
07060
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082 static VALUE
07083 d_lite_strftime(int argc, VALUE *argv, VALUE self)
07084 {
07085 return date_strftime_internal(argc, argv, self,
07086 "%Y-%m-%d", set_tmx);
07087 }
07088
07089 static VALUE
07090 strftimev(const char *fmt, VALUE self,
07091 void (*func)(VALUE, struct tmx *))
07092 {
07093 char buffer[SMALLBUF], *buf = buffer;
07094 struct tmx tmx;
07095 long len;
07096 VALUE str;
07097
07098 (*func)(self, &tmx);
07099 len = date_strftime_alloc(&buf, fmt, &tmx);
07100 str = rb_usascii_str_new(buf, len);
07101 if (buf != buffer) xfree(buf);
07102 return str;
07103 }
07104
07105
07106
07107
07108
07109
07110
07111
07112
07113
07114
07115 static VALUE
07116 d_lite_asctime(VALUE self)
07117 {
07118 return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx);
07119 }
07120
07121
07122
07123
07124
07125
07126
07127
07128 static VALUE
07129 d_lite_iso8601(VALUE self)
07130 {
07131 return strftimev("%Y-%m-%d", self, set_tmx);
07132 }
07133
07134
07135
07136
07137
07138
07139
07140 static VALUE
07141 d_lite_rfc3339(VALUE self)
07142 {
07143 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
07144 }
07145
07146
07147
07148
07149
07150
07151
07152
07153 static VALUE
07154 d_lite_rfc2822(VALUE self)
07155 {
07156 return strftimev("%a, %-d %b %Y %T %z", self, set_tmx);
07157 }
07158
07159
07160
07161
07162
07163
07164
07165
07166 static VALUE
07167 d_lite_httpdate(VALUE self)
07168 {
07169 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
07170 return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx);
07171 }
07172
07173 static VALUE
07174 jisx0301_date(VALUE jd, VALUE y)
07175 {
07176 VALUE a[2];
07177
07178 if (f_lt_p(jd, INT2FIX(2405160)))
07179 return rb_usascii_str_new2("%Y-%m-%d");
07180 if (f_lt_p(jd, INT2FIX(2419614))) {
07181 a[0] = rb_usascii_str_new2("M%02d" ".%%m.%%d");
07182 a[1] = f_sub(y, INT2FIX(1867));
07183 }
07184 else if (f_lt_p(jd, INT2FIX(2424875))) {
07185 a[0] = rb_usascii_str_new2("T%02d" ".%%m.%%d");
07186 a[1] = f_sub(y, INT2FIX(1911));
07187 }
07188 else if (f_lt_p(jd, INT2FIX(2447535))) {
07189 a[0] = rb_usascii_str_new2("S%02d" ".%%m.%%d");
07190 a[1] = f_sub(y, INT2FIX(1925));
07191 }
07192 else {
07193 a[0] = rb_usascii_str_new2("H%02d" ".%%m.%%d");
07194 a[1] = f_sub(y, INT2FIX(1988));
07195 }
07196 return rb_f_sprintf(2, a);
07197 }
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209 static VALUE
07210 d_lite_jisx0301(VALUE self)
07211 {
07212 VALUE s;
07213
07214 get_d1(self);
07215 s = jisx0301_date(m_real_local_jd(dat),
07216 m_real_year(dat));
07217 return strftimev(RSTRING_PTR(s), self, set_tmx);
07218 }
07219
07220 #ifndef NDEBUG
07221 static VALUE
07222 d_lite_marshal_dump_old(VALUE self)
07223 {
07224 VALUE a;
07225
07226 get_d1(self);
07227
07228 a = rb_ary_new3(3,
07229 m_ajd(dat),
07230 m_of_in_day(dat),
07231 DBL2NUM(m_sg(dat)));
07232
07233 if (FL_TEST(self, FL_EXIVAR)) {
07234 rb_copy_generic_ivar(a, self);
07235 FL_SET(a, FL_EXIVAR);
07236 }
07237
07238 return a;
07239 }
07240 #endif
07241
07242
07243 static VALUE
07244 d_lite_marshal_dump(VALUE self)
07245 {
07246 VALUE a;
07247
07248 get_d1(self);
07249
07250 a = rb_ary_new3(6,
07251 m_nth(dat),
07252 INT2FIX(m_jd(dat)),
07253 INT2FIX(m_df(dat)),
07254 m_sf(dat),
07255 INT2FIX(m_of(dat)),
07256 DBL2NUM(m_sg(dat)));
07257
07258 if (FL_TEST(self, FL_EXIVAR)) {
07259 rb_copy_generic_ivar(a, self);
07260 FL_SET(a, FL_EXIVAR);
07261 }
07262
07263 return a;
07264 }
07265
07266
07267 static VALUE
07268 d_lite_marshal_load(VALUE self, VALUE a)
07269 {
07270 get_d1(self);
07271
07272 if (TYPE(a) != T_ARRAY)
07273 rb_raise(rb_eTypeError, "expected an array");
07274
07275 switch (RARRAY_LEN(a)) {
07276 case 3:
07277 {
07278 VALUE ajd, of, sg, nth, sf;
07279 int jd, df, rof;
07280 double rsg;
07281
07282 ajd = RARRAY_PTR(a)[0];
07283 of = RARRAY_PTR(a)[1];
07284 sg = RARRAY_PTR(a)[2];
07285
07286 old_to_new(ajd, of, sg,
07287 &nth, &jd, &df, &sf, &rof, &rsg);
07288
07289 if (!df && f_zero_p(sf) && !rof) {
07290 set_to_simple(&dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD);
07291 } else {
07292 if (!complex_dat_p(dat))
07293 rb_raise(rb_eArgError,
07294 "cannot load complex into simple");
07295
07296 set_to_complex(&dat->c, nth, jd, df, sf, rof, rsg,
07297 0, 0, 0, 0, 0, 0,
07298 HAVE_JD | HAVE_DF | COMPLEX_DAT);
07299 }
07300 }
07301 break;
07302 case 6:
07303 {
07304 VALUE nth, sf;
07305 int jd, df, of;
07306 double sg;
07307
07308 nth = RARRAY_PTR(a)[0];
07309 jd = NUM2INT(RARRAY_PTR(a)[1]);
07310 df = NUM2INT(RARRAY_PTR(a)[2]);
07311 sf = RARRAY_PTR(a)[3];
07312 of = NUM2INT(RARRAY_PTR(a)[4]);
07313 sg = NUM2DBL(RARRAY_PTR(a)[5]);
07314 if (!df && f_zero_p(sf) && !of) {
07315 set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
07316 } else {
07317 if (!complex_dat_p(dat))
07318 rb_raise(rb_eArgError,
07319 "cannot load complex into simple");
07320
07321 set_to_complex(&dat->c, nth, jd, df, sf, of, sg,
07322 0, 0, 0, 0, 0, 0,
07323 HAVE_JD | HAVE_DF | COMPLEX_DAT);
07324 }
07325 }
07326 break;
07327 default:
07328 rb_raise(rb_eTypeError, "invalid size");
07329 break;
07330 }
07331
07332 if (FL_TEST(a, FL_EXIVAR)) {
07333 rb_copy_generic_ivar(self, a);
07334 FL_SET(self, FL_EXIVAR);
07335 }
07336
07337 return self;
07338 }
07339
07340
07341
07342
07343
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357 static VALUE
07358 datetime_s_jd(int argc, VALUE *argv, VALUE klass)
07359 {
07360 VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
07361 int h, min, s, rof;
07362 double sg;
07363
07364 rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
07365
07366 jd = INT2FIX(0);
07367
07368 h = min = s = 0;
07369 fr2 = INT2FIX(0);
07370 rof = 0;
07371 sg = DEFAULT_SG;
07372
07373 switch (argc) {
07374 case 6:
07375 val2sg(vsg, sg);
07376 case 5:
07377 val2off(vof, rof);
07378 case 4:
07379 num2int_with_frac(s, positive_inf);
07380 case 3:
07381 num2int_with_frac(min, 3);
07382 case 2:
07383 num2int_with_frac(h, 2);
07384 case 1:
07385 num2num_with_frac(jd, 1);
07386 }
07387
07388 {
07389 VALUE nth;
07390 int rh, rmin, rs, rjd, rjd2;
07391
07392 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07393 rb_raise(rb_eArgError, "invalid date");
07394 canon24oc();
07395
07396 decode_jd(jd, &nth, &rjd);
07397 rjd2 = jd_local_to_utc(rjd,
07398 time_to_df(rh, rmin, rs),
07399 rof);
07400
07401 ret = d_complex_new_internal(klass,
07402 nth, rjd2,
07403 0, INT2FIX(0),
07404 rof, sg,
07405 0, 0, 0,
07406 rh, rmin, rs,
07407 HAVE_JD | HAVE_TIME);
07408 }
07409 add_frac();
07410 return ret;
07411 }
07412
07413
07414
07415
07416
07417
07418
07419
07420
07421
07422
07423
07424
07425
07426
07427 static VALUE
07428 datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
07429 {
07430 VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07431 int d, h, min, s, rof;
07432 double sg;
07433
07434 rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
07435
07436 y = INT2FIX(-4712);
07437 d = 1;
07438
07439 h = min = s = 0;
07440 fr2 = INT2FIX(0);
07441 rof = 0;
07442 sg = DEFAULT_SG;
07443
07444 switch (argc) {
07445 case 7:
07446 val2sg(vsg, sg);
07447 case 6:
07448 val2off(vof, rof);
07449 case 5:
07450 num2int_with_frac(s, positive_inf);
07451 case 4:
07452 num2int_with_frac(min, 4);
07453 case 3:
07454 num2int_with_frac(h, 3);
07455 case 2:
07456 num2int_with_frac(d, 2);
07457 case 1:
07458 y = vy;
07459 }
07460
07461 {
07462 VALUE nth;
07463 int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
07464
07465 if (!valid_ordinal_p(y, d, sg,
07466 &nth, &ry,
07467 &rd, &rjd,
07468 &ns))
07469 rb_raise(rb_eArgError, "invalid date");
07470 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07471 rb_raise(rb_eArgError, "invalid date");
07472 canon24oc();
07473
07474 rjd2 = jd_local_to_utc(rjd,
07475 time_to_df(rh, rmin, rs),
07476 rof);
07477
07478 ret = d_complex_new_internal(klass,
07479 nth, rjd2,
07480 0, INT2FIX(0),
07481 rof, sg,
07482 0, 0, 0,
07483 rh, rmin, rs,
07484 HAVE_JD | HAVE_TIME);
07485 }
07486 add_frac();
07487 return ret;
07488 }
07489
07490
07491
07492
07493
07494
07495
07496
07497
07498
07499
07500
07501
07502
07503
07504
07505 static VALUE
07506 datetime_s_civil(int argc, VALUE *argv, VALUE klass)
07507 {
07508 VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07509 int m, d, h, min, s, rof;
07510 double sg;
07511
07512 rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
07513
07514 y = INT2FIX(-4712);
07515 m = 1;
07516 d = 1;
07517
07518 h = min = s = 0;
07519 fr2 = INT2FIX(0);
07520 rof = 0;
07521 sg = DEFAULT_SG;
07522
07523 switch (argc) {
07524 case 8:
07525 val2sg(vsg, sg);
07526 case 7:
07527 val2off(vof, rof);
07528 case 6:
07529 num2int_with_frac(s, positive_inf);
07530 case 5:
07531 num2int_with_frac(min, 5);
07532 case 4:
07533 num2int_with_frac(h, 4);
07534 case 3:
07535 num2int_with_frac(d, 3);
07536 case 2:
07537 m = NUM2INT(vm);
07538 case 1:
07539 y = vy;
07540 }
07541
07542 if (guess_style(y, sg) < 0) {
07543 VALUE nth;
07544 int ry, rm, rd, rh, rmin, rs;
07545
07546 if (!valid_gregorian_p(y, m, d,
07547 &nth, &ry,
07548 &rm, &rd))
07549 rb_raise(rb_eArgError, "invalid date");
07550 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07551 rb_raise(rb_eArgError, "invalid date");
07552 canon24oc();
07553
07554 ret = d_complex_new_internal(klass,
07555 nth, 0,
07556 0, INT2FIX(0),
07557 rof, sg,
07558 ry, rm, rd,
07559 rh, rmin, rs,
07560 HAVE_CIVIL | HAVE_TIME);
07561 }
07562 else {
07563 VALUE nth;
07564 int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns;
07565
07566 if (!valid_civil_p(y, m, d, sg,
07567 &nth, &ry,
07568 &rm, &rd, &rjd,
07569 &ns))
07570 rb_raise(rb_eArgError, "invalid date");
07571 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07572 rb_raise(rb_eArgError, "invalid date");
07573 canon24oc();
07574
07575 rjd2 = jd_local_to_utc(rjd,
07576 time_to_df(rh, rmin, rs),
07577 rof);
07578
07579 ret = d_complex_new_internal(klass,
07580 nth, rjd2,
07581 0, INT2FIX(0),
07582 rof, sg,
07583 ry, rm, rd,
07584 rh, rmin, rs,
07585 HAVE_JD | HAVE_CIVIL | HAVE_TIME);
07586 }
07587 add_frac();
07588 return ret;
07589 }
07590
07591
07592
07593
07594
07595
07596
07597
07598
07599
07600
07601
07602
07603
07604 static VALUE
07605 datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
07606 {
07607 VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07608 int w, d, h, min, s, rof;
07609 double sg;
07610
07611 rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
07612
07613 y = INT2FIX(-4712);
07614 w = 1;
07615 d = 1;
07616
07617 h = min = s = 0;
07618 fr2 = INT2FIX(0);
07619 rof = 0;
07620 sg = DEFAULT_SG;
07621
07622 switch (argc) {
07623 case 8:
07624 val2sg(vsg, sg);
07625 case 7:
07626 val2off(vof, rof);
07627 case 6:
07628 num2int_with_frac(s, positive_inf);
07629 case 5:
07630 num2int_with_frac(min, 5);
07631 case 4:
07632 num2int_with_frac(h, 4);
07633 case 3:
07634 num2int_with_frac(d, 3);
07635 case 2:
07636 w = NUM2INT(vw);
07637 case 1:
07638 y = vy;
07639 }
07640
07641 {
07642 VALUE nth;
07643 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
07644
07645 if (!valid_commercial_p(y, w, d, sg,
07646 &nth, &ry,
07647 &rw, &rd, &rjd,
07648 &ns))
07649 rb_raise(rb_eArgError, "invalid date");
07650 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07651 rb_raise(rb_eArgError, "invalid date");
07652 canon24oc();
07653
07654 rjd2 = jd_local_to_utc(rjd,
07655 time_to_df(rh, rmin, rs),
07656 rof);
07657
07658 ret = d_complex_new_internal(klass,
07659 nth, rjd2,
07660 0, INT2FIX(0),
07661 rof, sg,
07662 0, 0, 0,
07663 rh, rmin, rs,
07664 HAVE_JD | HAVE_TIME);
07665 }
07666 add_frac();
07667 return ret;
07668 }
07669
07670 #ifndef NDEBUG
07671 static VALUE
07672 datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
07673 {
07674 VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07675 int w, d, f, h, min, s, rof;
07676 double sg;
07677
07678 rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
07679 &vh, &vmin, &vs, &vof, &vsg);
07680
07681 y = INT2FIX(-4712);
07682 w = 0;
07683 d = 1;
07684 f = 0;
07685
07686 h = min = s = 0;
07687 fr2 = INT2FIX(0);
07688 rof = 0;
07689 sg = DEFAULT_SG;
07690
07691 switch (argc) {
07692 case 9:
07693 val2sg(vsg, sg);
07694 case 8:
07695 val2off(vof, rof);
07696 case 7:
07697 num2int_with_frac(s, positive_inf);
07698 case 6:
07699 num2int_with_frac(min, 6);
07700 case 5:
07701 num2int_with_frac(h, 5);
07702 case 4:
07703 f = NUM2INT(vf);
07704 case 3:
07705 num2int_with_frac(d, 4);
07706 case 2:
07707 w = NUM2INT(vw);
07708 case 1:
07709 y = vy;
07710 }
07711
07712 {
07713 VALUE nth;
07714 int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
07715
07716 if (!valid_weeknum_p(y, w, d, f, sg,
07717 &nth, &ry,
07718 &rw, &rd, &rjd,
07719 &ns))
07720 rb_raise(rb_eArgError, "invalid date");
07721 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07722 rb_raise(rb_eArgError, "invalid date");
07723 canon24oc();
07724
07725 rjd2 = jd_local_to_utc(rjd,
07726 time_to_df(rh, rmin, rs),
07727 rof);
07728 ret = d_complex_new_internal(klass,
07729 nth, rjd2,
07730 0, INT2FIX(0),
07731 rof, sg,
07732 0, 0, 0,
07733 rh, rmin, rs,
07734 HAVE_JD | HAVE_TIME);
07735 }
07736 add_frac();
07737 return ret;
07738 }
07739
07740 static VALUE
07741 datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
07742 {
07743 VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
07744 int m, n, k, h, min, s, rof;
07745 double sg;
07746
07747 rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
07748 &vh, &vmin, &vs, &vof, &vsg);
07749
07750 y = INT2FIX(-4712);
07751 m = 1;
07752 n = 1;
07753 k = 1;
07754
07755 h = min = s = 0;
07756 fr2 = INT2FIX(0);
07757 rof = 0;
07758 sg = DEFAULT_SG;
07759
07760 switch (argc) {
07761 case 9:
07762 val2sg(vsg, sg);
07763 case 8:
07764 val2off(vof, rof);
07765 case 7:
07766 num2int_with_frac(s, positive_inf);
07767 case 6:
07768 num2int_with_frac(min, 6);
07769 case 5:
07770 num2int_with_frac(h, 5);
07771 case 4:
07772 num2int_with_frac(k, 4);
07773 case 3:
07774 n = NUM2INT(vn);
07775 case 2:
07776 m = NUM2INT(vm);
07777 case 1:
07778 y = vy;
07779 }
07780
07781 {
07782 VALUE nth;
07783 int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns;
07784
07785 if (!valid_nth_kday_p(y, m, n, k, sg,
07786 &nth, &ry,
07787 &rm, &rn, &rk, &rjd,
07788 &ns))
07789 rb_raise(rb_eArgError, "invalid date");
07790 if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
07791 rb_raise(rb_eArgError, "invalid date");
07792 canon24oc();
07793
07794 rjd2 = jd_local_to_utc(rjd,
07795 time_to_df(rh, rmin, rs),
07796 rof);
07797 ret = d_complex_new_internal(klass,
07798 nth, rjd2,
07799 0, INT2FIX(0),
07800 rof, sg,
07801 0, 0, 0,
07802 rh, rmin, rs,
07803 HAVE_JD | HAVE_TIME);
07804 }
07805 add_frac();
07806 return ret;
07807 }
07808 #endif
07809
07810
07811
07812
07813
07814
07815
07816
07817
07818
07819
07820 static VALUE
07821 datetime_s_now(int argc, VALUE *argv, VALUE klass)
07822 {
07823 VALUE vsg, nth, ret;
07824 double sg;
07825 #ifdef HAVE_CLOCK_GETTIME
07826 struct timespec ts;
07827 #else
07828 struct timeval tv;
07829 #endif
07830 time_t sec;
07831 struct tm tm;
07832 long sf, of;
07833 int y, ry, m, d, h, min, s;
07834
07835 rb_scan_args(argc, argv, "01", &vsg);
07836
07837 if (argc < 1)
07838 sg = DEFAULT_SG;
07839 else
07840 sg = NUM2DBL(vsg);
07841
07842 #ifdef HAVE_CLOCK_GETTIME
07843 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
07844 rb_sys_fail("clock_gettime");
07845 sec = ts.tv_sec;
07846 #else
07847 if (gettimeofday(&tv, NULL) == -1)
07848 rb_sys_fail("gettimeofday");
07849 sec = tv.tv_sec;
07850 #endif
07851 tzset();
07852 if (!localtime_r(&sec, &tm))
07853 rb_sys_fail("localtime");
07854
07855 y = tm.tm_year + 1900;
07856 m = tm.tm_mon + 1;
07857 d = tm.tm_mday;
07858 h = tm.tm_hour;
07859 min = tm.tm_min;
07860 s = tm.tm_sec;
07861 if (s == 60)
07862 s = 59;
07863 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
07864 of = tm.tm_gmtoff;
07865 #elif defined(HAVE_VAR_TIMEZONE)
07866 #ifdef HAVE_VAR_ALTZONE
07867 of = (long)((tm.tm_isdst > 0) ? altzone : timezone);
07868 #else
07869 of = (long)-timezone;
07870 if (tm.tm_isdst) {
07871 time_t sec2;
07872
07873 tm.tm_isdst = 0;
07874 sec2 = mktime(&tm);
07875 of += (long)difftime(sec2, sec);
07876 }
07877 #endif
07878 #elif defined(HAVE_TIMEGM)
07879 {
07880 time_t sec2;
07881
07882 sec2 = timegm(&tm);
07883 of = (long)difftime(sec2, sec);
07884 }
07885 #else
07886 {
07887 struct tm tm2;
07888 time_t sec2;
07889
07890 if (!gmtime_r(&sec, &tm2))
07891 rb_sys_fail("gmtime");
07892 tm2.tm_isdst = tm.tm_isdst;
07893 sec2 = mktime(&tm2);
07894 of = (long)difftime(sec, sec2);
07895 }
07896 #endif
07897 #ifdef HAVE_CLOCK_GETTIME
07898 sf = ts.tv_nsec;
07899 #else
07900 sf = tv.tv_usec * 1000;
07901 #endif
07902
07903 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
07904 of = 0;
07905 rb_warning("invalid offset is ignored");
07906 }
07907
07908 decode_year(INT2FIX(y), -1, &nth, &ry);
07909
07910 ret = d_complex_new_internal(klass,
07911 nth, 0,
07912 0, LONG2NUM(sf),
07913 (int)of, GREGORIAN,
07914 ry, m, d,
07915 h, min, s,
07916 HAVE_CIVIL | HAVE_TIME);
07917 {
07918 get_d1(ret);
07919 set_sg(dat, sg);
07920 }
07921 return ret;
07922 }
07923
07924 static VALUE
07925 dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
07926 {
07927 VALUE jd, sf, t;
07928 int df, of;
07929
07930 if (!c_valid_start_p(NUM2DBL(sg))) {
07931 sg = INT2FIX(DEFAULT_SG);
07932 rb_warning("invalid start is ignored");
07933 }
07934
07935 if (NIL_P(hash))
07936 rb_raise(rb_eArgError, "invalid date");
07937
07938 if (NIL_P(ref_hash("jd")) &&
07939 NIL_P(ref_hash("yday")) &&
07940 !NIL_P(ref_hash("year")) &&
07941 !NIL_P(ref_hash("mon")) &&
07942 !NIL_P(ref_hash("mday"))) {
07943 jd = rt__valid_civil_p(ref_hash("year"),
07944 ref_hash("mon"),
07945 ref_hash("mday"), sg);
07946
07947 if (NIL_P(ref_hash("hour")))
07948 set_hash("hour", INT2FIX(0));
07949 if (NIL_P(ref_hash("min")))
07950 set_hash("min", INT2FIX(0));
07951 if (NIL_P(ref_hash("sec")))
07952 set_hash("sec", INT2FIX(0));
07953 else if (f_gt_p(ref_hash("sec"), INT2FIX(59)))
07954 set_hash("sec", INT2FIX(59));
07955 }
07956 else {
07957 hash = rt_rewrite_frags(hash);
07958 hash = rt_complete_frags(klass, hash);
07959 jd = rt__valid_date_frags_p(hash, sg);
07960 }
07961
07962 if (NIL_P(jd))
07963 rb_raise(rb_eArgError, "invalid date");
07964
07965 {
07966 int rh, rmin, rs;
07967
07968 if (!c_valid_time_p(NUM2INT(ref_hash("hour")),
07969 NUM2INT(ref_hash("min")),
07970 NUM2INT(ref_hash("sec")),
07971 &rh, &rmin, &rs))
07972 rb_raise(rb_eArgError, "invalid date");
07973
07974 df = time_to_df(rh, rmin, rs);
07975 }
07976
07977 t = ref_hash("sec_fraction");
07978 if (NIL_P(t))
07979 sf = INT2FIX(0);
07980 else
07981 sf = sec_to_ns(t);
07982
07983 t = ref_hash("offset");
07984 if (NIL_P(t))
07985 of = 0;
07986 else {
07987 of = NUM2INT(t);
07988 if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
07989 of = 0;
07990 rb_warning("invalid offset is ignored");
07991 }
07992 }
07993 {
07994 VALUE nth;
07995 int rjd, rjd2;
07996
07997 decode_jd(jd, &nth, &rjd);
07998 rjd2 = jd_local_to_utc(rjd, df, of);
07999 df = df_local_to_utc(df, of);
08000
08001 return d_complex_new_internal(klass,
08002 nth, rjd2,
08003 df, sf,
08004 of, NUM2DBL(sg),
08005 0, 0, 0,
08006 0, 0, 0,
08007 HAVE_JD | HAVE_DF);
08008 }
08009 }
08010
08011
08012
08013
08014
08015
08016
08017
08018
08019
08020 static VALUE
08021 datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
08022 {
08023 return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
08024 }
08025
08026
08027
08028
08029
08030
08031
08032
08033
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054 static VALUE
08055 datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
08056 {
08057 VALUE str, fmt, sg;
08058
08059 rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
08060
08061 switch (argc) {
08062 case 0:
08063 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08064 case 1:
08065 fmt = rb_str_new2("%FT%T%z");
08066 case 2:
08067 sg = INT2FIX(DEFAULT_SG);
08068 }
08069
08070 {
08071 VALUE argv2[2], hash;
08072
08073 argv2[0] = str;
08074 argv2[1] = fmt;
08075 hash = date_s__strptime(2, argv2, klass);
08076 return dt_new_by_frags(klass, hash, sg);
08077 }
08078 }
08079
08080
08081
08082
08083
08084
08085
08086
08087
08088
08089
08090
08091
08092
08093
08094
08095
08096
08097
08098
08099 static VALUE
08100 datetime_s_parse(int argc, VALUE *argv, VALUE klass)
08101 {
08102 VALUE str, comp, sg;
08103
08104 rb_scan_args(argc, argv, "03", &str, &comp, &sg);
08105
08106 switch (argc) {
08107 case 0:
08108 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08109 case 1:
08110 comp = Qtrue;
08111 case 2:
08112 sg = INT2FIX(DEFAULT_SG);
08113 }
08114
08115 {
08116 VALUE argv2[2], hash;
08117
08118 argv2[0] = str;
08119 argv2[1] = comp;
08120 hash = date_s__parse(2, argv2, klass);
08121 return dt_new_by_frags(klass, hash, sg);
08122 }
08123 }
08124
08125
08126
08127
08128
08129
08130
08131
08132
08133
08134
08135
08136
08137
08138
08139
08140
08141 static VALUE
08142 datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
08143 {
08144 VALUE str, sg;
08145
08146 rb_scan_args(argc, argv, "02", &str, &sg);
08147
08148 switch (argc) {
08149 case 0:
08150 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08151 case 1:
08152 sg = INT2FIX(DEFAULT_SG);
08153 }
08154
08155 {
08156 VALUE hash = date_s__iso8601(klass, str);
08157 return dt_new_by_frags(klass, hash, sg);
08158 }
08159 }
08160
08161
08162
08163
08164
08165
08166
08167
08168
08169
08170
08171
08172
08173 static VALUE
08174 datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
08175 {
08176 VALUE str, sg;
08177
08178 rb_scan_args(argc, argv, "02", &str, &sg);
08179
08180 switch (argc) {
08181 case 0:
08182 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08183 case 1:
08184 sg = INT2FIX(DEFAULT_SG);
08185 }
08186
08187 {
08188 VALUE hash = date_s__rfc3339(klass, str);
08189 return dt_new_by_frags(klass, hash, sg);
08190 }
08191 }
08192
08193
08194
08195
08196
08197
08198
08199
08200
08201
08202
08203
08204
08205 static VALUE
08206 datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
08207 {
08208 VALUE str, sg;
08209
08210 rb_scan_args(argc, argv, "02", &str, &sg);
08211
08212 switch (argc) {
08213 case 0:
08214 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08215 case 1:
08216 sg = INT2FIX(DEFAULT_SG);
08217 }
08218
08219 {
08220 VALUE hash = date_s__xmlschema(klass, str);
08221 return dt_new_by_frags(klass, hash, sg);
08222 }
08223 }
08224
08225
08226
08227
08228
08229
08230
08231
08232
08233
08234
08235
08236
08237
08238 static VALUE
08239 datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
08240 {
08241 VALUE str, sg;
08242
08243 rb_scan_args(argc, argv, "02", &str, &sg);
08244
08245 switch (argc) {
08246 case 0:
08247 str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
08248 case 1:
08249 sg = INT2FIX(DEFAULT_SG);
08250 }
08251
08252 {
08253 VALUE hash = date_s__rfc2822(klass, str);
08254 return dt_new_by_frags(klass, hash, sg);
08255 }
08256 }
08257
08258
08259
08260
08261
08262
08263
08264
08265
08266
08267
08268
08269
08270 static VALUE
08271 datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
08272 {
08273 VALUE str, sg;
08274
08275 rb_scan_args(argc, argv, "02", &str, &sg);
08276
08277 switch (argc) {
08278 case 0:
08279 str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
08280 case 1:
08281 sg = INT2FIX(DEFAULT_SG);
08282 }
08283
08284 {
08285 VALUE hash = date_s__httpdate(klass, str);
08286 return dt_new_by_frags(klass, hash, sg);
08287 }
08288 }
08289
08290
08291
08292
08293
08294
08295
08296
08297
08298
08299
08300
08301
08302 static VALUE
08303 datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
08304 {
08305 VALUE str, sg;
08306
08307 rb_scan_args(argc, argv, "02", &str, &sg);
08308
08309 switch (argc) {
08310 case 0:
08311 str = rb_str_new2("-4712-01-01T00:00:00+00:00");
08312 case 1:
08313 sg = INT2FIX(DEFAULT_SG);
08314 }
08315
08316 {
08317 VALUE hash = date_s__jisx0301(klass, str);
08318 return dt_new_by_frags(klass, hash, sg);
08319 }
08320 }
08321
08322
08323
08324
08325
08326
08327
08328
08329
08330
08331
08332
08333
08334 static VALUE
08335 dt_lite_to_s(VALUE self)
08336 {
08337 return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
08338 }
08339
08340
08341
08342
08343
08344
08345
08346
08347
08348
08349
08350
08351
08352
08353
08354
08355
08356
08357
08358
08359
08360
08361
08362
08363
08364
08365
08366
08367
08368
08369
08370
08371
08372
08373
08374
08375
08376
08377
08378
08379
08380
08381
08382
08383
08384
08385
08386
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396
08397
08398
08399
08400
08401
08402
08403
08404
08405
08406
08407
08408
08409
08410
08411
08412
08413
08414
08415
08416
08417
08418
08419
08420
08421
08422
08423
08424
08425
08426
08427
08428
08429
08430
08431
08432
08433
08434
08435
08436
08437
08438
08439
08440
08441
08442
08443
08444
08445
08446
08447
08448
08449
08450
08451
08452
08453
08454
08455
08456
08457
08458
08459
08460
08461
08462
08463
08464
08465
08466
08467
08468
08469
08470
08471
08472
08473
08474
08475
08476
08477
08478
08479
08480
08481
08482
08483
08484
08485
08486
08487
08488
08489
08490
08491
08492
08493
08494
08495
08496
08497
08498
08499
08500
08501
08502
08503
08504
08505
08506
08507
08508
08509
08510
08511
08512
08513
08514
08515
08516
08517 static VALUE
08518 dt_lite_strftime(int argc, VALUE *argv, VALUE self)
08519 {
08520 return date_strftime_internal(argc, argv, self,
08521 "%Y-%m-%dT%H:%M:%S%:z", set_tmx);
08522 }
08523
08524 static VALUE
08525 iso8601_timediv(VALUE self, VALUE n)
08526 {
08527 VALUE fmt;
08528
08529 fmt = rb_usascii_str_new2("T%H:%M:%S");
08530 if (f_gt_p(n, INT2FIX(0))) {
08531 VALUE argv[3];
08532
08533 get_d1(self);
08534
08535 argv[0] = rb_usascii_str_new2(".%0*d");
08536 argv[1] = n;
08537 argv[2] = f_round(f_quo(m_sf_in_sec(dat),
08538 f_quo(INT2FIX(1),
08539 f_expt(INT2FIX(10), n))));
08540 rb_str_append(fmt, rb_f_sprintf(3, argv));
08541 }
08542 rb_str_append(fmt, rb_usascii_str_new2("%:z"));
08543 return strftimev(RSTRING_PTR(fmt), self, set_tmx);
08544 }
08545
08546
08547
08548
08549
08550
08551
08552
08553
08554
08555
08556
08557
08558
08559 static VALUE
08560 dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
08561 {
08562 VALUE n;
08563
08564 rb_scan_args(argc, argv, "01", &n);
08565
08566 if (argc < 1)
08567 n = INT2FIX(0);
08568
08569 return f_add(strftimev("%Y-%m-%d", self, set_tmx),
08570 iso8601_timediv(self, n));
08571 }
08572
08573
08574
08575
08576
08577
08578
08579
08580
08581
08582
08583
08584
08585 static VALUE
08586 dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
08587 {
08588 return dt_lite_iso8601(argc, argv, self);
08589 }
08590
08591
08592
08593
08594
08595
08596
08597
08598
08599
08600
08601
08602
08603 static VALUE
08604 dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
08605 {
08606 VALUE n, s;
08607
08608 rb_scan_args(argc, argv, "01", &n);
08609
08610 if (argc < 1)
08611 n = INT2FIX(0);
08612
08613 {
08614 get_d1(self);
08615 s = jisx0301_date(m_real_local_jd(dat),
08616 m_real_year(dat));
08617 return rb_str_append(strftimev(RSTRING_PTR(s), self, set_tmx),
08618 iso8601_timediv(self, n));
08619 }
08620 }
08621
08622
08623
08624 #define f_getlocal(x) rb_funcall(x, rb_intern("getlocal"), 0)
08625 #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
08626 #define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0)
08627 #define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d)
08628 #define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6,\
08629 y, m, d, h, min, s)
08630
08631
08632
08633
08634
08635
08636
08637 static VALUE
08638 time_to_time(VALUE self)
08639 {
08640 return rb_funcall(self, rb_intern("getlocal"), 0);
08641 }
08642
08643
08644
08645
08646
08647
08648
08649 static VALUE
08650 time_to_date(VALUE self)
08651 {
08652 VALUE y, nth, ret;
08653 int ry, m, d;
08654
08655 y = f_year(self);
08656 m = FIX2INT(f_mon(self));
08657 d = FIX2INT(f_mday(self));
08658
08659 decode_year(y, -1, &nth, &ry);
08660
08661 ret = d_simple_new_internal(cDate,
08662 nth, 0,
08663 GREGORIAN,
08664 ry, m, d,
08665 HAVE_CIVIL);
08666 {
08667 get_d1(ret);
08668 set_sg(dat, DEFAULT_SG);
08669 }
08670 return ret;
08671 }
08672
08673
08674
08675
08676
08677
08678
08679 static VALUE
08680 time_to_datetime(VALUE self)
08681 {
08682 VALUE y, sf, nth, ret;
08683 int ry, m, d, h, min, s, of;
08684
08685 y = f_year(self);
08686 m = FIX2INT(f_mon(self));
08687 d = FIX2INT(f_mday(self));
08688
08689 h = FIX2INT(f_hour(self));
08690 min = FIX2INT(f_min(self));
08691 s = FIX2INT(f_sec(self));
08692 if (s == 60)
08693 s = 59;
08694
08695 sf = sec_to_ns(f_subsec(self));
08696 of = FIX2INT(f_utc_offset(self));
08697
08698 decode_year(y, -1, &nth, &ry);
08699
08700 ret = d_complex_new_internal(cDateTime,
08701 nth, 0,
08702 0, sf,
08703 of, DEFAULT_SG,
08704 ry, m, d,
08705 h, min, s,
08706 HAVE_CIVIL | HAVE_TIME);
08707 {
08708 get_d1(ret);
08709 set_sg(dat, DEFAULT_SG);
08710 }
08711 return ret;
08712 }
08713
08714
08715
08716
08717
08718
08719
08720 static VALUE
08721 date_to_time(VALUE self)
08722 {
08723 get_d1(self);
08724
08725 return f_local3(rb_cTime,
08726 m_real_year(dat),
08727 INT2FIX(m_mon(dat)),
08728 INT2FIX(m_mday(dat)));
08729 }
08730
08731
08732
08733
08734
08735
08736
08737 static VALUE
08738 date_to_date(VALUE self)
08739 {
08740 return self;
08741 }
08742
08743
08744
08745
08746
08747
08748
08749 static VALUE
08750 date_to_datetime(VALUE self)
08751 {
08752 get_d1a(self);
08753
08754 if (simple_dat_p(adat)) {
08755 VALUE new = d_lite_s_alloc_simple(cDateTime);
08756 {
08757 get_d1b(new);
08758 bdat->s = adat->s;
08759 return new;
08760 }
08761 }
08762 else {
08763 VALUE new = d_lite_s_alloc_complex(cDateTime);
08764 {
08765 get_d1b(new);
08766 bdat->c = adat->c;
08767 bdat->c.df = 0;
08768 bdat->c.sf = INT2FIX(0);
08769 #ifndef USE_PACK
08770 bdat->c.hour = 0;
08771 bdat->c.min = 0;
08772 bdat->c.sec = 0;
08773 #else
08774 bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc),
08775 0, 0, 0);
08776 bdat->c.flags |= HAVE_DF | HAVE_TIME;
08777 #endif
08778 return new;
08779 }
08780 }
08781 }
08782
08783
08784
08785
08786
08787
08788
08789 static VALUE
08790 datetime_to_time(VALUE self)
08791 {
08792 volatile VALUE dup = dup_obj_with_new_offset(self, 0);
08793 {
08794 VALUE t;
08795
08796 get_d1(dup);
08797
08798 t = f_utc6(rb_cTime,
08799 m_real_year(dat),
08800 INT2FIX(m_mon(dat)),
08801 INT2FIX(m_mday(dat)),
08802 INT2FIX(m_hour(dat)),
08803 INT2FIX(m_min(dat)),
08804 f_add(INT2FIX(m_sec(dat)),
08805 m_sf_in_sec(dat)));
08806 return f_getlocal(t);
08807 }
08808 }
08809
08810
08811
08812
08813
08814
08815
08816 static VALUE
08817 datetime_to_date(VALUE self)
08818 {
08819 get_d1a(self);
08820
08821 if (simple_dat_p(adat)) {
08822 VALUE new = d_lite_s_alloc_simple(cDate);
08823 {
08824 get_d1b(new);
08825 bdat->s = adat->s;
08826 bdat->s.jd = m_local_jd(adat);
08827 return new;
08828 }
08829 }
08830 else {
08831 VALUE new = d_lite_s_alloc_simple(cDate);
08832 {
08833 get_d1b(new);
08834 copy_complex_to_simple(&bdat->s, &adat->c)
08835 bdat->s.jd = m_local_jd(adat);
08836 bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
08837 return new;
08838 }
08839 }
08840 }
08841
08842
08843
08844
08845
08846
08847
08848 static VALUE
08849 datetime_to_datetime(VALUE self)
08850 {
08851 return self;
08852 }
08853
08854 #ifndef NDEBUG
08855
08856
08857 #define MIN_YEAR -4713
08858 #define MAX_YEAR 1000000
08859 #define MIN_JD -327
08860 #define MAX_JD 366963925
08861
08862 static int
08863 test_civil(int from, int to, double sg)
08864 {
08865 int j;
08866
08867 fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n",
08868 from, to, to - from, sg);
08869 for (j = from; j <= to; j++) {
08870 int y, m, d, rj, ns;
08871
08872 c_jd_to_civil(j, sg, &y, &m, &d);
08873 c_civil_to_jd(y, m, d, sg, &rj, &ns);
08874 if (j != rj) {
08875 fprintf(stderr, "%d != %d\n", j, rj);
08876 return 0;
08877 }
08878 }
08879 return 1;
08880 }
08881
08882 static VALUE
08883 date_s_test_civil(VALUE klass)
08884 {
08885 if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN))
08886 return Qfalse;
08887 if (!test_civil(2305814, 2598007, GREGORIAN))
08888 return Qfalse;
08889 if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN))
08890 return Qfalse;
08891
08892 if (!test_civil(MIN_JD, MIN_JD + 366, ITALY))
08893 return Qfalse;
08894 if (!test_civil(2305814, 2598007, ITALY))
08895 return Qfalse;
08896 if (!test_civil(MAX_JD - 366, MAX_JD, ITALY))
08897 return Qfalse;
08898
08899 return Qtrue;
08900 }
08901
08902 static int
08903 test_ordinal(int from, int to, double sg)
08904 {
08905 int j;
08906
08907 fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n",
08908 from, to, to - from, sg);
08909 for (j = from; j <= to; j++) {
08910 int y, d, rj, ns;
08911
08912 c_jd_to_ordinal(j, sg, &y, &d);
08913 c_ordinal_to_jd(y, d, sg, &rj, &ns);
08914 if (j != rj) {
08915 fprintf(stderr, "%d != %d\n", j, rj);
08916 return 0;
08917 }
08918 }
08919 return 1;
08920 }
08921
08922 static VALUE
08923 date_s_test_ordinal(VALUE klass)
08924 {
08925 if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN))
08926 return Qfalse;
08927 if (!test_ordinal(2305814, 2598007, GREGORIAN))
08928 return Qfalse;
08929 if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN))
08930 return Qfalse;
08931
08932 if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY))
08933 return Qfalse;
08934 if (!test_ordinal(2305814, 2598007, ITALY))
08935 return Qfalse;
08936 if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY))
08937 return Qfalse;
08938
08939 return Qtrue;
08940 }
08941
08942 static int
08943 test_commercial(int from, int to, double sg)
08944 {
08945 int j;
08946
08947 fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n",
08948 from, to, to - from, sg);
08949 for (j = from; j <= to; j++) {
08950 int y, w, d, rj, ns;
08951
08952 c_jd_to_commercial(j, sg, &y, &w, &d);
08953 c_commercial_to_jd(y, w, d, sg, &rj, &ns);
08954 if (j != rj) {
08955 fprintf(stderr, "%d != %d\n", j, rj);
08956 return 0;
08957 }
08958 }
08959 return 1;
08960 }
08961
08962 static VALUE
08963 date_s_test_commercial(VALUE klass)
08964 {
08965 if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN))
08966 return Qfalse;
08967 if (!test_commercial(2305814, 2598007, GREGORIAN))
08968 return Qfalse;
08969 if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN))
08970 return Qfalse;
08971
08972 if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY))
08973 return Qfalse;
08974 if (!test_commercial(2305814, 2598007, ITALY))
08975 return Qfalse;
08976 if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY))
08977 return Qfalse;
08978
08979 return Qtrue;
08980 }
08981
08982 static int
08983 test_weeknum(int from, int to, int f, double sg)
08984 {
08985 int j;
08986
08987 fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n",
08988 from, to, to - from, sg);
08989 for (j = from; j <= to; j++) {
08990 int y, w, d, rj, ns;
08991
08992 c_jd_to_weeknum(j, f, sg, &y, &w, &d);
08993 c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns);
08994 if (j != rj) {
08995 fprintf(stderr, "%d != %d\n", j, rj);
08996 return 0;
08997 }
08998 }
08999 return 1;
09000 }
09001
09002 static VALUE
09003 date_s_test_weeknum(VALUE klass)
09004 {
09005 int f;
09006
09007 for (f = 0; f <= 1; f++) {
09008 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN))
09009 return Qfalse;
09010 if (!test_weeknum(2305814, 2598007, f, GREGORIAN))
09011 return Qfalse;
09012 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN))
09013 return Qfalse;
09014
09015 if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY))
09016 return Qfalse;
09017 if (!test_weeknum(2305814, 2598007, f, ITALY))
09018 return Qfalse;
09019 if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY))
09020 return Qfalse;
09021 }
09022
09023 return Qtrue;
09024 }
09025
09026 static int
09027 test_nth_kday(int from, int to, double sg)
09028 {
09029 int j;
09030
09031 fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n",
09032 from, to, to - from, sg);
09033 for (j = from; j <= to; j++) {
09034 int y, m, n, k, rj, ns;
09035
09036 c_jd_to_nth_kday(j, sg, &y, &m, &n, &k);
09037 c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns);
09038 if (j != rj) {
09039 fprintf(stderr, "%d != %d\n", j, rj);
09040 return 0;
09041 }
09042 }
09043 return 1;
09044 }
09045
09046 static VALUE
09047 date_s_test_nth_kday(VALUE klass)
09048 {
09049 if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN))
09050 return Qfalse;
09051 if (!test_nth_kday(2305814, 2598007, GREGORIAN))
09052 return Qfalse;
09053 if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN))
09054 return Qfalse;
09055
09056 if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY))
09057 return Qfalse;
09058 if (!test_nth_kday(2305814, 2598007, ITALY))
09059 return Qfalse;
09060 if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY))
09061 return Qfalse;
09062
09063 return Qtrue;
09064 }
09065
09066 static int
09067 test_unit_v2v(VALUE i,
09068 VALUE (* conv1)(VALUE),
09069 VALUE (* conv2)(VALUE))
09070 {
09071 VALUE c, o;
09072 c = (*conv1)(i);
09073 o = (*conv2)(c);
09074 return f_eqeq_p(o, i);
09075 }
09076
09077 static int
09078 test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
09079 VALUE (* conv2)(VALUE))
09080 {
09081 if (!test_unit_v2v(INT2FIX(0), conv1, conv2))
09082 return 0;
09083 if (!test_unit_v2v(INT2FIX(1), conv1, conv2))
09084 return 0;
09085 if (!test_unit_v2v(INT2FIX(2), conv1, conv2))
09086 return 0;
09087 if (!test_unit_v2v(INT2FIX(3), conv1, conv2))
09088 return 0;
09089 if (!test_unit_v2v(INT2FIX(11), conv1, conv2))
09090 return 0;
09091 if (!test_unit_v2v(INT2FIX(65535), conv1, conv2))
09092 return 0;
09093 if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2))
09094 return 0;
09095 if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2))
09096 return 0;
09097 if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2))
09098 return 0;
09099 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2))
09100 return 0;
09101 if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2))
09102 return 0;
09103 if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2))
09104 return 0;
09105 return 1;
09106 }
09107
09108 static int
09109 test_unit_v2v_iter(VALUE (* conv1)(VALUE),
09110 VALUE (* conv2)(VALUE))
09111 {
09112 if (!test_unit_v2v_iter2(conv1, conv2))
09113 return 0;
09114 if (!test_unit_v2v_iter2(conv2, conv1))
09115 return 0;
09116 return 1;
09117 }
09118
09119 static VALUE
09120 date_s_test_unit_conv(VALUE klass)
09121 {
09122 if (!test_unit_v2v_iter(sec_to_day, day_to_sec))
09123 return Qfalse;
09124 if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms))
09125 return Qfalse;
09126 if (!test_unit_v2v_iter(ns_to_day, day_to_ns))
09127 return Qfalse;
09128 if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns))
09129 return Qfalse;
09130 return Qtrue;
09131 }
09132
09133 static VALUE
09134 date_s_test_all(VALUE klass)
09135 {
09136 if (date_s_test_civil(klass) == Qfalse)
09137 return Qfalse;
09138 if (date_s_test_ordinal(klass) == Qfalse)
09139 return Qfalse;
09140 if (date_s_test_commercial(klass) == Qfalse)
09141 return Qfalse;
09142 if (date_s_test_weeknum(klass) == Qfalse)
09143 return Qfalse;
09144 if (date_s_test_nth_kday(klass) == Qfalse)
09145 return Qfalse;
09146 if (date_s_test_unit_conv(klass) == Qfalse)
09147 return Qfalse;
09148 return Qtrue;
09149 }
09150 #endif
09151
09152 static const char *monthnames[] = {
09153 NULL,
09154 "January", "February", "March",
09155 "April", "May", "June",
09156 "July", "August", "September",
09157 "October", "November", "December"
09158 };
09159
09160 static const char *abbr_monthnames[] = {
09161 NULL,
09162 "Jan", "Feb", "Mar", "Apr",
09163 "May", "Jun", "Jul", "Aug",
09164 "Sep", "Oct", "Nov", "Dec"
09165 };
09166
09167 static const char *daynames[] = {
09168 "Sunday", "Monday", "Tuesday", "Wednesday",
09169 "Thursday", "Friday", "Saturday"
09170 };
09171
09172 static const char *abbr_daynames[] = {
09173 "Sun", "Mon", "Tue", "Wed",
09174 "Thu", "Fri", "Sat"
09175 };
09176
09177 static VALUE
09178 mk_ary_of_str(long len, const char *a[])
09179 {
09180 VALUE o;
09181 long i;
09182
09183 o = rb_ary_new2(len);
09184 for (i = 0; i < len; i++) {
09185 VALUE e;
09186
09187 if (!a[i])
09188 e = Qnil;
09189 else {
09190 e = rb_usascii_str_new2(a[i]);
09191 rb_obj_freeze(e);
09192 }
09193 rb_ary_push(o, e);
09194 }
09195 rb_obj_freeze(o);
09196 return o;
09197 }
09198
09199 void
09200 Init_date_core(void)
09201 {
09202 #undef rb_intern
09203 #define rb_intern(str) rb_intern_const(str)
09204
09205 assert(fprintf(stderr, "assert() is now active\n"));
09206
09207 id_cmp = rb_intern("<=>");
09208 id_le_p = rb_intern("<=");
09209 id_ge_p = rb_intern(">=");
09210 id_eqeq_p = rb_intern("==");
09211
09212 half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
09213
09214 #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
09215 day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
09216 SECOND_IN_NANOSECONDS);
09217 #elif defined HAVE_LONG_LONG
09218 day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS *
09219 SECOND_IN_NANOSECONDS);
09220 #else
09221 day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
09222 INT2FIX(SECOND_IN_NANOSECONDS));
09223 #endif
09224
09225 rb_gc_register_mark_object(half_days_in_day);
09226 rb_gc_register_mark_object(day_in_nanoseconds);
09227
09228 positive_inf = +INFINITY;
09229 negative_inf = -INFINITY;
09230
09231
09232
09233
09234
09235
09236
09237
09238
09239
09240
09241
09242
09243
09244
09245
09246
09247
09248
09249
09250
09251
09252
09253
09254
09255
09256
09257
09258
09259
09260
09261
09262
09263
09264
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282
09283
09284
09285
09286
09287
09288
09289
09290
09291
09292
09293
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313
09314
09315
09316
09317
09318
09319
09320
09321
09322
09323
09324
09325
09326
09327
09328
09329
09330
09331
09332
09333
09334
09335
09336
09337
09338
09339
09340
09341
09342
09343
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353
09354
09355
09356
09357
09358
09359
09360
09361
09362
09363
09364
09365
09366
09367
09368
09369
09370
09371
09372
09373
09374
09375
09376
09377
09378
09379
09380
09381
09382
09383
09384
09385
09386
09387
09388
09389
09390
09391
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417
09418
09419
09420
09421
09422
09423
09424
09425
09426
09427
09428
09429
09430
09431 cDate = rb_define_class("Date", rb_cObject);
09432
09433 rb_include_module(cDate, rb_mComparable);
09434
09435
09436
09437
09438 rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
09439
09440
09441
09442
09443 rb_define_const(cDate, "ABBR_MONTHNAMES",
09444 mk_ary_of_str(13, abbr_monthnames));
09445
09446
09447
09448
09449 rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
09450
09451
09452
09453
09454 rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames));
09455
09456
09457
09458
09459 rb_define_const(cDate, "ITALY", INT2FIX(ITALY));
09460
09461
09462
09463
09464 rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND));
09465
09466
09467
09468
09469 rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
09470
09471
09472
09473
09474 rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
09475
09476 rb_define_alloc_func(cDate, d_lite_s_alloc);
09477
09478 #ifndef NDEBUG
09479 #define de_define_private_method rb_define_private_method
09480 de_define_private_method(CLASS_OF(cDate), "_valid_jd?",
09481 date_s__valid_jd_p, -1);
09482 de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?",
09483 date_s__valid_ordinal_p, -1);
09484 de_define_private_method(CLASS_OF(cDate), "_valid_civil?",
09485 date_s__valid_civil_p, -1);
09486 de_define_private_method(CLASS_OF(cDate), "_valid_date?",
09487 date_s__valid_civil_p, -1);
09488 de_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
09489 date_s__valid_commercial_p, -1);
09490 de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
09491 date_s__valid_weeknum_p, -1);
09492 de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?",
09493 date_s__valid_nth_kday_p, -1);
09494 #endif
09495
09496 rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1);
09497 rb_define_singleton_method(cDate, "valid_ordinal?",
09498 date_s_valid_ordinal_p, -1);
09499 rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1);
09500 rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1);
09501 rb_define_singleton_method(cDate, "valid_commercial?",
09502 date_s_valid_commercial_p, -1);
09503
09504 #ifndef NDEBUG
09505 de_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
09506 date_s_valid_weeknum_p, -1);
09507 de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
09508 date_s_valid_nth_kday_p, -1);
09509 de_define_private_method(CLASS_OF(cDate), "zone_to_diff",
09510 date_s_zone_to_diff, 1);
09511 #endif
09512
09513 rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1);
09514 rb_define_singleton_method(cDate, "gregorian_leap?",
09515 date_s_gregorian_leap_p, 1);
09516 rb_define_singleton_method(cDate, "leap?",
09517 date_s_gregorian_leap_p, 1);
09518
09519 #ifndef NDEBUG
09520 #define de_define_singleton_method rb_define_singleton_method
09521 #define de_define_alias rb_define_alias
09522 de_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
09523 de_define_alias(rb_singleton_class(cDate), "new_l!", "new");
09524 #endif
09525
09526 rb_define_singleton_method(cDate, "jd", date_s_jd, -1);
09527 rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1);
09528 rb_define_singleton_method(cDate, "civil", date_s_civil, -1);
09529 rb_define_singleton_method(cDate, "new", date_s_civil, -1);
09530 rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1);
09531
09532 #ifndef NDEBUG
09533 de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
09534 de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1);
09535 #endif
09536
09537 rb_define_singleton_method(cDate, "today", date_s_today, -1);
09538 rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1);
09539 rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
09540 rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
09541 rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
09542 rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
09543 rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
09544 rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
09545 rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
09546 rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
09547 rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
09548 rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
09549 rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
09550 rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
09551 rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
09552 rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
09553 rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
09554 rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
09555 rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
09556
09557 #ifndef NDEBUG
09558 #define de_define_method rb_define_method
09559 de_define_method(cDate, "initialize", d_lite_initialize, -1);
09560 #endif
09561 rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1);
09562
09563 #ifndef NDEBUG
09564 de_define_method(cDate, "fill", d_lite_fill, 0);
09565 #endif
09566
09567 rb_define_method(cDate, "ajd", d_lite_ajd, 0);
09568 rb_define_method(cDate, "amjd", d_lite_amjd, 0);
09569 rb_define_method(cDate, "jd", d_lite_jd, 0);
09570 rb_define_method(cDate, "mjd", d_lite_mjd, 0);
09571 rb_define_method(cDate, "ld", d_lite_ld, 0);
09572
09573 rb_define_method(cDate, "year", d_lite_year, 0);
09574 rb_define_method(cDate, "yday", d_lite_yday, 0);
09575 rb_define_method(cDate, "mon", d_lite_mon, 0);
09576 rb_define_method(cDate, "month", d_lite_mon, 0);
09577 rb_define_method(cDate, "mday", d_lite_mday, 0);
09578 rb_define_method(cDate, "day", d_lite_mday, 0);
09579 rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0);
09580
09581 rb_define_method(cDate, "cwyear", d_lite_cwyear, 0);
09582 rb_define_method(cDate, "cweek", d_lite_cweek, 0);
09583 rb_define_method(cDate, "cwday", d_lite_cwday, 0);
09584
09585 #ifndef NDEBUG
09586 de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0);
09587 de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0);
09588 #endif
09589
09590 rb_define_method(cDate, "wday", d_lite_wday, 0);
09591
09592 rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0);
09593 rb_define_method(cDate, "monday?", d_lite_monday_p, 0);
09594 rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0);
09595 rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0);
09596 rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0);
09597 rb_define_method(cDate, "friday?", d_lite_friday_p, 0);
09598 rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0);
09599
09600 #ifndef NDEBUG
09601 de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2);
09602 #endif
09603
09604 rb_define_private_method(cDate, "hour", d_lite_hour, 0);
09605 rb_define_private_method(cDate, "min", d_lite_min, 0);
09606 rb_define_private_method(cDate, "minute", d_lite_min, 0);
09607 rb_define_private_method(cDate, "sec", d_lite_sec, 0);
09608 rb_define_private_method(cDate, "second", d_lite_sec, 0);
09609 rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0);
09610 rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0);
09611 rb_define_private_method(cDate, "offset", d_lite_offset, 0);
09612 rb_define_private_method(cDate, "zone", d_lite_zone, 0);
09613
09614 rb_define_method(cDate, "julian?", d_lite_julian_p, 0);
09615 rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0);
09616 rb_define_method(cDate, "leap?", d_lite_leap_p, 0);
09617
09618 rb_define_method(cDate, "start", d_lite_start, 0);
09619 rb_define_method(cDate, "new_start", d_lite_new_start, -1);
09620 rb_define_method(cDate, "italy", d_lite_italy, 0);
09621 rb_define_method(cDate, "england", d_lite_england, 0);
09622 rb_define_method(cDate, "julian", d_lite_julian, 0);
09623 rb_define_method(cDate, "gregorian", d_lite_gregorian, 0);
09624
09625 rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1);
09626
09627 rb_define_method(cDate, "+", d_lite_plus, 1);
09628 rb_define_method(cDate, "-", d_lite_minus, 1);
09629
09630 rb_define_method(cDate, "next_day", d_lite_next_day, -1);
09631 rb_define_method(cDate, "prev_day", d_lite_prev_day, -1);
09632 rb_define_method(cDate, "next", d_lite_next, 0);
09633 rb_define_method(cDate, "succ", d_lite_next, 0);
09634
09635 rb_define_method(cDate, ">>", d_lite_rshift, 1);
09636 rb_define_method(cDate, "<<", d_lite_lshift, 1);
09637
09638 rb_define_method(cDate, "next_month", d_lite_next_month, -1);
09639 rb_define_method(cDate, "prev_month", d_lite_prev_month, -1);
09640 rb_define_method(cDate, "next_year", d_lite_next_year, -1);
09641 rb_define_method(cDate, "prev_year", d_lite_prev_year, -1);
09642
09643 rb_define_method(cDate, "step", d_lite_step, -1);
09644 rb_define_method(cDate, "upto", d_lite_upto, 1);
09645 rb_define_method(cDate, "downto", d_lite_downto, 1);
09646
09647 rb_define_method(cDate, "<=>", d_lite_cmp, 1);
09648 rb_define_method(cDate, "===", d_lite_equal, 1);
09649 rb_define_method(cDate, "eql?", d_lite_eql_p, 1);
09650 rb_define_method(cDate, "hash", d_lite_hash, 0);
09651
09652 rb_define_method(cDate, "to_s", d_lite_to_s, 0);
09653 #ifndef NDEBUG
09654 de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0);
09655 #endif
09656 rb_define_method(cDate, "inspect", d_lite_inspect, 0);
09657
09658 rb_define_method(cDate, "strftime", d_lite_strftime, -1);
09659
09660 rb_define_method(cDate, "asctime", d_lite_asctime, 0);
09661 rb_define_method(cDate, "ctime", d_lite_asctime, 0);
09662 rb_define_method(cDate, "iso8601", d_lite_iso8601, 0);
09663 rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0);
09664 rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0);
09665 rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0);
09666 rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0);
09667 rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
09668 rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
09669
09670 #ifndef NDEBUG
09671 de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
09672 #endif
09673 rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
09674 rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
09675
09676
09677
09678 cDateTime = rb_define_class("DateTime", cDate);
09679
09680 rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1);
09681 rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1);
09682 rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1);
09683 rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
09684 rb_define_singleton_method(cDateTime, "commercial",
09685 datetime_s_commercial, -1);
09686
09687 #ifndef NDEBUG
09688 de_define_singleton_method(cDateTime, "weeknum",
09689 datetime_s_weeknum, -1);
09690 de_define_singleton_method(cDateTime, "nth_kday",
09691 datetime_s_nth_kday, -1);
09692 #endif
09693
09694 rb_undef_method(CLASS_OF(cDateTime), "today");
09695
09696 rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1);
09697 rb_define_singleton_method(cDateTime, "_strptime",
09698 datetime_s__strptime, -1);
09699 rb_define_singleton_method(cDateTime, "strptime",
09700 datetime_s_strptime, -1);
09701 rb_define_singleton_method(cDateTime, "parse",
09702 datetime_s_parse, -1);
09703 rb_define_singleton_method(cDateTime, "iso8601",
09704 datetime_s_iso8601, -1);
09705 rb_define_singleton_method(cDateTime, "rfc3339",
09706 datetime_s_rfc3339, -1);
09707 rb_define_singleton_method(cDateTime, "xmlschema",
09708 datetime_s_xmlschema, -1);
09709 rb_define_singleton_method(cDateTime, "rfc2822",
09710 datetime_s_rfc2822, -1);
09711 rb_define_singleton_method(cDateTime, "rfc822",
09712 datetime_s_rfc2822, -1);
09713 rb_define_singleton_method(cDateTime, "httpdate",
09714 datetime_s_httpdate, -1);
09715 rb_define_singleton_method(cDateTime, "jisx0301",
09716 datetime_s_jisx0301, -1);
09717
09718 #define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\
09719 ID2SYM(rb_intern(s)))
09720
09721 f_public(cDateTime, "hour");
09722 f_public(cDateTime, "min");
09723 f_public(cDateTime, "minute");
09724 f_public(cDateTime, "sec");
09725 f_public(cDateTime, "second");
09726 f_public(cDateTime, "sec_fraction");
09727 f_public(cDateTime, "second_fraction");
09728 f_public(cDateTime, "offset");
09729 f_public(cDateTime, "zone");
09730 f_public(cDateTime, "new_offset");
09731
09732 rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0);
09733
09734 rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
09735
09736 rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1);
09737 rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1);
09738 rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
09739 rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
09740
09741
09742
09743 rb_define_method(rb_cTime, "to_time", time_to_time, 0);
09744 rb_define_method(rb_cTime, "to_date", time_to_date, 0);
09745 rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0);
09746
09747 rb_define_method(cDate, "to_time", date_to_time, 0);
09748 rb_define_method(cDate, "to_date", date_to_date, 0);
09749 rb_define_method(cDate, "to_datetime", date_to_datetime, 0);
09750
09751 rb_define_method(cDateTime, "to_time", datetime_to_time, 0);
09752 rb_define_method(cDateTime, "to_date", datetime_to_date, 0);
09753 rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0);
09754
09755 #ifndef NDEBUG
09756
09757
09758 de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
09759 de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
09760 de_define_singleton_method(cDate, "test_commercial",
09761 date_s_test_commercial, 0);
09762 de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
09763 de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
09764 de_define_singleton_method(cDate, "test_unit_conv",
09765 date_s_test_unit_conv, 0);
09766 de_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
09767 #endif
09768 }
09769
09770
09771
09772
09773
09774
09775