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