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