diff options
Diffstat (limited to 'ruby_1_9_3/ext/date')
-rw-r--r-- | ruby_1_9_3/ext/date/date_core.c | 9774 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/date_parse.c | 2425 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/date_strftime.c | 1155 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/date_strptime.c | 698 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/date_tmx.h | 56 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/depend | 2 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/extconf.rb | 2 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/lib/date.rb | 61 | ||||
-rw-r--r-- | ruby_1_9_3/ext/date/lib/date/format.rb | 1 |
9 files changed, 0 insertions, 14174 deletions
diff --git a/ruby_1_9_3/ext/date/date_core.c b/ruby_1_9_3/ext/date/date_core.c deleted file mode 100644 index 4048d1345d..0000000000 --- a/ruby_1_9_3/ext/date/date_core.c +++ /dev/null @@ -1,9774 +0,0 @@ -/* - date_core.c: Coded by Tadayoshi Funaba 2010, 2011 -*/ - -#include "ruby.h" -#include "ruby/encoding.h" -#include <math.h> -#include <time.h> - -#define NDEBUG -#include <assert.h> - -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif - -#define USE_PACK - -static ID id_cmp, id_le_p, id_ge_p, id_eqeq_p; -static VALUE cDate, cDateTime; -static VALUE half_days_in_day, day_in_nanoseconds; -static double positive_inf, negative_inf; - -#define f_boolcast(x) ((x) ? Qtrue : Qfalse) - -#define f_abs(x) rb_funcall(x, rb_intern("abs"), 0) -#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0) -#define f_add(x,y) rb_funcall(x, '+', 1, y) -#define f_sub(x,y) rb_funcall(x, '-', 1, y) -#define f_mul(x,y) rb_funcall(x, '*', 1, y) -#define f_div(x,y) rb_funcall(x, '/', 1, y) -#define f_quo(x,y) rb_funcall(x, rb_intern("quo"), 1, y) -#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y) -#define f_mod(x,y) rb_funcall(x, '%', 1, y) -#define f_remainder(x,y) rb_funcall(x, rb_intern("remainder"), 1, y) -#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y) -#define f_floor(x) rb_funcall(x, rb_intern("floor"), 0) -#define f_ceil(x) rb_funcall(x, rb_intern("ceil"), 0) -#define f_truncate(x) rb_funcall(x, rb_intern("truncate"), 0) -#define f_round(x) rb_funcall(x, rb_intern("round"), 0) - -#define f_to_i(x) rb_funcall(x, rb_intern("to_i"), 0) -#define f_to_r(x) rb_funcall(x, rb_intern("to_r"), 0) -#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0) -#define f_inspect(x) rb_funcall(x, rb_intern("inspect"), 0) - -#define f_add3(x,y,z) f_add(f_add(x, y), z) -#define f_sub3(x,y,z) f_sub(f_sub(x, y), z) - -inline static VALUE -f_cmp(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) { - long c = FIX2LONG(x) - FIX2LONG(y); - if (c > 0) - c = 1; - else if (c < 0) - c = -1; - return INT2FIX(c); - } - return rb_funcall(x, id_cmp, 1, y); -} - -inline static VALUE -f_lt_p(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) - return f_boolcast(FIX2LONG(x) < FIX2LONG(y)); - return rb_funcall(x, '<', 1, y); -} - -inline static VALUE -f_gt_p(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) - return f_boolcast(FIX2LONG(x) > FIX2LONG(y)); - return rb_funcall(x, '>', 1, y); -} - -inline static VALUE -f_le_p(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) - return f_boolcast(FIX2LONG(x) <= FIX2LONG(y)); - return rb_funcall(x, id_le_p, 1, y); -} - -inline static VALUE -f_ge_p(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) - return f_boolcast(FIX2LONG(x) >= FIX2LONG(y)); - return rb_funcall(x, rb_intern(">="), 1, y); -} - -inline static VALUE -f_eqeq_p(VALUE x, VALUE y) -{ - if (FIXNUM_P(x) && FIXNUM_P(y)) - return f_boolcast(FIX2LONG(x) == FIX2LONG(y)); - return rb_funcall(x, rb_intern("=="), 1, y); -} - -inline static VALUE -f_zero_p(VALUE x) -{ - switch (TYPE(x)) { - case T_FIXNUM: - return f_boolcast(FIX2LONG(x) == 0); - case T_BIGNUM: - return Qfalse; - case T_RATIONAL: - { - VALUE num = RRATIONAL(x)->num; - return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0); - } - } - return rb_funcall(x, id_eqeq_p, 1, INT2FIX(0)); -} - -#define f_nonzero_p(x) (!f_zero_p(x)) - -inline static VALUE -f_negative_p(VALUE x) -{ - if (FIXNUM_P(x)) - return f_boolcast(FIX2LONG(x) < 0); - return rb_funcall(x, '<', 1, INT2FIX(0)); -} - -#define f_positive_p(x) (!f_negative_p(x)) - -#define f_ajd(x) rb_funcall(x, rb_intern("ajd"), 0) -#define f_jd(x) rb_funcall(x, rb_intern("jd"), 0) -#define f_year(x) rb_funcall(x, rb_intern("year"), 0) -#define f_mon(x) rb_funcall(x, rb_intern("mon"), 0) -#define f_mday(x) rb_funcall(x, rb_intern("mday"), 0) -#define f_wday(x) rb_funcall(x, rb_intern("wday"), 0) -#define f_hour(x) rb_funcall(x, rb_intern("hour"), 0) -#define f_min(x) rb_funcall(x, rb_intern("min"), 0) -#define f_sec(x) rb_funcall(x, rb_intern("sec"), 0) - -/* copied from time.c */ -#define NDIV(x,y) (-(-((x)+1)/(y))-1) -#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1) -#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) -#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d)) - -#define HAVE_JD (1 << 0) -#define HAVE_DF (1 << 1) -#define HAVE_CIVIL (1 << 2) -#define HAVE_TIME (1 << 3) -#define COMPLEX_DAT (1 << 7) - -#define have_jd_p(x) ((x)->flags & HAVE_JD) -#define have_df_p(x) ((x)->flags & HAVE_DF) -#define have_civil_p(x) ((x)->flags & HAVE_CIVIL) -#define have_time_p(x) ((x)->flags & HAVE_TIME) -#define complex_dat_p(x) ((x)->flags & COMPLEX_DAT) -#define simple_dat_p(x) (!complex_dat_p(x)) - -#define ITALY 2299161 /* 1582-10-15 */ -#define ENGLAND 2361222 /* 1752-09-14 */ -#define JULIAN positive_inf -#define GREGORIAN negative_inf -#define DEFAULT_SG ITALY - -#define UNIX_EPOCH_IN_CJD INT2FIX(2440588) /* 1970-01-01 */ - -#define MINUTE_IN_SECONDS 60 -#define HOUR_IN_SECONDS 3600 -#define DAY_IN_SECONDS 86400 -#define SECOND_IN_MILLISECONDS 1000 -#define SECOND_IN_NANOSECONDS 1000000000 - -#define JC_PERIOD0 1461 /* 365.25 * 4 */ -#define GC_PERIOD0 146097 /* 365.2425 * 400 */ -#define CM_PERIOD0 71149239 /* (lcm 7 1461 146097) */ -#define CM_PERIOD (0xfffffff / CM_PERIOD0 * CM_PERIOD0) -#define CM_PERIOD_JCY (CM_PERIOD / JC_PERIOD0 * 4) -#define CM_PERIOD_GCY (CM_PERIOD / GC_PERIOD0 * 400) - -#define REFORM_BEGIN_YEAR 1582 -#define REFORM_END_YEAR 1930 -#define REFORM_BEGIN_JD 2298874 /* ns 1582-01-01 */ -#define REFORM_END_JD 2426355 /* os 1930-12-31 */ - -#ifdef USE_PACK -#define SEC_WIDTH 6 -#define MIN_WIDTH 6 -#define HOUR_WIDTH 5 -#define MDAY_WIDTH 5 -#define MON_WIDTH 4 - -#define SEC_SHIFT 0 -#define MIN_SHIFT SEC_WIDTH -#define HOUR_SHIFT (MIN_WIDTH + SEC_WIDTH) -#define MDAY_SHIFT (HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH) -#define MON_SHIFT (MDAY_WIDTH + HOUR_WIDTH + MIN_WIDTH + SEC_WIDTH) - -#define PK_MASK(x) ((1 << (x)) - 1) - -#define EX_SEC(x) (((x) >> SEC_SHIFT) & PK_MASK(SEC_WIDTH)) -#define EX_MIN(x) (((x) >> MIN_SHIFT) & PK_MASK(MIN_WIDTH)) -#define EX_HOUR(x) (((x) >> HOUR_SHIFT) & PK_MASK(HOUR_WIDTH)) -#define EX_MDAY(x) (((x) >> MDAY_SHIFT) & PK_MASK(MDAY_WIDTH)) -#define EX_MON(x) (((x) >> MON_SHIFT) & PK_MASK(MON_WIDTH)) - -#define PACK5(m,d,h,min,s) \ - (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT) |\ - ((h) << HOUR_SHIFT) | ((min) << MIN_SHIFT) | ((s) << SEC_SHIFT)) - -#define PACK2(m,d) \ - (((m) << MON_SHIFT) | ((d) << MDAY_SHIFT)) -#endif - -#ifdef HAVE_FLOAT_H -#include <float.h> -#endif - -#if defined(FLT_RADIX) && defined(FLT_MANT_DIG) -#if FLT_RADIX == 2 && FLT_MANT_DIG > 22 -#define USE_FLOAT -#define sg_cast float -#else -#define sg_cast double -#endif -#endif - -/* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at - * noon of GMT (assume equal to UTC). However, this begins at - * midnight. - */ - -struct SimpleDateData -{ - unsigned flags; - VALUE nth; /* not always canonicalized */ - int jd; /* as utc */ - /* df is zero */ - /* sf is zero */ - /* of is zero */ -#ifndef USE_FLOAT - double sg; /* 2298874..2426355 or -/+oo */ -#else - float sg; /* at most 22 bits */ -#endif - /* decoded as utc=local */ - int year; /* truncated */ -#ifndef USE_PACK - int mon; - int mday; - /* hour is zero */ - /* min is zero */ - /* sec is zero */ -#else - /* packed civil */ - unsigned pc; -#endif -}; - -struct ComplexDateData -{ - unsigned flags; - VALUE nth; /* not always canonicalized */ - int jd; /* as utc */ - int df; /* as utc, in secs */ - VALUE sf; /* in nano secs */ - int of; /* in secs */ -#ifndef USE_FLOAT - double sg; /* 2298874..2426355 or -/+oo */ -#else - float sg; /* at most 22 bits */ -#endif - /* decoded as local */ - int year; /* truncated */ -#ifndef USE_PACK - int mon; - int mday; - int hour; - int min; - int sec; -#else - /* packed civil */ - unsigned pc; -#endif -}; - -union DateData { - unsigned flags; - struct SimpleDateData s; - struct ComplexDateData c; -}; - -#define get_d1(x)\ - union DateData *dat;\ - Data_Get_Struct(x, union DateData, dat); - -#define get_d1a(x)\ - union DateData *adat;\ - Data_Get_Struct(x, union DateData, adat); - -#define get_d1b(x)\ - union DateData *bdat;\ - Data_Get_Struct(x, union DateData, bdat); - -#define get_d2(x,y)\ - union DateData *adat, *bdat;\ - Data_Get_Struct(x, union DateData, adat);\ - Data_Get_Struct(y, union DateData, bdat); - -inline static VALUE -canon(VALUE x) -{ - if (TYPE(x) == T_RATIONAL) { - VALUE den = RRATIONAL(x)->den; - if (FIXNUM_P(den) && FIX2LONG(den) == 1) - return RRATIONAL(x)->num; - } - return x; -} - -#ifndef USE_PACK -#define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \ -{\ - (x)->nth = canon(_nth);\ - (x)->jd = _jd;\ - (x)->sg = (sg_cast)(_sg);\ - (x)->year = _year;\ - (x)->mon = _mon;\ - (x)->mday = _mday;\ - (x)->flags = _flags;\ -} -#else -#define set_to_simple(x, _nth, _jd ,_sg, _year, _mon, _mday, _flags) \ -{\ - (x)->nth = canon(_nth);\ - (x)->jd = _jd;\ - (x)->sg = (sg_cast)(_sg);\ - (x)->year = _year;\ - (x)->pc = PACK2(_mon, _mday);\ - (x)->flags = _flags;\ -} -#endif - -#ifndef USE_PACK -#define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\ -_year, _mon, _mday, _hour, _min, _sec, _flags) \ -{\ - (x)->nth = canon(_nth);\ - (x)->jd = _jd;\ - (x)->df = _df;\ - (x)->sf = canon(_sf);\ - (x)->of = _of;\ - (x)->sg = (sg_cast)(_sg);\ - (x)->year = _year;\ - (x)->mon = _mon;\ - (x)->mday = _mday;\ - (x)->hour = _hour;\ - (x)->min = _min;\ - (x)->sec = _sec;\ - (x)->flags = _flags;\ -} -#else -#define set_to_complex(x, _nth, _jd ,_df, _sf, _of, _sg,\ -_year, _mon, _mday, _hour, _min, _sec, _flags) \ -{\ - (x)->nth = canon(_nth);\ - (x)->jd = _jd;\ - (x)->df = _df;\ - (x)->sf = canon(_sf);\ - (x)->of = _of;\ - (x)->sg = (sg_cast)(_sg);\ - (x)->year = _year;\ - (x)->pc = PACK5(_mon, _mday, _hour, _min, _sec);\ - (x)->flags = _flags;\ -} -#endif - -#ifndef USE_PACK -#define copy_simple_to_complex(x, y) \ -{\ - (x)->nth = (y)->nth;\ - (x)->jd = (y)->jd;\ - (x)->df = 0;\ - (x)->sf = INT2FIX(0);\ - (x)->of = 0;\ - (x)->sg = (sg_cast)((y)->sg);\ - (x)->year = (y)->year;\ - (x)->mon = (y)->mon;\ - (x)->mday = (y)->mday;\ - (x)->hour = 0;\ - (x)->min = 0;\ - (x)->sec = 0;\ - (x)->flags = (y)->flags;\ -} -#else -#define copy_simple_to_complex(x, y) \ -{\ - (x)->nth = (y)->nth;\ - (x)->jd = (y)->jd;\ - (x)->df = 0;\ - (x)->sf = INT2FIX(0);\ - (x)->of = 0;\ - (x)->sg = (sg_cast)((y)->sg);\ - (x)->year = (y)->year;\ - (x)->pc = PACK5(EX_MON((y)->pc), EX_MDAY((y)->pc), 0, 0, 0);\ - (x)->flags = (y)->flags;\ -} -#endif - -#ifndef USE_PACK -#define copy_complex_to_simple(x, y) \ -{\ - (x)->nth = (y)->nth;\ - (x)->jd = (y)->jd;\ - (x)->sg = (sg_cast)((y)->sg);\ - (x)->year = (y)->year;\ - (x)->mon = (y)->mon;\ - (x)->mday = (y)->mday;\ - (x)->flags = (y)->flags;\ -} -#else -#define copy_complex_to_simple(x, y) \ -{\ - (x)->nth = (y)->nth;\ - (x)->jd = (y)->jd;\ - (x)->sg = (sg_cast)((y)->sg);\ - (x)->year = (y)->year;\ - (x)->pc = PACK2(EX_MON((y)->pc), EX_MDAY((y)->pc));\ - (x)->flags = (y)->flags;\ -} -#endif - -/* base */ - -static int c_valid_civil_p(int, int, int, double, - int *, int *, int *, int *); - -static int -c_find_fdoy(int y, double sg, int *rjd, int *ns) -{ - int d, rm, rd; - - for (d = 1; d < 31; d++) - if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns)) - return 1; - return 0; -} - -static int -c_find_ldoy(int y, double sg, int *rjd, int *ns) -{ - int i, rm, rd; - - for (i = 0; i < 30; i++) - if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns)) - return 1; - return 0; -} - -#ifndef NDEBUG -static int -c_find_fdom(int y, int m, double sg, int *rjd, int *ns) -{ - int d, rm, rd; - - for (d = 1; d < 31; d++) - if (c_valid_civil_p(y, m, d, sg, &rm, &rd, rjd, ns)) - return 1; - return 0; -} -#endif - -static int -c_find_ldom(int y, int m, double sg, int *rjd, int *ns) -{ - int i, rm, rd; - - for (i = 0; i < 30; i++) - if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns)) - return 1; - return 0; -} - -static void -c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns) -{ - double a, b, jd; - - if (m <= 2) { - y -= 1; - m += 12; - } - a = floor(y / 100.0); - b = 2 - a + floor(a / 4.0); - jd = floor(365.25 * (y + 4716)) + - floor(30.6001 * (m + 1)) + - d + b - 1524; - if (jd < sg) { - jd -= b; - *ns = 0; - } - else - *ns = 1; - - *rjd = (int)jd; -} - -static void -c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom) -{ - double x, a, b, c, d, e, y, m, dom; - - if (jd < sg) - a = jd; - else { - x = floor((jd - 1867216.25) / 36524.25); - a = jd + 1 + x - floor(x / 4.0); - } - b = a + 1524; - c = floor((b - 122.1) / 365.25); - d = floor(365.25 * c); - e = floor((b - d) / 30.6001); - dom = b - d - floor(30.6001 * e); - if (e <= 13) { - m = e - 1; - y = c - 4716; - } - else { - m = e - 13; - y = c - 4715; - } - - *ry = (int)y; - *rm = (int)m; - *rdom = (int)dom; -} - -static void -c_ordinal_to_jd(int y, int d, double sg, int *rjd, int *ns) -{ - int ns2; - - c_find_fdoy(y, sg, rjd, &ns2); - *rjd += d - 1; - *ns = (*rjd < sg) ? 0 : 1; -} - -static void -c_jd_to_ordinal(int jd, double sg, int *ry, int *rd) -{ - int rm2, rd2, rjd, ns; - - c_jd_to_civil(jd, sg, ry, &rm2, &rd2); - c_find_fdoy(*ry, sg, &rjd, &ns); - *rd = (jd - rjd) + 1; -} - -static void -c_commercial_to_jd(int y, int w, int d, double sg, int *rjd, int *ns) -{ - int rjd2, ns2; - - c_find_fdoy(y, sg, &rjd2, &ns2); - rjd2 += 3; - *rjd = - (rjd2 - MOD((rjd2 - 1) + 1, 7)) + - 7 * (w - 1) + - (d - 1); - *ns = (*rjd < sg) ? 0 : 1; -} - -static void -c_jd_to_commercial(int jd, double sg, int *ry, int *rw, int *rd) -{ - int ry2, rm2, rd2, a, rjd2, ns2; - - c_jd_to_civil(jd - 3, sg, &ry2, &rm2, &rd2); - a = ry2; - c_commercial_to_jd(a + 1, 1, 1, sg, &rjd2, &ns2); - if (jd >= rjd2) - *ry = a + 1; - else { - c_commercial_to_jd(a, 1, 1, sg, &rjd2, &ns2); - *ry = a; - } - *rw = 1 + DIV(jd - rjd2, 7); - *rd = MOD(jd + 1, 7); - if (*rd == 0) - *rd = 7; -} - -static void -c_weeknum_to_jd(int y, int w, int d, int f, double sg, int *rjd, int *ns) -{ - int rjd2, ns2; - - c_find_fdoy(y, sg, &rjd2, &ns2); - rjd2 += 6; - *rjd = (rjd2 - MOD(((rjd2 - f) + 1), 7) - 7) + 7 * w + d; - *ns = (*rjd < sg) ? 0 : 1; -} - -static void -c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd) -{ - int rm, rd2, rjd, ns, j; - - c_jd_to_civil(jd, sg, ry, &rm, &rd2); - c_find_fdoy(*ry, sg, &rjd, &ns); - rjd += 6; - j = jd - (rjd - MOD((rjd - f) + 1, 7)) + 7; - *rw = (int)DIV(j, 7); - *rd = (int)MOD(j, 7); -} - -#ifndef NDEBUG -static void -c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns) -{ - int rjd2, ns2; - - if (n > 0) { - c_find_fdom(y, m, sg, &rjd2, &ns2); - rjd2 -= 1; - } - else { - c_find_ldom(y, m, sg, &rjd2, &ns2); - rjd2 += 7; - } - *rjd = (rjd2 - MOD((rjd2 - k) + 1, 7)) + 7 * n; - *ns = (*rjd < sg) ? 0 : 1; -} -#endif - -inline static int -c_jd_to_wday(int jd) -{ - return MOD(jd + 1, 7); -} - -#ifndef NDEBUG -static void -c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk) -{ - int rd, rjd, ns2; - - c_jd_to_civil(jd, sg, ry, rm, &rd); - c_find_fdom(*ry, *rm, sg, &rjd, &ns2); - *rn = DIV(jd - rjd, 7) + 1; - *rk = c_jd_to_wday(jd); -} -#endif - -static int -c_valid_ordinal_p(int y, int d, double sg, - int *rd, int *rjd, int *ns) -{ - int ry2, rd2; - - if (d < 0) { - int rjd2, ns2; - - if (!c_find_ldoy(y, sg, &rjd2, &ns2)) - return 0; - c_jd_to_ordinal(rjd2 + d + 1, sg, &ry2, &rd2); - if (ry2 != y) - return 0; - d = rd2; - } - c_ordinal_to_jd(y, d, sg, rjd, ns); - c_jd_to_ordinal(*rjd, sg, &ry2, &rd2); - if (ry2 != y || rd2 != d) - return 0; - return 1; -} - -static const int monthtab[2][13] = { - { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -}; - -inline static int -c_julian_leap_p(int y) -{ - return MOD(y, 4) == 0; -} - -inline static int -c_gregorian_leap_p(int y) -{ - return MOD(y, 4) == 0 && y % 100 != 0 || MOD(y, 400) == 0; -} - -static int -c_julian_last_day_of_month(int y, int m) -{ - assert(m >= 1 && m <= 12); - return monthtab[c_julian_leap_p(y) ? 1 : 0][m]; -} - -static int -c_gregorian_last_day_of_month(int y, int m) -{ - assert(m >= 1 && m <= 12); - return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m]; -} - -static int -c_valid_julian_p(int y, int m, int d, int *rm, int *rd) -{ - int last; - - if (m < 0) - m += 13; - if (m < 1 || m > 12) - return 0; - last = c_julian_last_day_of_month(y, m); - if (d < 0) - d = last + d + 1; - if (d < 1 || d > last) - return 0; - *rm = m; - *rd = d; - return 1; -} - -static int -c_valid_gregorian_p(int y, int m, int d, int *rm, int *rd) -{ - int last; - - if (m < 0) - m += 13; - if (m < 1 || m > 12) - return 0; - last = c_gregorian_last_day_of_month(y, m); - if (d < 0) - d = last + d + 1; - if (d < 1 || d > last) - return 0; - *rm = m; - *rd = d; - return 1; -} - -static int -c_valid_civil_p(int y, int m, int d, double sg, - int *rm, int *rd, int *rjd, int *ns) -{ - int ry; - - if (m < 0) - m += 13; - if (d < 0) { - if (!c_find_ldom(y, m, sg, rjd, ns)) - return 0; - c_jd_to_civil(*rjd + d + 1, sg, &ry, rm, rd); - if (ry != y || *rm != m) - return 0; - d = *rd; - } - c_civil_to_jd(y, m, d, sg, rjd, ns); - c_jd_to_civil(*rjd, sg, &ry, rm, rd); - if (ry != y || *rm != m || *rd != d) - return 0; - return 1; -} - -static int -c_valid_commercial_p(int y, int w, int d, double sg, - int *rw, int *rd, int *rjd, int *ns) -{ - int ns2, ry2, rw2, rd2; - - if (d < 0) - d += 8; - if (w < 0) { - int rjd2; - - c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2); - c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2); - if (ry2 != y) - return 0; - w = rw2; - } - c_commercial_to_jd(y, w, d, sg, rjd, ns); - c_jd_to_commercial(*rjd, sg, &ry2, rw, rd); - if (y != ry2 || w != *rw || d != *rd) - return 0; - return 1; -} - -static int -c_valid_weeknum_p(int y, int w, int d, int f, double sg, - int *rw, int *rd, int *rjd, int *ns) -{ - int ns2, ry2, rw2, rd2; - - if (d < 0) - d += 7; - if (w < 0) { - int rjd2; - - c_weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2); - c_jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2); - if (ry2 != y) - return 0; - w = rw2; - } - c_weeknum_to_jd(y, w, d, f, sg, rjd, ns); - c_jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd); - if (y != ry2 || w != *rw || d != *rd) - return 0; - return 1; -} - -#ifndef NDEBUG -static int -c_valid_nth_kday_p(int y, int m, int n, int k, double sg, - int *rm, int *rn, int *rk, int *rjd, int *ns) -{ - int ns2, ry2, rm2, rn2, rk2; - - if (k < 0) - k += 7; - if (n < 0) { - int t, ny, nm, rjd2; - - t = y * 12 + m; - ny = DIV(t, 12); - nm = MOD(t, 12) + 1; - - c_nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2); - c_jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2); - if (ry2 != y || rm2 != m) - return 0; - n = rn2; - } - c_nth_kday_to_jd(y, m, n, k, sg, rjd, ns); - c_jd_to_nth_kday(*rjd, sg, &ry2, rm, rn, rk); - if (y != ry2 || m != *rm || n != *rn || k != *rk) - return 0; - return 1; -} -#endif - -static int -c_valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs) -{ - if (h < 0) - h += 24; - if (min < 0) - min += 60; - if (s < 0) - s += 60; - *rh = h; - *rmin = min; - *rs = s; - return !(h < 0 || h > 24 || - min < 0 || min > 59 || - s < 0 || s > 59 || - (h == 24 && (min > 0 || s > 0))); -} - -inline static int -c_valid_start_p(double sg) -{ - if (isnan(sg)) - return 0; - if (isinf(sg)) - return 1; - if (sg < REFORM_BEGIN_JD || sg > REFORM_END_JD) - return 0; - return 1; -} - -inline static int -df_local_to_utc(int df, int of) -{ - df -= of; - if (df < 0) - df += DAY_IN_SECONDS; - else if (df >= DAY_IN_SECONDS) - df -= DAY_IN_SECONDS; - return df; -} - -inline static int -df_utc_to_local(int df, int of) -{ - df += of; - if (df < 0) - df += DAY_IN_SECONDS; - else if (df >= DAY_IN_SECONDS) - df -= DAY_IN_SECONDS; - return df; -} - -inline static int -jd_local_to_utc(int jd, int df, int of) -{ - df -= of; - if (df < 0) - jd -= 1; - else if (df >= DAY_IN_SECONDS) - jd += 1; - return jd; -} - -inline static int -jd_utc_to_local(int jd, int df, int of) -{ - df += of; - if (df < 0) - jd -= 1; - else if (df >= DAY_IN_SECONDS) - jd += 1; - return jd; -} - -inline static int -time_to_df(int h, int min, int s) -{ - return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s; -} - -inline static void -df_to_time(int df, int *h, int *min, int *s) -{ - *h = df / HOUR_IN_SECONDS; - df %= HOUR_IN_SECONDS; - *min = df / MINUTE_IN_SECONDS; - *s = df % MINUTE_IN_SECONDS; -} - -static VALUE -sec_to_day(VALUE s) -{ - if (FIXNUM_P(s)) - return rb_rational_new2(s, INT2FIX(DAY_IN_SECONDS)); - return f_quo(s, INT2FIX(DAY_IN_SECONDS)); -} - -inline static VALUE -isec_to_day(int s) -{ - return sec_to_day(INT2FIX(s)); -} - -static VALUE -ns_to_day(VALUE n) -{ - if (FIXNUM_P(n)) - return rb_rational_new2(n, day_in_nanoseconds); - return f_quo(n, day_in_nanoseconds); -} - -#ifndef NDEBUG -static VALUE -ms_to_sec(VALUE m) -{ - if (FIXNUM_P(m)) - return rb_rational_new2(m, INT2FIX(SECOND_IN_MILLISECONDS)); - return f_quo(m, INT2FIX(SECOND_IN_MILLISECONDS)); -} -#endif - -static VALUE -ns_to_sec(VALUE n) -{ - if (FIXNUM_P(n)) - return rb_rational_new2(n, INT2FIX(SECOND_IN_NANOSECONDS)); - return f_quo(n, INT2FIX(SECOND_IN_NANOSECONDS)); -} - -#ifndef NDEBUG -inline static VALUE -ins_to_day(int n) -{ - return ns_to_day(INT2FIX(n)); -} -#endif - -static int -safe_mul_p(VALUE x, long m) -{ - long ix; - - if (!FIXNUM_P(x)) - return 0; - ix = FIX2LONG(x); - if (ix >= (FIXNUM_MAX / m)) - return 0; - return 1; -} - -static VALUE -day_to_sec(VALUE d) -{ - if (safe_mul_p(d, DAY_IN_SECONDS)) - return LONG2FIX(FIX2LONG(d) * DAY_IN_SECONDS); - return f_mul(d, INT2FIX(DAY_IN_SECONDS)); -} - -#ifndef NDEBUG -static VALUE -day_to_ns(VALUE d) -{ - return f_mul(d, day_in_nanoseconds); -} -#endif - -static VALUE -sec_to_ms(VALUE s) -{ - if (safe_mul_p(s, SECOND_IN_MILLISECONDS)) - return LONG2FIX(FIX2LONG(s) * SECOND_IN_MILLISECONDS); - return f_mul(s, INT2FIX(SECOND_IN_MILLISECONDS)); -} - -static VALUE -sec_to_ns(VALUE s) -{ - if (safe_mul_p(s, SECOND_IN_NANOSECONDS)) - return LONG2FIX(FIX2LONG(s) * SECOND_IN_NANOSECONDS); - return f_mul(s, INT2FIX(SECOND_IN_NANOSECONDS)); -} - -#ifndef NDEBUG -static VALUE -isec_to_ns(int s) -{ - return sec_to_ns(INT2FIX(s)); -} -#endif - -static VALUE -div_day(VALUE d, VALUE *f) -{ - if (f) - *f = f_mod(d, INT2FIX(1)); - return f_floor(d); -} - -static VALUE -div_df(VALUE d, VALUE *f) -{ - VALUE s = day_to_sec(d); - - if (f) - *f = f_mod(s, INT2FIX(1)); - return f_floor(s); -} - -#ifndef NDEBUG -static VALUE -div_sf(VALUE s, VALUE *f) -{ - VALUE n = sec_to_ns(s); - - if (f) - *f = f_mod(n, INT2FIX(1)); - return f_floor(n); -} -#endif - -static void -decode_day(VALUE d, VALUE *jd, VALUE *df, VALUE *sf) -{ - VALUE f; - - *jd = div_day(d, &f); - *df = div_df(f, &f); - *sf = sec_to_ns(f); -} - -inline static double -s_virtual_sg(union DateData *x) -{ - if (isinf(x->s.sg)) - return x->s.sg; - if (f_zero_p(x->s.nth)) - return x->s.sg; - else if (f_negative_p(x->s.nth)) - return positive_inf; - return negative_inf; -} - -inline static double -c_virtual_sg(union DateData *x) -{ - if (isinf(x->c.sg)) - return x->c.sg; - if (f_zero_p(x->c.nth)) - return x->c.sg; - else if (f_negative_p(x->c.nth)) - return positive_inf; - return negative_inf; -} - -inline static double -m_virtual_sg(union DateData *x) -{ - if (simple_dat_p(x)) - return s_virtual_sg(x); - else - return c_virtual_sg(x); -} - -inline static void -get_s_jd(union DateData *x) -{ - assert(simple_dat_p(x)); - if (!have_jd_p(x)) { - int jd, ns; - - assert(have_civil_p(x)); -#ifndef USE_PACK - c_civil_to_jd(x->s.year, x->s.mon, x->s.mday, - s_virtual_sg(x), &jd, &ns); -#else - c_civil_to_jd(x->s.year, EX_MON(x->s.pc), EX_MDAY(x->s.pc), - s_virtual_sg(x), &jd, &ns); -#endif - x->s.jd = jd; - x->s.flags |= HAVE_JD; - } -} - -inline static void -get_s_civil(union DateData *x) -{ - assert(simple_dat_p(x)); - if (!have_civil_p(x)) { - int y, m, d; - - assert(have_jd_p(x)); - c_jd_to_civil(x->s.jd, s_virtual_sg(x), &y, &m, &d); - x->s.year = y; -#ifndef USE_PACK - x->s.mon = m; - x->s.mday = d; -#else - x->s.pc = PACK2(m, d); -#endif - x->s.flags |= HAVE_CIVIL; - } -} - -inline static void -get_c_df(union DateData *x) -{ - assert(complex_dat_p(x)); - if (!have_df_p(x)) { - assert(have_time_p(x)); -#ifndef USE_PACK - x->c.df = df_local_to_utc(time_to_df(x->c.hour, x->c.min, x->c.sec), - x->c.of); -#else - x->c.df = df_local_to_utc(time_to_df(EX_HOUR(x->c.pc), - EX_MIN(x->c.pc), - EX_SEC(x->c.pc)), - x->c.of); -#endif - x->c.flags |= HAVE_DF; - } -} - -inline static void -get_c_time(union DateData *x) -{ - assert(complex_dat_p(x)); - if (!have_time_p(x)) { -#ifndef USE_PACK - int r; - assert(have_df_p(x)); - r = df_utc_to_local(x->c.df, x->c.of); - df_to_time(r, &x->c.hour, &x->c.min, &x->c.sec); - x->c.flags |= HAVE_TIME; -#else - int r, m, d, h, min, s; - - assert(have_df_p(x)); - m = EX_MON(x->c.pc); - d = EX_MDAY(x->c.pc); - r = df_utc_to_local(x->c.df, x->c.of); - df_to_time(r, &h, &min, &s); - x->c.pc = PACK5(m, d, h, min, s); - x->c.flags |= HAVE_TIME; -#endif - } -} - -inline static void -get_c_jd(union DateData *x) -{ - assert(complex_dat_p(x)); - if (!have_jd_p(x)) { - int jd, ns; - - assert(have_civil_p(x)); -#ifndef USE_PACK - c_civil_to_jd(x->c.year, x->c.mon, x->c.mday, - c_virtual_sg(x), &jd, &ns); -#else - c_civil_to_jd(x->c.year, EX_MON(x->c.pc), EX_MDAY(x->c.pc), - c_virtual_sg(x), &jd, &ns); -#endif - - get_c_time(x); -#ifndef USE_PACK - x->c.jd = jd_local_to_utc(jd, - time_to_df(x->c.hour, x->c.min, x->c.sec), - x->c.of); -#else - x->c.jd = jd_local_to_utc(jd, - time_to_df(EX_HOUR(x->c.pc), - EX_MIN(x->c.pc), - EX_SEC(x->c.pc)), - x->c.of); -#endif - x->c.flags |= HAVE_JD; - } -} - -inline static void -get_c_civil(union DateData *x) -{ - assert(complex_dat_p(x)); - if (!have_civil_p(x)) { -#ifndef USE_PACK - int jd, y, m, d; -#else - int jd, y, m, d, h, min, s; -#endif - - assert(have_jd_p(x)); - get_c_df(x); - jd = jd_utc_to_local(x->c.jd, x->c.df, x->c.of); - c_jd_to_civil(jd, c_virtual_sg(x), &y, &m, &d); - x->c.year = y; -#ifndef USE_PACK - x->c.mon = m; - x->c.mday = d; -#else - h = EX_HOUR(x->c.pc); - min = EX_MIN(x->c.pc); - s = EX_SEC(x->c.pc); - x->c.pc = PACK5(m, d, h, min, s); -#endif - x->c.flags |= HAVE_CIVIL; - } -} - -inline static int -local_jd(union DateData *x) -{ - assert(complex_dat_p(x)); - assert(have_jd_p(x)); - assert(have_df_p(x)); - return jd_utc_to_local(x->c.jd, x->c.df, x->c.of); -} - -inline static int -local_df(union DateData *x) -{ - assert(complex_dat_p(x)); - assert(have_df_p(x)); - return df_utc_to_local(x->c.df, x->c.of); -} - -static void -decode_year(VALUE y, double style, - VALUE *nth, int *ry) -{ - int period; - VALUE t; - - period = (style < 0) ? - CM_PERIOD_GCY : - CM_PERIOD_JCY; - if (FIXNUM_P(y)) { - long iy, it, inth; - - iy = FIX2LONG(y); - if (iy >= (FIXNUM_MAX - 4712)) - goto big; - it = iy + 4712; /* shift */ - inth = DIV(it, ((long)period)); - *nth = LONG2FIX(inth); - if (inth) - it = MOD(it, ((long)period)); - *ry = (int)it - 4712; /* unshift */ - return; - } - big: - t = f_add(y, INT2FIX(4712)); /* shift */ - *nth = f_idiv(t, INT2FIX(period)); - if (f_nonzero_p(*nth)) - t = f_mod(t, INT2FIX(period)); - *ry = FIX2INT(t) - 4712; /* unshift */ -} - -static void -encode_year(VALUE nth, int y, double style, - VALUE *ry) -{ - int period; - VALUE t; - - period = (style < 0) ? - CM_PERIOD_GCY : - CM_PERIOD_JCY; - if (f_zero_p(nth)) - *ry = INT2FIX(y); - else { - t = f_mul(INT2FIX(period), nth); - t = f_add(t, INT2FIX(y)); - *ry = t; - } -} - -static void -decode_jd(VALUE jd, VALUE *nth, int *rjd) -{ - assert(FIXNUM_P(jd) || RB_TYPE_P(jd, T_BIGNUM)); - *nth = f_idiv(jd, INT2FIX(CM_PERIOD)); - if (f_zero_p(*nth)) { - assert(FIXNUM_P(jd)); - *rjd = FIX2INT(jd); - return; - } - *rjd = FIX2INT(f_mod(jd, INT2FIX(CM_PERIOD))); -} - -static void -encode_jd(VALUE nth, int jd, VALUE *rjd) -{ - if (f_zero_p(nth)) { - *rjd = INT2FIX(jd); - return; - } - *rjd = f_add(f_mul(INT2FIX(CM_PERIOD), nth), INT2FIX(jd)); -} - -inline static double -guess_style(VALUE y, double sg) /* -/+oo or zero */ -{ - double style = 0; - - if (isinf(sg)) - style = sg; - else if (!FIXNUM_P(y)) - style = f_positive_p(y) ? negative_inf : positive_inf; - else { - long iy = FIX2LONG(y); - - assert(FIXNUM_P(y)); - if (iy < REFORM_BEGIN_YEAR) - style = positive_inf; - else if (iy > REFORM_END_YEAR) - style = negative_inf; - } - return style; -} - -inline static VALUE -m_nth(union DateData *x) -{ - if (simple_dat_p(x)) - return x->s.nth; - else { - get_c_civil(x); - return x->c.nth; - } -} - -inline static int -m_jd(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_jd(x); - return x->s.jd; - } - else { - get_c_jd(x); - return x->c.jd; - } -} - -static VALUE -m_real_jd(union DateData *x) -{ - VALUE nth, rjd; - int jd; - - nth = m_nth(x); - jd = m_jd(x); - - encode_jd(nth, jd, &rjd); - return rjd; -} - -static int -m_local_jd(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_jd(x); - return x->s.jd; - } - else { - get_c_jd(x); - get_c_df(x); - return local_jd(x); - } -} - -static VALUE -m_real_local_jd(union DateData *x) -{ - VALUE nth, rjd; - int jd; - - nth = m_nth(x); - jd = m_local_jd(x); - - encode_jd(nth, jd, &rjd); - return rjd; -} - -inline static int -m_df(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_df(x); - return x->c.df; - } -} - -#ifndef NDEBUG -static VALUE -m_df_in_day(union DateData *x) -{ - return isec_to_day(m_df(x)); -} -#endif - -static int -m_local_df(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_df(x); - return local_df(x); - } -} - -#ifndef NDEBUG -static VALUE -m_local_df_in_day(union DateData *x) -{ - return isec_to_day(m_local_df(x)); -} -#endif - -inline static VALUE -m_sf(union DateData *x) -{ - if (simple_dat_p(x)) - return INT2FIX(0); - else - return x->c.sf; -} - -#ifndef NDEBUG -static VALUE -m_sf_in_day(union DateData *x) -{ - return ns_to_day(m_sf(x)); -} -#endif - -static VALUE -m_sf_in_sec(union DateData *x) -{ - return ns_to_sec(m_sf(x)); -} - -static VALUE -m_fr(union DateData *x) -{ - if (simple_dat_p(x)) - return INT2FIX(0); - else { - int df; - VALUE sf, fr; - - df = m_local_df(x); - sf = m_sf(x); - fr = isec_to_day(df); - if (f_nonzero_p(sf)) - fr = f_add(fr, ns_to_day(sf)); - return fr; - } -} - -#define HALF_DAYS_IN_SECONDS (DAY_IN_SECONDS / 2) - -static VALUE -m_ajd(union DateData *x) -{ - VALUE r, sf; - int df; - - if (simple_dat_p(x)) { - r = m_real_jd(x); - if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) { - long ir = FIX2LONG(r); - ir = ir * 2 - 1; - return rb_rational_new2(LONG2FIX(ir), INT2FIX(2)); - } - else - return rb_rational_new2(f_sub(f_mul(r, - INT2FIX(2)), - INT2FIX(1)), - INT2FIX(2)); - } - - r = m_real_jd(x); - df = m_df(x); - df -= HALF_DAYS_IN_SECONDS; - if (df) - r = f_add(r, isec_to_day(df)); - sf = m_sf(x); - if (f_nonzero_p(sf)) - r = f_add(r, ns_to_day(sf)); - - return r; -} - -static VALUE -m_amjd(union DateData *x) -{ - VALUE r, sf; - int df; - - r = m_real_jd(x); - if (FIXNUM_P(r) && FIX2LONG(r) >= (FIXNUM_MIN + 2400001)) { - long ir = FIX2LONG(r); - ir -= 2400001; - r = rb_rational_new1(LONG2FIX(ir)); - } - else - r = rb_rational_new1(f_sub(m_real_jd(x), - INT2FIX(2400001))); - - if (simple_dat_p(x)) - return r; - - df = m_df(x); - if (df) - r = f_add(r, isec_to_day(df)); - sf = m_sf(x); - if (f_nonzero_p(sf)) - r = f_add(r, ns_to_day(sf)); - - return r; -} - -inline static int -m_of(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_jd(x); - return x->c.of; - } -} - -static VALUE -m_of_in_day(union DateData *x) -{ - return isec_to_day(m_of(x)); -} - -inline static double -m_sg(union DateData *x) -{ - if (simple_dat_p(x)) - return x->s.sg; - else { - get_c_jd(x); - return x->c.sg; - } -} - -static int -m_julian_p(union DateData *x) -{ - int jd; - double sg; - - if (simple_dat_p(x)) { - get_s_jd(x); - jd = x->s.jd; - sg = s_virtual_sg(x); - } - else { - get_c_jd(x); - jd = x->c.jd; - sg = c_virtual_sg(x); - } - if (isinf(sg)) - return sg == positive_inf; - return jd < sg; -} - -inline static int -m_gregorian_p(union DateData *x) -{ - return !m_julian_p(x); -} - -inline static int -m_proleptic_julian_p(union DateData *x) -{ - double sg; - - sg = m_sg(x); - if (isinf(sg) && sg > 0) - return 1; - return 0; -} - -inline static int -m_proleptic_gregorian_p(union DateData *x) -{ - double sg; - - sg = m_sg(x); - if (isinf(sg) && sg < 0) - return 1; - return 0; -} - -inline static int -m_year(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_civil(x); - return x->s.year; - } - else { - get_c_civil(x); - return x->c.year; - } -} - -static VALUE -m_real_year(union DateData *x) -{ - VALUE nth, ry; - int year; - - nth = m_nth(x); - year = m_year(x); - - if (f_zero_p(nth)) - return INT2FIX(year); - - encode_year(nth, year, - m_gregorian_p(x) ? -1 : +1, - &ry); - return ry; -} - - -#ifdef USE_PACK -inline static int -m_pc(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_civil(x); - return x->s.pc; - } - else { - get_c_civil(x); - get_c_time(x); - return x->c.pc; - } -} -#endif - -inline static int -m_mon(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_civil(x); -#ifndef USE_PACK - return x->s.mon; -#else - return EX_MON(x->s.pc); -#endif - } - else { - get_c_civil(x); -#ifndef USE_PACK - return x->c.mon; -#else - return EX_MON(x->c.pc); -#endif - } -} - -inline static int -m_mday(union DateData *x) -{ - if (simple_dat_p(x)) { - get_s_civil(x); -#ifndef USE_PACK - return x->s.mday; -#else - return EX_MDAY(x->s.pc); -#endif - } - else { - get_c_civil(x); -#ifndef USE_PACK - return x->c.mday; -#else - return EX_MDAY(x->c.pc); -#endif - } -} - -static const int yeartab[2][13] = { - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, - { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } -}; - -static int -c_julian_to_yday(int y, int m, int d) -{ - assert(m >= 1 && m <= 12); - return yeartab[c_julian_leap_p(y) ? 1 : 0][m] + d; -} - -static int -c_gregorian_to_yday(int y, int m, int d) -{ - assert(m >= 1 && m <= 12); - return yeartab[c_gregorian_leap_p(y) ? 1 : 0][m] + d; -} - -static int -m_yday(union DateData *x) -{ - int jd, ry, rd; - double sg; - - jd = m_local_jd(x); - sg = m_virtual_sg(x); /* !=m_sg() */ - - if (m_proleptic_gregorian_p(x) || - (jd - sg) > 366) - return c_gregorian_to_yday(m_year(x), m_mon(x), m_mday(x)); - if (m_proleptic_julian_p(x)) - return c_julian_to_yday(m_year(x), m_mon(x), m_mday(x)); - c_jd_to_ordinal(jd, sg, &ry, &rd); - return rd; -} - -static int -m_wday(union DateData *x) -{ - return c_jd_to_wday(m_local_jd(x)); -} - -static int -m_cwyear(union DateData *x) -{ - int ry, rw, rd; - - c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */ - &ry, &rw, &rd); - return ry; -} - -static VALUE -m_real_cwyear(union DateData *x) -{ - VALUE nth, ry; - int year; - - nth = m_nth(x); - year = m_cwyear(x); - - if (f_zero_p(nth)) - return INT2FIX(year); - - encode_year(nth, year, - m_gregorian_p(x) ? -1 : +1, - &ry); - return ry; -} - -static int -m_cweek(union DateData *x) -{ - int ry, rw, rd; - - c_jd_to_commercial(m_local_jd(x), m_virtual_sg(x), /* !=m_sg() */ - &ry, &rw, &rd); - return rw; -} - -static int -m_cwday(union DateData *x) -{ - int w; - - w = m_wday(x); - if (w == 0) - w = 7; - return w; -} - -static int -m_wnumx(union DateData *x, int f) -{ - int ry, rw, rd; - - c_jd_to_weeknum(m_local_jd(x), f, m_virtual_sg(x), /* !=m_sg() */ - &ry, &rw, &rd); - return rw; -} - -static int -m_wnum0(union DateData *x) -{ - return m_wnumx(x, 0); -} - -static int -m_wnum1(union DateData *x) -{ - return m_wnumx(x, 1); -} - -inline static int -m_hour(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_time(x); -#ifndef USE_PACK - return x->c.hour; -#else - return EX_HOUR(x->c.pc); -#endif - } -} - -inline static int -m_min(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_time(x); -#ifndef USE_PACK - return x->c.min; -#else - return EX_MIN(x->c.pc); -#endif - } -} - -inline static int -m_sec(union DateData *x) -{ - if (simple_dat_p(x)) - return 0; - else { - get_c_time(x); -#ifndef USE_PACK - return x->c.sec; -#else - return EX_SEC(x->c.pc); -#endif - } -} - -#define decode_offset(of,s,h,m)\ -{\ - int a;\ - s = (of < 0) ? '-' : '+';\ - a = (of < 0) ? -of : of;\ - h = a / HOUR_IN_SECONDS;\ - m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\ -} - -static VALUE -of2str(int of) -{ - int s, h, m; - - decode_offset(of, s, h, m); - return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m); -} - -static VALUE -m_zone(union DateData *x) -{ - if (simple_dat_p(x)) - return rb_usascii_str_new2("+00:00"); - return of2str(m_of(x)); -} - -inline static VALUE -f_kind_of_p(VALUE x, VALUE c) -{ - return rb_obj_is_kind_of(x, c); -} - -inline static VALUE -k_date_p(VALUE x) -{ - return f_kind_of_p(x, cDate); -} - -inline static VALUE -k_datetime_p(VALUE x) -{ - return f_kind_of_p(x, cDateTime); -} - -inline static VALUE -k_numeric_p(VALUE x) -{ - return f_kind_of_p(x, rb_cNumeric); -} - -inline static VALUE -k_rational_p(VALUE x) -{ - return f_kind_of_p(x, rb_cRational); -} - -#ifndef NDEBUG -static void -civil_to_jd(VALUE y, int m, int d, double sg, - VALUE *nth, int *ry, - int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - - if (style == 0) { - int jd; - - c_civil_to_jd(FIX2INT(y), m, d, sg, &jd, ns); - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - c_civil_to_jd(*ry, m, d, style, rjd, ns); - } -} - -static void -jd_to_civil(VALUE jd, double sg, - VALUE *nth, int *rjd, - int *ry, int *rm, int *rd) -{ - decode_jd(jd, nth, rjd); - c_jd_to_civil(*rjd, sg, ry, rm, rd); -} - -static void -ordinal_to_jd(VALUE y, int d, double sg, - VALUE *nth, int *ry, - int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - - if (style == 0) { - int jd; - - c_ordinal_to_jd(FIX2INT(y), d, sg, &jd, ns); - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - c_ordinal_to_jd(*ry, d, style, rjd, ns); - } -} - -static void -jd_to_ordinal(VALUE jd, double sg, - VALUE *nth, int *rjd, - int *ry, int *rd) -{ - decode_jd(jd, nth, rjd); - c_jd_to_ordinal(*rjd, sg, ry, rd); -} - -static void -commercial_to_jd(VALUE y, int w, int d, double sg, - VALUE *nth, int *ry, - int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - - if (style == 0) { - int jd; - - c_commercial_to_jd(FIX2INT(y), w, d, sg, &jd, ns); - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - c_commercial_to_jd(*ry, w, d, style, rjd, ns); - } -} - -static void -jd_to_commercial(VALUE jd, double sg, - VALUE *nth, int *rjd, - int *ry, int *rw, int *rd) -{ - decode_jd(jd, nth, rjd); - c_jd_to_commercial(*rjd, sg, ry, rw, rd); -} - -static void -weeknum_to_jd(VALUE y, int w, int d, int f, double sg, - VALUE *nth, int *ry, - int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - - if (style == 0) { - int jd; - - c_weeknum_to_jd(FIX2INT(y), w, d, f, sg, &jd, ns); - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - c_weeknum_to_jd(*ry, w, d, f, style, rjd, ns); - } -} - -static void -jd_to_weeknum(VALUE jd, int f, double sg, - VALUE *nth, int *rjd, - int *ry, int *rw, int *rd) -{ - decode_jd(jd, nth, rjd); - c_jd_to_weeknum(*rjd, f, sg, ry, rw, rd); -} - -static void -nth_kday_to_jd(VALUE y, int m, int n, int k, double sg, - VALUE *nth, int *ry, - int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - - if (style == 0) { - int jd; - - c_nth_kday_to_jd(FIX2INT(y), m, n, k, sg, &jd, ns); - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - c_nth_kday_to_jd(*ry, m, n, k, style, rjd, ns); - } -} - -static void -jd_to_nth_kday(VALUE jd, double sg, - VALUE *nth, int *rjd, - int *ry, int *rm, int *rn, int *rk) -{ - decode_jd(jd, nth, rjd); - c_jd_to_nth_kday(*rjd, sg, ry, rm, rn, rk); -} -#endif - -static int -valid_ordinal_p(VALUE y, int d, double sg, - VALUE *nth, int *ry, - int *rd, int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - int r; - - if (style == 0) { - int jd; - - r = c_valid_ordinal_p(FIX2INT(y), d, sg, rd, &jd, ns); - if (!r) - return 0; - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - r = c_valid_ordinal_p(*ry, d, style, rd, rjd, ns); - } - return r; -} - -static int -valid_gregorian_p(VALUE y, int m, int d, - VALUE *nth, int *ry, - int *rm, int *rd) -{ - decode_year(y, -1, nth, ry); - return c_valid_gregorian_p(*ry, m, d, rm, rd); -} - -static int -valid_civil_p(VALUE y, int m, int d, double sg, - VALUE *nth, int *ry, - int *rm, int *rd, int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - int r; - - if (style == 0) { - int jd; - - r = c_valid_civil_p(FIX2INT(y), m, d, sg, rm, rd, &jd, ns); - if (!r) - return 0; - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - if (style < 0) - r = c_valid_gregorian_p(*ry, m, d, rm, rd); - else - r = c_valid_julian_p(*ry, m, d, rm, rd); - if (!r) - return 0; - c_civil_to_jd(*ry, *rm, *rd, style, rjd, ns); - } - return r; -} - -static int -valid_commercial_p(VALUE y, int w, int d, double sg, - VALUE *nth, int *ry, - int *rw, int *rd, int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - int r; - - if (style == 0) { - int jd; - - r = c_valid_commercial_p(FIX2INT(y), w, d, sg, rw, rd, &jd, ns); - if (!r) - return 0; - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - r = c_valid_commercial_p(*ry, w, d, style, rw, rd, rjd, ns); - } - return r; -} - -static int -valid_weeknum_p(VALUE y, int w, int d, int f, double sg, - VALUE *nth, int *ry, - int *rw, int *rd, int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - int r; - - if (style == 0) { - int jd; - - r = c_valid_weeknum_p(FIX2INT(y), w, d, f, sg, rw, rd, &jd, ns); - if (!r) - return 0; - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - r = c_valid_weeknum_p(*ry, w, d, f, style, rw, rd, rjd, ns); - } - return r; -} - -#ifndef NDEBUG -static int -valid_nth_kday_p(VALUE y, int m, int n, int k, double sg, - VALUE *nth, int *ry, - int *rm, int *rn, int *rk, int *rjd, - int *ns) -{ - double style = guess_style(y, sg); - int r; - - if (style == 0) { - int jd; - - r = c_valid_nth_kday_p(FIX2INT(y), m, n, k, sg, rm, rn, rk, &jd, ns); - if (!r) - return 0; - decode_jd(INT2FIX(jd), nth, rjd); - if (f_zero_p(*nth)) - *ry = FIX2INT(y); - else { - VALUE nth2; - decode_year(y, ns ? -1 : +1, &nth2, ry); - } - } - else { - decode_year(y, style, nth, ry); - r = c_valid_nth_kday_p(*ry, m, n, k, style, rm, rn, rk, rjd, ns); - } - return r; -} -#endif - -VALUE date_zone_to_diff(VALUE); - -static int -offset_to_sec(VALUE vof, int *rof) -{ - switch (TYPE(vof)) { - case T_FIXNUM: - { - long n; - - n = FIX2LONG(vof); - if (n != -1 && n != 0 && n != 1) - return 0; - *rof = (int)n * DAY_IN_SECONDS; - return 1; - } - case T_FLOAT: - { - double n; - - n = RFLOAT_VALUE(vof) * DAY_IN_SECONDS; - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = (int)round(n); - if (*rof != n) - rb_warning("fraction of offset is ignored"); - return 1; - } - default: - if (!k_numeric_p(vof)) - rb_raise(rb_eTypeError, "expected numeric"); - vof = f_to_r(vof); -#ifdef CANONICALIZATION_FOR_MATHN - if (!k_rational_p(vof)) - return offset_to_sec(vof, rof); -#endif - /* fall through */ - case T_RATIONAL: - { - VALUE vs, vn, vd; - long n; - - vs = day_to_sec(vof); - -#ifdef CANONICALIZATION_FOR_MATHN - if (!k_rational_p(vs)) { - if (!FIXNUM_P(vs)) - return 0; - n = FIX2LONG(vs); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = (int)n; - return 1; - } -#endif - vn = RRATIONAL(vs)->num; - vd = RRATIONAL(vs)->den; - - if (FIXNUM_P(vn) && FIXNUM_P(vd) && (FIX2LONG(vd) == 1)) - n = FIX2LONG(vn); - else { - vn = f_round(vs); - if (!f_eqeq_p(vn, vs)) - rb_warning("fraction of offset is ignored"); - if (!FIXNUM_P(vn)) - return 0; - n = FIX2LONG(vn); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - } - *rof = (int)n; - return 1; - } - case T_STRING: - { - VALUE vs = date_zone_to_diff(vof); - long n; - - if (!FIXNUM_P(vs)) - return 0; - n = FIX2LONG(vs); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = (int)n; - return 1; - } - } - return 0; -} - -/* date */ - -#define valid_sg(sg) \ -{\ - if (!c_valid_start_p(sg)) {\ - sg = 0;\ - rb_warning("invalid start is ignored");\ - }\ -} - -static VALUE -valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - double sg = NUM2DBL(argv[1]); - valid_sg(sg); - return argv[0]; -} - -#ifndef NDEBUG -static VALUE -date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vjd, vsg; - VALUE argv2[2]; - - rb_scan_args(argc, argv, "11", &vjd, &vsg); - - argv2[0] = vjd; - if (argc < 2) - argv2[1] = DBL2NUM(GREGORIAN); - else - argv2[1] = vsg; - - return valid_jd_sub(2, argv2, klass, 1); -} -#endif - -/* - * call-seq: - * Date.valid_jd?(jd[, start=Date::ITALY]) -> bool - * - * Just returns true. It's nonsense, but is for symmetry. - * - * For example: - * - * Date.valid_jd?(2451944) #=> true - * - * See also jd. - */ -static VALUE -date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vjd, vsg; - VALUE argv2[2]; - - rb_scan_args(argc, argv, "11", &vjd, &vsg); - - argv2[0] = vjd; - if (argc < 2) - argv2[1] = INT2FIX(DEFAULT_SG); - else - argv2[1] = vsg; - - if (NIL_P(valid_jd_sub(2, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -static VALUE -valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - VALUE nth, y; - int m, d, ry, rm, rd; - double sg; - - y = argv[0]; - m = NUM2INT(argv[1]); - d = NUM2INT(argv[2]); - sg = NUM2DBL(argv[3]); - - valid_sg(sg); - - if (!need_jd && (guess_style(y, sg) < 0)) { - if (!valid_gregorian_p(y, m, d, - &nth, &ry, - &rm, &rd)) - return Qnil; - return INT2FIX(0); /* dummy */ - } - else { - int rjd, ns; - VALUE rjd2; - - if (!valid_civil_p(y, m, d, sg, - &nth, &ry, - &rm, &rd, &rjd, - &ns)) - return Qnil; - if (!need_jd) - return INT2FIX(0); /* dummy */ - encode_jd(nth, rjd, &rjd2); - return rjd2; - } -} - -#ifndef NDEBUG -static VALUE -date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vd, vsg; - VALUE argv2[4]; - - rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vm; - argv2[2] = vd; - if (argc < 4) - argv2[3] = DBL2NUM(GREGORIAN); - else - argv2[3] = vsg; - - return valid_civil_sub(4, argv2, klass, 1); -} -#endif - -/* - * call-seq: - * Date.valid_civil?(year, month, mday[, start=Date::ITALY]) -> bool - * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool - * - * Returns true if the given calendar date is valid, and false if not. - * - * For example: - * - * Date.valid_date?(2001,2,3) #=> true - * Date.valid_date?(2001,2,29) #=> false - * - * See also jd and civil. - */ -static VALUE -date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vd, vsg; - VALUE argv2[4]; - - rb_scan_args(argc, argv, "31", &vy, &vm, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vm; - argv2[2] = vd; - if (argc < 4) - argv2[3] = INT2FIX(DEFAULT_SG); - else - argv2[3] = vsg; - - if (NIL_P(valid_civil_sub(4, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -static VALUE -valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - VALUE nth, y; - int d, ry, rd; - double sg; - - y = argv[0]; - d = NUM2INT(argv[1]); - sg = NUM2DBL(argv[2]); - - valid_sg(sg); - - { - int rjd, ns; - VALUE rjd2; - - if (!valid_ordinal_p(y, d, sg, - &nth, &ry, - &rd, &rjd, - &ns)) - return Qnil; - if (!need_jd) - return INT2FIX(0); /* dummy */ - encode_jd(nth, rjd, &rjd2); - return rjd2; - } -} - -#ifndef NDEBUG -static VALUE -date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vd, vsg; - VALUE argv2[3]; - - rb_scan_args(argc, argv, "21", &vy, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vd; - if (argc < 3) - argv2[2] = DBL2NUM(GREGORIAN); - else - argv2[2] = vsg; - - return valid_ordinal_sub(3, argv2, klass, 1); -} -#endif - -/* - * call-seq: - * Date.valid_ordinal?(year, yday[, start=Date::ITALY]) -> bool - * - * Returns true if the given ordinal date is valid, and false if not. - * - * For example: - * - * Date.valid_ordinal?(2001,34) #=> true - * Date.valid_ordinal?(2001,366) #=> false - * - * See also jd and ordinal. - */ -static VALUE -date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vd, vsg; - VALUE argv2[3]; - - rb_scan_args(argc, argv, "21", &vy, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vd; - if (argc < 3) - argv2[2] = INT2FIX(DEFAULT_SG); - else - argv2[2] = vsg; - - if (NIL_P(valid_ordinal_sub(3, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -static VALUE -valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - VALUE nth, y; - int w, d, ry, rw, rd; - double sg; - - y = argv[0]; - w = NUM2INT(argv[1]); - d = NUM2INT(argv[2]); - sg = NUM2DBL(argv[3]); - - valid_sg(sg); - - { - int rjd, ns; - VALUE rjd2; - - if (!valid_commercial_p(y, w, d, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - return Qnil; - if (!need_jd) - return INT2FIX(0); /* dummy */ - encode_jd(nth, rjd, &rjd2); - return rjd2; - } -} - -#ifndef NDEBUG -static VALUE -date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vsg; - VALUE argv2[4]; - - rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vw; - argv2[2] = vd; - if (argc < 4) - argv2[3] = DBL2NUM(GREGORIAN); - else - argv2[3] = vsg; - - return valid_commercial_sub(4, argv2, klass, 1); -} -#endif - -/* - * call-seq: - * Date.valid_commercial?(cwyear, cweek, cwday[, start=Date::ITALY]) -> bool - * - * Returns true if the given week date is valid, and false if not. - * - * For example: - * - * Date.valid_commercial?(2001,5,6) #=> true - * Date.valid_commercial?(2001,5,8) #=> false - * - * See also jd and commercial. - */ -static VALUE -date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vsg; - VALUE argv2[4]; - - rb_scan_args(argc, argv, "31", &vy, &vw, &vd, &vsg); - - argv2[0] = vy; - argv2[1] = vw; - argv2[2] = vd; - if (argc < 4) - argv2[3] = INT2FIX(DEFAULT_SG); - else - argv2[3] = vsg; - - if (NIL_P(valid_commercial_sub(4, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -#ifndef NDEBUG -static VALUE -valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - VALUE nth, y; - int w, d, f, ry, rw, rd; - double sg; - - y = argv[0]; - w = NUM2INT(argv[1]); - d = NUM2INT(argv[2]); - f = NUM2INT(argv[3]); - sg = NUM2DBL(argv[4]); - - valid_sg(sg); - - { - int rjd, ns; - VALUE rjd2; - - if (!valid_weeknum_p(y, w, d, f, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - return Qnil; - if (!need_jd) - return INT2FIX(0); /* dummy */ - encode_jd(nth, rjd, &rjd2); - return rjd2; - } -} - -static VALUE -date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vf, vsg; - VALUE argv2[5]; - - rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg); - - argv2[0] = vy; - argv2[1] = vw; - argv2[2] = vd; - argv2[3] = vf; - if (argc < 5) - argv2[4] = DBL2NUM(GREGORIAN); - else - argv2[4] = vsg; - - return valid_weeknum_sub(5, argv2, klass, 1); -} - -static VALUE -date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vf, vsg; - VALUE argv2[5]; - - rb_scan_args(argc, argv, "41", &vy, &vw, &vd, &vf, &vsg); - - argv2[0] = vy; - argv2[1] = vw; - argv2[2] = vd; - argv2[3] = vf; - if (argc < 5) - argv2[4] = INT2FIX(DEFAULT_SG); - else - argv2[4] = vsg; - - if (NIL_P(valid_weeknum_sub(5, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -static VALUE -valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd) -{ - VALUE nth, y; - int m, n, k, ry, rm, rn, rk; - double sg; - - y = argv[0]; - m = NUM2INT(argv[1]); - n = NUM2INT(argv[2]); - k = NUM2INT(argv[3]); - sg = NUM2DBL(argv[4]); - - { - int rjd, ns; - VALUE rjd2; - - if (!valid_nth_kday_p(y, m, n, k, sg, - &nth, &ry, - &rm, &rn, &rk, &rjd, - &ns)) - return Qnil; - if (!need_jd) - return INT2FIX(0); /* dummy */ - encode_jd(nth, rjd, &rjd2); - return rjd2; - } -} - -static VALUE -date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vn, vk, vsg; - VALUE argv2[5]; - - rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg); - - argv2[0] = vy; - argv2[1] = vm; - argv2[2] = vn; - argv2[3] = vk; - if (argc < 5) - argv2[4] = DBL2NUM(GREGORIAN); - else - argv2[4] = vsg; - - return valid_nth_kday_sub(5, argv2, klass, 1); -} - -static VALUE -date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vn, vk, vsg; - VALUE argv2[5]; - - rb_scan_args(argc, argv, "41", &vy, &vm, &vn, &vk, &vsg); - - argv2[0] = vy; - argv2[1] = vm; - argv2[2] = vn; - argv2[3] = vk; - if (argc < 5) - argv2[4] = INT2FIX(DEFAULT_SG); - else - argv2[4] = vsg; - - if (NIL_P(valid_nth_kday_sub(5, argv2, klass, 0))) - return Qfalse; - return Qtrue; -} - -static VALUE -date_s_zone_to_diff(VALUE klass, VALUE str) -{ - return date_zone_to_diff(str); -} -#endif - -/* - * call-seq: - * Date.julian_leap?(year) -> bool - * - * Returns true if the given year is a leap year of the proleptic - * Julian calendar. - * - * For example: - * - * Date.julian_leap?(1900) #=> true - * Date.julian_leap?(1901) #=> false - */ -static VALUE -date_s_julian_leap_p(VALUE klass, VALUE y) -{ - VALUE nth; - int ry; - - decode_year(y, +1, &nth, &ry); - return f_boolcast(c_julian_leap_p(ry)); -} - -/* - * call-seq: - * Date.gregorian_leap?(year) -> bool - * Date.leap?(year) -> bool - * - * Returns true if the given year is a leap year of the proleptic - * Gregorian calendar. - * - * For example: - * - * Date.gregorian_leap?(1900) #=> false - * Date.gregorian_leap?(2000) #=> true - */ -static VALUE -date_s_gregorian_leap_p(VALUE klass, VALUE y) -{ - VALUE nth; - int ry; - - decode_year(y, -1, &nth, &ry); - return f_boolcast(c_gregorian_leap_p(ry)); -} - -static void -d_lite_gc_mark(union DateData *dat) -{ - if (simple_dat_p(dat)) - rb_gc_mark(dat->s.nth); - else { - rb_gc_mark(dat->c.nth); - rb_gc_mark(dat->c.sf); - - } -} - -inline static VALUE -d_simple_new_internal(VALUE klass, - VALUE nth, int jd, - double sg, - int y, int m, int d, - unsigned flags) -{ - struct SimpleDateData *dat; - VALUE obj; - - obj = Data_Make_Struct(klass, struct SimpleDateData, - d_lite_gc_mark, -1, dat); - set_to_simple(dat, nth, jd, sg, y, m, d, flags & ~COMPLEX_DAT); - - assert(have_jd_p(dat) || have_civil_p(dat)); - - return obj; -} - -inline static VALUE -d_complex_new_internal(VALUE klass, - VALUE nth, int jd, - int df, VALUE sf, - int of, double sg, - int y, int m, int d, - int h, int min, int s, - unsigned flags) -{ - struct ComplexDateData *dat; - VALUE obj; - - obj = Data_Make_Struct(klass, struct ComplexDateData, - d_lite_gc_mark, -1, dat); - set_to_complex(dat, nth, jd, df, sf, of, sg, - y, m, d, h, min, s, flags | COMPLEX_DAT); - - assert(have_jd_p(dat) || have_civil_p(dat)); - assert(have_df_p(dat) || have_time_p(dat)); - - return obj; -} - -static VALUE -d_lite_s_alloc_simple(VALUE klass) -{ - return d_simple_new_internal(klass, - INT2FIX(0), 0, - DEFAULT_SG, - 0, 0, 0, - HAVE_JD); -} - -static VALUE -d_lite_s_alloc_complex(VALUE klass) -{ - return d_complex_new_internal(klass, - INT2FIX(0), 0, - 0, INT2FIX(0), - 0, DEFAULT_SG, - 0, 0, 0, - 0, 0, 0, - HAVE_JD | HAVE_DF); -} - -static VALUE -d_lite_s_alloc(VALUE klass) -{ - return d_lite_s_alloc_complex(klass); -} - -static void -old_to_new(VALUE ajd, VALUE of, VALUE sg, - VALUE *rnth, int *rjd, int *rdf, VALUE *rsf, - int *rof, double *rsg) -{ - VALUE jd, df, sf, of2, t; - - decode_day(f_add(ajd, half_days_in_day), - &jd, &df, &sf); - t = day_to_sec(of); - of2 = f_round(t); - - if (!f_eqeq_p(of2, t)) - rb_warning("fraction of offset is ignored"); - - decode_jd(jd, rnth, rjd); - - *rdf = NUM2INT(df); - *rsf = sf; - *rof = NUM2INT(of2); - *rsg = NUM2DBL(sg); - - if (*rdf < 0 || *rdf >= DAY_IN_SECONDS) - rb_raise(rb_eArgError, "invalid day fraction"); - - if (f_lt_p(*rsf, INT2FIX(0)) || - f_ge_p(*rsf, INT2FIX(SECOND_IN_NANOSECONDS))) - - if (*rof < -DAY_IN_SECONDS || *rof > DAY_IN_SECONDS) { - *rof = 0; - rb_warning("invalid offset is ignored"); - } - - if (!c_valid_start_p(*rsg)) { - *rsg = DEFAULT_SG; - rb_warning("invalid start is ignored"); - } -} - -#ifndef NDEBUG -static VALUE -date_s_new_bang(int argc, VALUE *argv, VALUE klass) -{ - VALUE ajd, of, sg, nth, sf; - int jd, df, rof; - double rsg; - - rb_scan_args(argc, argv, "03", &ajd, &of, &sg); - - switch (argc) { - case 0: - ajd = INT2FIX(0); - case 1: - of = INT2FIX(0); - case 2: - sg = INT2FIX(DEFAULT_SG); - } - - old_to_new(ajd, of, sg, - &nth, &jd, &df, &sf, &rof, &rsg); - - if (!df && f_zero_p(sf) && !rof) - return d_simple_new_internal(klass, - nth, jd, - rsg, - 0, 0, 0, - HAVE_JD); - else - return d_complex_new_internal(klass, - nth, jd, - df, sf, - rof, rsg, - 0, 0, 0, - 0, 0, 0, - HAVE_JD | HAVE_DF); -} -#endif - -inline static int -wholenum_p(VALUE x) -{ - if (FIXNUM_P(x)) - return 1; - switch (TYPE(x)) { - case T_BIGNUM: - return 1; - case T_FLOAT: - { - double d = RFLOAT_VALUE(x); - return round(d) == d; - } - break; - case T_RATIONAL: - { - VALUE den = RRATIONAL(x)->den; - return FIXNUM_P(den) && FIX2LONG(den) == 1; - } - break; - } - return 0; -} - -inline static VALUE -to_integer(VALUE x) -{ - if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM)) - return x; - return f_to_i(x); -} - -inline static VALUE -d_trunc(VALUE d, VALUE *fr) -{ - VALUE rd; - - if (wholenum_p(d)) { - rd = to_integer(d); - *fr = INT2FIX(0); - } - else { - rd = f_idiv(d, INT2FIX(1)); - *fr = f_mod(d, INT2FIX(1)); - } - return rd; -} - -#define jd_trunc d_trunc -#define k_trunc d_trunc - -inline static VALUE -h_trunc(VALUE h, VALUE *fr) -{ - VALUE rh; - - if (wholenum_p(h)) { - rh = to_integer(h); - *fr = INT2FIX(0); - } - else { - rh = f_idiv(h, INT2FIX(1)); - *fr = f_mod(h, INT2FIX(1)); - *fr = f_quo(*fr, INT2FIX(24)); - } - return rh; -} - -inline static VALUE -min_trunc(VALUE min, VALUE *fr) -{ - VALUE rmin; - - if (wholenum_p(min)) { - rmin = to_integer(min); - *fr = INT2FIX(0); - } - else { - rmin = f_idiv(min, INT2FIX(1)); - *fr = f_mod(min, INT2FIX(1)); - *fr = f_quo(*fr, INT2FIX(1440)); - } - return rmin; -} - -inline static VALUE -s_trunc(VALUE s, VALUE *fr) -{ - VALUE rs; - - if (wholenum_p(s)) { - rs = to_integer(s); - *fr = INT2FIX(0); - } - else { - rs = f_idiv(s, INT2FIX(1)); - *fr = f_mod(s, INT2FIX(1)); - *fr = f_quo(*fr, INT2FIX(86400)); - } - return rs; -} - -#define num2num_with_frac(s,n) \ -{\ - s = s##_trunc(v##s, &fr);\ - if (f_nonzero_p(fr)) {\ - if (argc > n)\ - rb_raise(rb_eArgError, "invalid fraction");\ - fr2 = fr;\ - }\ -} - -#define num2int_with_frac(s,n) \ -{\ - s = NUM2INT(s##_trunc(v##s, &fr));\ - if (f_nonzero_p(fr)) {\ - if (argc > n)\ - rb_raise(rb_eArgError, "invalid fraction");\ - fr2 = fr;\ - }\ -} - -#define canon24oc() \ -{\ - if (rh == 24) {\ - rh = 0;\ - fr2 = f_add(fr2, INT2FIX(1));\ - }\ -} - -#define add_frac() \ -{\ - if (f_nonzero_p(fr2))\ - ret = d_lite_plus(ret, fr2);\ -} - -#define val2sg(vsg,dsg) \ -{\ - dsg = NUM2DBL(vsg);\ - if (!c_valid_start_p(dsg)) {\ - dsg = DEFAULT_SG;\ - rb_warning("invalid start is ignored");\ - }\ -} - -static VALUE d_lite_plus(VALUE, VALUE); - -/* - * call-seq: - * Date.jd([jd=0[, start=Date::ITALY]]) -> date - * - * Creates a date object denoting the given chronological Julian day - * number. - * - * For example: - * - * Date.jd(2451944) #=> #<Date: 2001-02-03 ...> - * Date.jd(2451945) #=> #<Date: 2001-02-04 ...> - * Date.jd(0) #=> #<Date: -4712-01-01 ...> - * - * See also new. - */ -static VALUE -date_s_jd(int argc, VALUE *argv, VALUE klass) -{ - VALUE vjd, vsg, jd, fr, fr2, ret; - double sg; - - rb_scan_args(argc, argv, "02", &vjd, &vsg); - - jd = INT2FIX(0); - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 2: - val2sg(vsg, sg); - case 1: - num2num_with_frac(jd, positive_inf); - } - - { - VALUE nth; - int rjd; - - decode_jd(jd, &nth, &rjd); - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - 0, 0, 0, - HAVE_JD); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * Date.ordinal([year=-4712[, yday=1[, start=Date::ITALY]]]) -> date - * - * Creates a date object denoting the given ordinal date. - * - * The day of year should be a negative or a positive number (as a - * relative day from the end of year when negative). It should not be - * zero. - * - * For example: - * - * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...> - * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...> - * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...> - * - * See also jd and new. - */ -static VALUE -date_s_ordinal(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vd, vsg, y, fr, fr2, ret; - int d; - double sg; - - rb_scan_args(argc, argv, "03", &vy, &vd, &vsg); - - y = INT2FIX(-4712); - d = 1; - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 3: - val2sg(vsg, sg); - case 2: - num2int_with_frac(d, positive_inf); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rd, rjd, ns; - - if (!valid_ordinal_p(y, d, sg, - &nth, &ry, - &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - 0, 0, 0, - HAVE_JD); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * Date.civil([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date - * Date.new([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date - * - * Creates a date object denoting the given calendar date. - * - * In this class, BCE years are counted astronomically. Thus, the - * year before the year 1 is the year zero, and the year preceding the - * year zero is the year -1. The month and the day of month should be - * a negative or a positive number (as a relative month/day from the - * end of year/month when negative). They should not be zero. - * - * The last argument should be a Julian day number which denotes the - * day of calendar reform. Date::ITALY (2299161=1582-10-15), - * Date::ENGLAND (2361222=1752-09-14), Date::GREGORIAN (the proleptic - * Gregorian calendar) and Date::JULIAN (the proleptic Julian - * calendar) can be specified as a day of calendar reform. - * - * For example: - * - * Date.new(2001) #=> #<Date: 2001-01-01 ...> - * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...> - * Date.new(2001,2,-1) #=> #<Date: 2001-02-28 ...> - * - * See also jd. - */ -static VALUE -date_s_civil(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vd, vsg, y, fr, fr2, ret; - int m, d; - double sg; - - rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg); - - y = INT2FIX(-4712); - m = 1; - d = 1; - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 4: - val2sg(vsg, sg); - case 3: - num2int_with_frac(d, positive_inf); - case 2: - m = NUM2INT(vm); - case 1: - y = vy; - } - - if (guess_style(y, sg) < 0) { - VALUE nth; - int ry, rm, rd; - - if (!valid_gregorian_p(y, m, d, - &nth, &ry, - &rm, &rd)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, 0, - sg, - ry, rm, rd, - HAVE_CIVIL); - } - else { - VALUE nth; - int ry, rm, rd, rjd, ns; - - if (!valid_civil_p(y, m, d, sg, - &nth, &ry, - &rm, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - ry, rm, rd, - HAVE_JD | HAVE_CIVIL); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * Date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) -> date - * - * Creates a date object denoting the given week date. - * - * The week and the day of week should be a negative or a positive - * number (as a relative week/day from the end of year/week when - * negative). They should not be zero. - * - * For example: - * - * Date.commercial(2001) #=> #<Date: 2001-01-01 ...> - * Date.commercial(2002) #=> #<Date: 2001-12-31 ...> - * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...> - * - * See also jd and new. - */ -static VALUE -date_s_commercial(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vsg, y, fr, fr2, ret; - int w, d; - double sg; - - rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg); - - y = INT2FIX(-4712); - w = 1; - d = 1; - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 4: - val2sg(vsg, sg); - case 3: - num2int_with_frac(d, positive_inf); - case 2: - w = NUM2INT(vw); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rw, rd, rjd, ns; - - if (!valid_commercial_p(y, w, d, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - 0, 0, 0, - HAVE_JD); - } - add_frac(); - return ret; -} - -#ifndef NDEBUG -static VALUE -date_s_weeknum(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vf, vsg, y, fr, fr2, ret; - int w, d, f; - double sg; - - rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg); - - y = INT2FIX(-4712); - w = 0; - d = 1; - f = 0; - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 5: - val2sg(vsg, sg); - case 4: - f = NUM2INT(vf); - case 3: - num2int_with_frac(d, positive_inf); - case 2: - w = NUM2INT(vw); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rw, rd, rjd, ns; - - if (!valid_weeknum_p(y, w, d, f, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - 0, 0, 0, - HAVE_JD); - } - add_frac(); - return ret; -} - -static VALUE -date_s_nth_kday(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vn, vk, vsg, y, fr, fr2, ret; - int m, n, k; - double sg; - - rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg); - - y = INT2FIX(-4712); - m = 1; - n = 1; - k = 1; - fr2 = INT2FIX(0); - sg = DEFAULT_SG; - - switch (argc) { - case 5: - val2sg(vsg, sg); - case 4: - num2int_with_frac(k, positive_inf); - case 3: - n = NUM2INT(vn); - case 2: - m = NUM2INT(vm); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rm, rn, rk, rjd, ns; - - if (!valid_nth_kday_p(y, m, n, k, sg, - &nth, &ry, - &rm, &rn, &rk, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - - ret = d_simple_new_internal(klass, - nth, rjd, - sg, - 0, 0, 0, - HAVE_JD); - } - add_frac(); - return ret; -} -#endif - -#if !defined(HAVE_GMTIME_R) -static struct tm* -gmtime_r(const time_t *t, struct tm *tm) -{ - auto struct tm *tmp = gmtime(t); - if (tmp) - *tm = *tmp; - return tmp; -} - -static struct tm* -localtime_r(const time_t *t, struct tm *tm) -{ - auto struct tm *tmp = localtime(t); - if (tmp) - *tm = *tmp; - return tmp; -} -#endif - -static void set_sg(union DateData *, double); - -/* - * call-seq: - * Date.today([start=Date::ITALY]) -> date - * - * For example: - * - * Date.today #=> #<Date: 2011-06-11 ..> - * - * Creates a date object denoting the present day. - */ -static VALUE -date_s_today(int argc, VALUE *argv, VALUE klass) -{ - VALUE vsg, nth, ret; - double sg; - time_t t; - struct tm tm; - int y, ry, m, d; - - rb_scan_args(argc, argv, "01", &vsg); - - if (argc < 1) - sg = DEFAULT_SG; - else - val2sg(vsg, sg); - - if (time(&t) == -1) - rb_sys_fail("time"); - tzset(); - if (!localtime_r(&t, &tm)) - rb_sys_fail("localtime"); - - y = tm.tm_year + 1900; - m = tm.tm_mon + 1; - d = tm.tm_mday; - - decode_year(INT2FIX(y), -1, &nth, &ry); - - ret = d_simple_new_internal(klass, - nth, 0, - GREGORIAN, - ry, m, d, - HAVE_CIVIL); - { - get_d1(ret); - set_sg(dat, sg); - } - return ret; -} - -#define set_hash0(k,v) rb_hash_aset(hash, k, v) -#define ref_hash0(k) rb_hash_aref(hash, k) -#define del_hash0(k) rb_hash_delete(hash, k) - -#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v) -#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k))) -#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k))) - -static VALUE -rt_rewrite_frags(VALUE hash) -{ - VALUE seconds; - - seconds = ref_hash("seconds"); - if (!NIL_P(seconds)) { - VALUE d, h, min, s, fr; - - d = f_idiv(seconds, INT2FIX(DAY_IN_SECONDS)); - fr = f_mod(seconds, INT2FIX(DAY_IN_SECONDS)); - - h = f_idiv(fr, INT2FIX(HOUR_IN_SECONDS)); - fr = f_mod(fr, INT2FIX(HOUR_IN_SECONDS)); - - min = f_idiv(fr, INT2FIX(MINUTE_IN_SECONDS)); - fr = f_mod(fr, INT2FIX(MINUTE_IN_SECONDS)); - - s = f_idiv(fr, INT2FIX(1)); - fr = f_mod(fr, INT2FIX(1)); - - set_hash("jd", f_add(UNIX_EPOCH_IN_CJD, d)); - set_hash("hour", h); - set_hash("min", min); - set_hash("sec", s); - set_hash("sec_fraction", fr); - del_hash("seconds"); - del_hash("offset"); - } - return hash; -} - -#define sym(x) ID2SYM(rb_intern(x)) - -static VALUE d_lite_year(VALUE); -static VALUE d_lite_wday(VALUE); -static VALUE d_lite_jd(VALUE); - -static VALUE -rt_complete_frags(VALUE klass, VALUE hash) -{ - static VALUE tab = Qnil; - int g, e; - VALUE k, a, d; - - if (NIL_P(tab)) { - tab = rb_ary_new3(11, - rb_ary_new3(2, - sym("time"), - rb_ary_new3(3, - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - Qnil, - rb_ary_new3(1, - sym("jd"))), - rb_ary_new3(2, - sym("ordinal"), - rb_ary_new3(5, - sym("year"), - sym("yday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - sym("civil"), - rb_ary_new3(6, - sym("year"), - sym("mon"), - sym("mday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - sym("commercial"), - rb_ary_new3(6, - sym("cwyear"), - sym("cweek"), - sym("cwday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - sym("wday"), - rb_ary_new3(4, - sym("wday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - sym("wnum0"), - rb_ary_new3(6, - sym("year"), - sym("wnum0"), - sym("wday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - sym("wnum1"), - rb_ary_new3(6, - sym("year"), - sym("wnum1"), - sym("wday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - Qnil, - rb_ary_new3(6, - sym("cwyear"), - sym("cweek"), - sym("wday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - Qnil, - rb_ary_new3(6, - sym("year"), - sym("wnum0"), - sym("cwday"), - sym("hour"), - sym("min"), - sym("sec"))), - rb_ary_new3(2, - Qnil, - rb_ary_new3(6, - sym("year"), - sym("wnum1"), - sym("cwday"), - sym("hour"), - sym("min"), - sym("sec")))); - rb_gc_register_mark_object(tab); - } - - { - int i, eno = 0, idx = 0; - - for (i = 0; i < RARRAY_LENINT(tab); i++) { - VALUE x, a; - - x = RARRAY_PTR(tab)[i]; - a = RARRAY_PTR(x)[1]; - - { - int j, n = 0; - - for (j = 0; j < RARRAY_LENINT(a); j++) - if (!NIL_P(ref_hash0(RARRAY_PTR(a)[j]))) - n++; - if (n > eno) { - eno = n; - idx = i; - } - } - } - if (eno == 0) - g = 0; - else { - g = 1; - k = RARRAY_PTR(RARRAY_PTR(tab)[idx])[0]; - a = RARRAY_PTR(RARRAY_PTR(tab)[idx])[1]; - e = eno; - } - } - - d = Qnil; - - if (g && !NIL_P(k) && (RARRAY_LENINT(a) - e)) { - if (k == sym("ordinal")) { - if (NIL_P(ref_hash("year"))) { - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash("year", d_lite_year(d)); - } - if (NIL_P(ref_hash("yday"))) - set_hash("yday", INT2FIX(1)); - } - else if (k == sym("civil")) { - int i; - - for (i = 0; i < RARRAY_LENINT(a); i++) { - VALUE e = RARRAY_PTR(a)[i]; - - if (!NIL_P(ref_hash0(e))) - break; - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash0(e, rb_funcall(d, SYM2ID(e), 0)); - } - if (NIL_P(ref_hash("mon"))) - set_hash("mon", INT2FIX(1)); - if (NIL_P(ref_hash("mday"))) - set_hash("mday", INT2FIX(1)); - } - else if (k == sym("commercial")) { - int i; - - for (i = 0; i < RARRAY_LENINT(a); i++) { - VALUE e = RARRAY_PTR(a)[i]; - - if (!NIL_P(ref_hash0(e))) - break; - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash0(e, rb_funcall(d, SYM2ID(e), 0)); - } - if (NIL_P(ref_hash("cweek"))) - set_hash("cweek", INT2FIX(1)); - if (NIL_P(ref_hash("cwday"))) - set_hash("cwday", INT2FIX(1)); - } - else if (k == sym("wday")) { - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash("jd", d_lite_jd(f_add(f_sub(d, - d_lite_wday(d)), - ref_hash("wday")))); - } - else if (k == sym("wnum0")) { - int i; - - for (i = 0; i < RARRAY_LENINT(a); i++) { - VALUE e = RARRAY_PTR(a)[i]; - - if (!NIL_P(ref_hash0(e))) - break; - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash0(e, rb_funcall(d, SYM2ID(e), 0)); - } - if (NIL_P(ref_hash("wnum0"))) - set_hash("wnum0", INT2FIX(0)); - if (NIL_P(ref_hash("wday"))) - set_hash("wday", INT2FIX(0)); - } - else if (k == sym("wnum1")) { - int i; - - for (i = 0; i < RARRAY_LENINT(a); i++) { - VALUE e = RARRAY_PTR(a)[i]; - - if (!NIL_P(ref_hash0(e))) - break; - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - set_hash0(e, rb_funcall(d, SYM2ID(e), 0)); - } - if (NIL_P(ref_hash("wnum1"))) - set_hash("wnum1", INT2FIX(0)); - if (NIL_P(ref_hash("wday"))) - set_hash("wday", INT2FIX(1)); - } - } - - if (g && k == sym("time")) { - if (f_le_p(klass, cDateTime)) { - if (NIL_P(d)) - d = date_s_today(0, (VALUE *)0, cDate); - if (NIL_P(ref_hash("jd"))) - set_hash("jd", d_lite_jd(d)); - } - } - - if (NIL_P(ref_hash("hour"))) - set_hash("hour", INT2FIX(0)); - if (NIL_P(ref_hash("min"))) - set_hash("min", INT2FIX(0)); - if (NIL_P(ref_hash("sec"))) - set_hash("sec", INT2FIX(0)); - else if (f_gt_p(ref_hash("sec"), INT2FIX(59))) - set_hash("sec", INT2FIX(59)); - - return hash; -} - -static VALUE -rt__valid_jd_p(VALUE jd, VALUE sg) -{ - return jd; -} - -static VALUE -rt__valid_ordinal_p(VALUE y, VALUE d, VALUE sg) -{ - VALUE nth, rjd2; - int ry, rd, rjd, ns; - - if (!valid_ordinal_p(y, NUM2INT(d), NUM2DBL(sg), - &nth, &ry, - &rd, &rjd, - &ns)) - return Qnil; - encode_jd(nth, rjd, &rjd2); - return rjd2; -} - -static VALUE -rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg) -{ - VALUE nth, rjd2; - int ry, rm, rd, rjd, ns; - - if (!valid_civil_p(y, NUM2INT(m), NUM2INT(d), NUM2DBL(sg), - &nth, &ry, - &rm, &rd, &rjd, - &ns)) - return Qnil; - encode_jd(nth, rjd, &rjd2); - return rjd2; -} - -static VALUE -rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg) -{ - VALUE nth, rjd2; - int ry, rw, rd, rjd, ns; - - if (!valid_commercial_p(y, NUM2INT(w), NUM2INT(d), NUM2DBL(sg), - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - return Qnil; - encode_jd(nth, rjd, &rjd2); - return rjd2; -} - -static VALUE -rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg) -{ - VALUE nth, rjd2; - int ry, rw, rd, rjd, ns; - - if (!valid_weeknum_p(y, NUM2INT(w), NUM2INT(d), NUM2INT(f), NUM2DBL(sg), - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - return Qnil; - encode_jd(nth, rjd, &rjd2); - return rjd2; -} - -static VALUE -rt__valid_date_frags_p(VALUE hash, VALUE sg) -{ - { - VALUE vjd; - - if (!NIL_P(vjd = ref_hash("jd"))) { - VALUE jd = rt__valid_jd_p(vjd, sg); - if (!NIL_P(jd)) - return jd; - } - } - - { - VALUE year, yday; - - if (!NIL_P(yday = ref_hash("yday")) && - !NIL_P(year = ref_hash("year"))) { - VALUE jd = rt__valid_ordinal_p(year, yday, sg); - if (!NIL_P(jd)) - return jd; - } - } - - { - VALUE year, mon, mday; - - if (!NIL_P(mday = ref_hash("mday")) && - !NIL_P(mon = ref_hash("mon")) && - !NIL_P(year = ref_hash("year"))) { - VALUE jd = rt__valid_civil_p(year, mon, mday, sg); - if (!NIL_P(jd)) - return jd; - } - } - - { - VALUE year, week, wday; - - wday = ref_hash("cwday"); - if (NIL_P(wday)) { - wday = ref_hash("wday"); - if (!NIL_P(wday)) - if (f_zero_p(wday)) - wday = INT2FIX(7); - } - - if (!NIL_P(wday) && - !NIL_P(week = ref_hash("cweek")) && - !NIL_P(year = ref_hash("cwyear"))) { - VALUE jd = rt__valid_commercial_p(year, week, wday, sg); - if (!NIL_P(jd)) - return jd; - } - } - - { - VALUE year, week, wday; - - wday = ref_hash("wday"); - if (NIL_P(wday)) { - wday = ref_hash("cwday"); - if (!NIL_P(wday)) - if (f_eqeq_p(wday, INT2FIX(7))) - wday = INT2FIX(0); - } - - if (!NIL_P(wday) && - !NIL_P(week = ref_hash("wnum0")) && - !NIL_P(year = ref_hash("year"))) { - VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(0), sg); - if (!NIL_P(jd)) - return jd; - } - } - - { - VALUE year, week, wday; - - wday = ref_hash("wday"); - if (NIL_P(wday)) - wday = ref_hash("cwday"); - if (!NIL_P(wday)) - wday = f_mod(f_sub(wday, INT2FIX(1)), - INT2FIX(7)); - - if (!NIL_P(wday) && - !NIL_P(week = ref_hash("wnum1")) && - !NIL_P(year = ref_hash("year"))) { - VALUE jd = rt__valid_weeknum_p(year, week, wday, INT2FIX(1), sg); - if (!NIL_P(jd)) - return jd; - } - } - return Qnil; -} - -static VALUE -d_new_by_frags(VALUE klass, VALUE hash, VALUE sg) -{ - VALUE jd; - - if (!c_valid_start_p(NUM2DBL(sg))) { - sg = INT2FIX(DEFAULT_SG); - rb_warning("invalid start is ignored"); - } - - if (NIL_P(hash)) - rb_raise(rb_eArgError, "invalid date"); - - if (NIL_P(ref_hash("jd")) && - NIL_P(ref_hash("yday")) && - !NIL_P(ref_hash("year")) && - !NIL_P(ref_hash("mon")) && - !NIL_P(ref_hash("mday"))) - jd = rt__valid_civil_p(ref_hash("year"), - ref_hash("mon"), - ref_hash("mday"), sg); - else { - hash = rt_rewrite_frags(hash); - hash = rt_complete_frags(klass, hash); - jd = rt__valid_date_frags_p(hash, sg); - } - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - { - VALUE nth; - int rjd; - - decode_jd(jd, &nth, &rjd); - return d_simple_new_internal(klass, - nth, rjd, - NUM2DBL(sg), - 0, 0, 0, - HAVE_JD); - } -} - -VALUE date__strptime(const char *str, size_t slen, - const char *fmt, size_t flen, VALUE hash); - -static VALUE -date_s__strptime_internal(int argc, VALUE *argv, VALUE klass, - const char *default_fmt) -{ - VALUE vstr, vfmt, hash; - const char *str, *fmt; - size_t slen, flen; - - rb_scan_args(argc, argv, "11", &vstr, &vfmt); - - StringValue(vstr); - if (!rb_enc_str_asciicompat_p(vstr)) - rb_raise(rb_eArgError, - "string should have ASCII compatible encoding"); - str = RSTRING_PTR(vstr); - slen = RSTRING_LEN(vstr); - if (argc < 2) { - fmt = default_fmt; - flen = strlen(default_fmt); - } - else { - StringValue(vfmt); - if (!rb_enc_str_asciicompat_p(vfmt)) - rb_raise(rb_eArgError, - "format should have ASCII compatible encoding"); - fmt = RSTRING_PTR(vfmt); - flen = RSTRING_LEN(vfmt); - } - hash = rb_hash_new(); - if (NIL_P(date__strptime(str, slen, fmt, flen, hash))) - return Qnil; - - { - VALUE zone = ref_hash("zone"); - VALUE left = ref_hash("leftover"); - - if (!NIL_P(zone)) { - rb_enc_copy(zone, vstr); - OBJ_INFECT(zone, vstr); - set_hash("zone", zone); - } - if (!NIL_P(left)) { - rb_enc_copy(left, vstr); - OBJ_INFECT(left, vstr); - set_hash("leftover", left); - } - } - - return hash; -} - -/* - * call-seq: - * Date._strptime(string[, format='%F']) -> hash - * - * Parses the given representation of date and time with the given - * template, and returns a hash of parsed elements. - * - * For example: - * - * Date._strptime('2001-02-03', '%Y-%m-%d') - * #=> {:year=>2001, :mon=>2, :mday=>3} - * - * See also strptime(3) and strftime. - */ -static VALUE -date_s__strptime(int argc, VALUE *argv, VALUE klass) -{ - return date_s__strptime_internal(argc, argv, klass, "%F"); -} - -/* - * call-seq: - * Date.strptime([string='-4712-01-01'[, format='%F'[, start=ITALY]]]) -> date - * - * Parses the given representation of date and time with the given - * template, and creates a date object. - * - * For example: - * - * Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...> - * Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...> - * Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...> - * - * See also strptime(3) and strftime. - */ -static VALUE -date_s_strptime(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, fmt, sg; - - rb_scan_args(argc, argv, "03", &str, &fmt, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01"); - case 1: - fmt = rb_str_new2("%F"); - case 2: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = fmt; - hash = date_s__strptime(2, argv2, klass); - return d_new_by_frags(klass, hash, sg); - } -} - -VALUE date__parse(VALUE str, VALUE comp); - -static VALUE -date_s__parse_internal(int argc, VALUE *argv, VALUE klass) -{ - VALUE vstr, vcomp, hash; - - rb_scan_args(argc, argv, "11", &vstr, &vcomp); - StringValue(vstr); - if (!rb_enc_str_asciicompat_p(vstr)) - rb_raise(rb_eArgError, - "string should have ASCII compatible encoding"); - if (argc < 2) - vcomp = Qtrue; - - hash = date__parse(vstr, vcomp); - - { - VALUE zone = ref_hash("zone"); - - if (!NIL_P(zone)) { - rb_enc_copy(zone, vstr); - OBJ_INFECT(zone, vstr); - set_hash("zone", zone); - } - } - - return hash; -} - -/* - * call-seq: - * Date._parse(string[, comp=true]) -> hash - * - * Parses the given representation of date and time, and returns a - * hash of parsed elements. - * - * If the optional second argument is true and the detected year is in - * the range "00" to "99", considers the year a 2-digit form and makes - * it full. - * - * For example: - * - * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3} - */ -static VALUE -date_s__parse(int argc, VALUE *argv, VALUE klass) -{ - return date_s__parse_internal(argc, argv, klass); -} - -/* - * call-seq: - * Date.parse(string='-4712-01-01'[, comp=true[, start=ITALY]]) -> date - * - * Parses the given representation of date and time, and creates a - * date object. - * - * If the optional second argument is true and the detected year is in - * the range "00" to "99", considers the year a 2-digit form and makes - * it full. - * - * For example: - * - * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...> - * Date.parse('20010203') #=> #<Date: 2001-02-03 ...> - * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_parse(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, comp, sg; - - rb_scan_args(argc, argv, "03", &str, &comp, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01"); - case 1: - comp = Qtrue; - case 2: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); - return d_new_by_frags(klass, hash, sg); - } -} - -VALUE date__iso8601(VALUE); -VALUE date__rfc3339(VALUE); -VALUE date__xmlschema(VALUE); -VALUE date__rfc2822(VALUE); -VALUE date__httpdate(VALUE); -VALUE date__jisx0301(VALUE); - -/* - * call-seq: - * Date._iso8601(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__iso8601(VALUE klass, VALUE str) -{ - return date__iso8601(str); -} - -/* - * call-seq: - * Date.iso8601(string='-4712-01-01'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some typical ISO 8601 formats. - * - * For example: - * - * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...> - * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...> - * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_iso8601(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__iso8601(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * Date._rfc3339(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__rfc3339(VALUE klass, VALUE str) -{ - return date__rfc3339(str); -} - -/* - * call-seq: - * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some typical RFC 3339 formats. - * - * For example: - * - * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_rfc3339(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__rfc3339(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * Date._xmlschema(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__xmlschema(VALUE klass, VALUE str) -{ - return date__xmlschema(str); -} - -/* - * call-seq: - * Date.xmlschema(string='-4712-01-01'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some typical XML Schema formats. - * - * For example: - * - * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_xmlschema(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__xmlschema(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * Date._rfc2822(string) -> hash - * Date._rfc822(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__rfc2822(VALUE klass, VALUE str) -{ - return date__rfc2822(str); -} - -/* - * call-seq: - * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> date - * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some typical RFC 2822 formats. - * - * For example: - * - * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000') - * #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_rfc2822(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__rfc2822(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * Date._httpdate(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__httpdate(VALUE klass, VALUE str) -{ - return date__httpdate(str); -} - -/* - * call-seq: - * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some RFC 2616 format. - * - * For example: - * - * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT') - * #=> #<Date: 2001-02-03 ...> - * - */ -static VALUE -date_s_httpdate(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__httpdate(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * Date._jisx0301(string) -> hash - * - * Returns a hash of parsed elements. - */ -static VALUE -date_s__jisx0301(VALUE klass, VALUE str) -{ - return date__jisx0301(str); -} - -/* - * call-seq: - * Date.jisx0301(string='-4712-01-01'[, start=ITALY]) -> date - * - * Creates a new Date object by parsing from a string according to - * some typical JIS X 0301 formats. - * - * For example: - * - * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...> - */ -static VALUE -date_s_jisx0301(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__jisx0301(klass, str); - return d_new_by_frags(klass, hash, sg); - } -} - -static VALUE -dup_obj(VALUE self) -{ - get_d1a(self); - - if (simple_dat_p(adat)) { - VALUE new = d_lite_s_alloc_simple(rb_obj_class(self)); - { - get_d1b(new); - bdat->s = adat->s; - return new; - } - } - else { - VALUE new = d_lite_s_alloc_complex(rb_obj_class(self)); - { - get_d1b(new); - bdat->c = adat->c; - return new; - } - } -} - -static VALUE -dup_obj_as_complex(VALUE self) -{ - get_d1a(self); - - if (simple_dat_p(adat)) { - VALUE new = d_lite_s_alloc_complex(rb_obj_class(self)); - { - get_d1b(new); - copy_simple_to_complex(&bdat->c, &adat->s); - bdat->c.flags |= HAVE_DF | COMPLEX_DAT; - return new; - } - } - else { - VALUE new = d_lite_s_alloc_complex(rb_obj_class(self)); - { - get_d1b(new); - bdat->c = adat->c; - return new; - } - } -} - -#define val2off(vof,iof) \ -{\ - if (!offset_to_sec(vof, &iof)) {\ - iof = 0;\ - rb_warning("invalid offset is ignored");\ - }\ -} - -#ifndef NDEBUG -static VALUE -d_lite_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE jd, vjd, vdf, sf, vsf, vof, vsg; - int df, of; - double sg; - - rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg); - - jd = INT2FIX(0); - df = 0; - sf = INT2FIX(0); - of = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 5: - val2sg(vsg, sg); - case 4: - val2off(vof, of); - case 3: - sf = vsf; - if (f_lt_p(sf, INT2FIX(0)) || - f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) - rb_raise(rb_eArgError, "invalid second fraction"); - case 2: - df = NUM2INT(vdf); - if (df < 0 || df >= DAY_IN_SECONDS) - rb_raise(rb_eArgError, "invalid day fraction"); - case 1: - jd = vjd; - } - - { - VALUE nth; - int rjd; - - get_d1(self); - - decode_jd(jd, &nth, &rjd); - if (!df && f_zero_p(sf) && !of) { - set_to_simple(&dat->s, nth, rjd, sg, 0, 0, 0, HAVE_JD); - } - else { - if (!complex_dat_p(dat)) - rb_raise(rb_eArgError, - "cannot load complex into simple"); - - set_to_complex(&dat->c, nth, rjd, df, sf, of, sg, - 0, 0, 0, 0, 0, 0, HAVE_JD | HAVE_DF | COMPLEX_DAT); - } - } - return self; -} -#endif - -/* :nodoc: */ -static VALUE -d_lite_initialize_copy(VALUE copy, VALUE date) -{ - if (copy == date) - return copy; - { - get_d2(copy, date); - if (simple_dat_p(bdat)) { - adat->s = bdat->s; - adat->s.flags &= ~COMPLEX_DAT; - } - else { - if (!complex_dat_p(adat)) - rb_raise(rb_eArgError, - "cannot load complex into simple"); - - adat->c = bdat->c; - adat->c.flags |= COMPLEX_DAT; - } - } - return copy; -} - -#ifndef NDEBUG -static VALUE -d_lite_fill(VALUE self) -{ - get_d1(self); - - if (simple_dat_p(dat)) { - get_s_jd(dat); - get_s_civil(dat); - } - else { - get_c_jd(dat); - get_c_civil(dat); - get_c_df(dat); - get_c_time(dat); - } - return self; -} -#endif - -/* - * call-seq: - * d.ajd -> rational - * - * Returns the astronomical Julian day number. This is a fractional - * number, which is not adjusted by the offset. - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6,'+7').ajd #=> (11769328217/4800) - * DateTime.new(2001,2,2,14,5,6,'-7').ajd #=> (11769328217/4800) - */ -static VALUE -d_lite_ajd(VALUE self) -{ - get_d1(self); - return m_ajd(dat); -} - -/* - * call-seq: - * d.amjd -> rational - * - * Returns the astronomical modified Julian day number. This is - * a fractional number, which is not adjusted by the offset. - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6,'+7').amjd #=> (249325817/4800) - * DateTime.new(2001,2,2,14,5,6,'-7').amjd #=> (249325817/4800) - */ -static VALUE -d_lite_amjd(VALUE self) -{ - get_d1(self); - return m_amjd(dat); -} - -/* - * call-seq: - * d.jd -> integer - * - * Returns the Julian day number. This is a whole number, which is - * adjusted by the offset as the local time. - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6,'+7').jd #=> 2451944 - * DateTime.new(2001,2,3,4,5,6,'-7').jd #=> 2451944 - */ -static VALUE -d_lite_jd(VALUE self) -{ - get_d1(self); - return m_real_local_jd(dat); -} - -/* - * call-seq: - * d.mjd -> integer - * - * Returns the modified Julian day number. This is a whole number, - * which is adjusted by the offset as the local time. - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6,'+7').mjd #=> 51943 - * DateTime.new(2001,2,3,4,5,6,'-7').mjd #=> 51943 - */ -static VALUE -d_lite_mjd(VALUE self) -{ - get_d1(self); - return f_sub(m_real_local_jd(dat), INT2FIX(2400001)); -} - -/* - * call-seq: - * d.ld -> integer - * - * Returns the Lilian day number. This is a whole number, which is - * adjusted by the offset as the local time. - * - * For example: - * - * Date.new(2001,2,3).ld #=> 152784 - */ -static VALUE -d_lite_ld(VALUE self) -{ - get_d1(self); - return f_sub(m_real_local_jd(dat), INT2FIX(2299160)); -} - -/* - * call-seq: - * d.year -> integer - * - * Returns the year. - * - * For example: - * - * Date.new(2001,2,3).year #=> 2001 - * (Date.new(1,1,1) - 1).year #=> 0 - */ -static VALUE -d_lite_year(VALUE self) -{ - get_d1(self); - return m_real_year(dat); -} - -/* - * call-seq: - * d.yday -> fixnum - * - * Returns the day of the year (1-366). - * - * For example: - * - * Date.new(2001,2,3).yday #=> 34 - */ -static VALUE -d_lite_yday(VALUE self) -{ - get_d1(self); - return INT2FIX(m_yday(dat)); -} - -/* - * call-seq: - * d.mon -> fixnum - * d.month -> fixnum - * - * Returns the month (1-12). - * - * For example: - * - * Date.new(2001,2,3).mon #=> 2 - */ -static VALUE -d_lite_mon(VALUE self) -{ - get_d1(self); - return INT2FIX(m_mon(dat)); -} - -/* - * call-seq: - * d.mday -> fixnum - * d.day -> fixnum - * - * Returns the day of the month (1-31). - * - * For example: - * - * Date.new(2001,2,3).mday #=> 3 - */ -static VALUE -d_lite_mday(VALUE self) -{ - get_d1(self); - return INT2FIX(m_mday(dat)); -} - -/* - * call-seq: - * d.day_fraction -> rational - * - * Returns the fractional part of the day. - * - * For example: - * - * DateTime.new(2001,2,3,12).day_fraction #=> (1/2) - */ -static VALUE -d_lite_day_fraction(VALUE self) -{ - get_d1(self); - if (simple_dat_p(dat)) - return INT2FIX(0); - return m_fr(dat); -} - -/* - * call-seq: - * d.cwyear -> integer - * - * Returns the calendar week based year. - * - * For example: - * - * Date.new(2001,2,3).cwyear #=> 2001 - * Date.new(2000,1,1).cwyear #=> 1999 - */ -static VALUE -d_lite_cwyear(VALUE self) -{ - get_d1(self); - return m_real_cwyear(dat); -} - -/* - * call-seq: - * d.cweek -> fixnum - * - * Returns the calendar week number (1-53). - * - * For example: - * - * Date.new(2001,2,3).cweek #=> 5 - */ -static VALUE -d_lite_cweek(VALUE self) -{ - get_d1(self); - return INT2FIX(m_cweek(dat)); -} - -/* - * call-seq: - * d.cwday -> fixnum - * - * Returns the day of calendar week (1-7, Monday is 1). - * - * For example: - * - * Date.new(2001,2,3).cwday #=> 6 - */ -static VALUE -d_lite_cwday(VALUE self) -{ - get_d1(self); - return INT2FIX(m_cwday(dat)); -} - -#ifndef NDEBUG -static VALUE -d_lite_wnum0(VALUE self) -{ - get_d1(self); - return INT2FIX(m_wnum0(dat)); -} - -static VALUE -d_lite_wnum1(VALUE self) -{ - get_d1(self); - return INT2FIX(m_wnum1(dat)); -} -#endif - -/* - * call-seq: - * d.wday -> fixnum - * - * Returns the day of week (0-6, Sunday is zero). - * - * For example: - * - * Date.new(2001,2,3).wday #=> 6 - */ -static VALUE -d_lite_wday(VALUE self) -{ - get_d1(self); - return INT2FIX(m_wday(dat)); -} - -/* - * call-seq: - * d.sunday? -> bool - * - * Returns true if the date is Sunday. - */ -static VALUE -d_lite_sunday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 0); -} - -/* - * call-seq: - * d.monday? -> bool - * - * Returns true if the date is Monday. - */ -static VALUE -d_lite_monday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 1); -} - -/* - * call-seq: - * d.tuesday? -> bool - * - * Returns true if the date is Tuesday. - */ -static VALUE -d_lite_tuesday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 2); -} - -/* - * call-seq: - * d.wednesday? -> bool - * - * Returns true if the date is Wednesday. - */ -static VALUE -d_lite_wednesday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 3); -} - -/* - * call-seq: - * d.thursday? -> bool - * - * Returns true if the date is Thursday. - */ -static VALUE -d_lite_thursday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 4); -} - -/* - * call-seq: - * d.friday? -> bool - * - * Returns true if the date is Friday. - */ -static VALUE -d_lite_friday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 5); -} - -/* - * call-seq: - * d.saturday? -> bool - * - * Returns true if the date is Saturday. - */ -static VALUE -d_lite_saturday_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_wday(dat) == 6); -} - -#ifndef NDEBUG -static VALUE -d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k) -{ - int rjd, ns; - - get_d1(self); - - if (NUM2INT(k) != m_wday(dat)) - return Qfalse; - - c_nth_kday_to_jd(m_year(dat), m_mon(dat), - NUM2INT(n), NUM2INT(k), m_virtual_sg(dat), /* !=m_sg() */ - &rjd, &ns); - if (m_local_jd(dat) != rjd) - return Qfalse; - return Qtrue; -} -#endif - -/* - * call-seq: - * d.hour -> fixnum - * - * Returns the hour (0-23). - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6).hour #=> 4 - */ -static VALUE -d_lite_hour(VALUE self) -{ - get_d1(self); - return INT2FIX(m_hour(dat)); -} - -/* - * call-seq: - * d.min -> fixnum - * d.minute -> fixnum - * - * Returns the minute (0-59). - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6).min #=> 5 - */ -static VALUE -d_lite_min(VALUE self) -{ - get_d1(self); - return INT2FIX(m_min(dat)); -} - -/* - * call-seq: - * d.sec -> fixnum - * d.second -> fixnum - * - * Returns the second (0-59). - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6).sec #=> 6 - */ -static VALUE -d_lite_sec(VALUE self) -{ - get_d1(self); - return INT2FIX(m_sec(dat)); -} - -/* - * call-seq: - * d.sec_fraction -> rational - * d.second_fraction -> rational - * - * Returns the fractional part of the second. - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6.5).sec_fraction #=> (1/2) - */ -static VALUE -d_lite_sec_fraction(VALUE self) -{ - get_d1(self); - return m_sf_in_sec(dat); -} - -/* - * call-seq: - * d.offset -> rational - * - * Returns the offset. - * - * For example: - * - * DateTime.parse('04pm+0730').offset #=> (5/16) - */ -static VALUE -d_lite_offset(VALUE self) -{ - get_d1(self); - return m_of_in_day(dat); -} - -/* - * call-seq: - * d.zone -> string - * - * Returns the timezone. - * - * For example: - * - * DateTime.parse('04pm+0730').zone #=> "+07:30" - */ -static VALUE -d_lite_zone(VALUE self) -{ - get_d1(self); - return m_zone(dat); -} - -/* - * call-seq: - * d.julian? -> bool - * - * Retruns true if the date is before the day of calendar reform. - * - * For example: - * - * Date.new(1582,10,15).julian? #=> false - * (Date.new(1582,10,15) - 1).julian? #=> true - */ -static VALUE -d_lite_julian_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_julian_p(dat)); -} - -/* - * call-seq: - * d.gregorian? -> bool - * - * Retunrs true if the date is on or after the day of calendar reform. - * - * For example: - * - * Date.new(1582,10,15).gregorian? #=> true - * (Date.new(1582,10,15) - 1).gregorian? #=> false - */ -static VALUE -d_lite_gregorian_p(VALUE self) -{ - get_d1(self); - return f_boolcast(m_gregorian_p(dat)); -} - -/* - * call-seq: - * d.leap? -> bool - * - * Returns true if the year is a leap year. - * - * For example: - * - * Date.new(2000).leap? #=> true - * Date.new(2001).leap? #=> false - */ -static VALUE -d_lite_leap_p(VALUE self) -{ - int rjd, ns, ry, rm, rd; - - get_d1(self); - if (m_gregorian_p(dat)) - return f_boolcast(c_gregorian_leap_p(m_year(dat))); - - c_civil_to_jd(m_year(dat), 3, 1, m_virtual_sg(dat), - &rjd, &ns); - c_jd_to_civil(rjd - 1, m_virtual_sg(dat), &ry, &rm, &rd); - return f_boolcast(rd == 29); -} - -/* - * call-seq: - * d.start -> float - * - * Returns the Julian day number denoting the day of calendar reform. - * - * For example: - * - * Date.new(2001,2,3).start #=> 2299161.0 - * Date.new(2001,2,3,Date::GREGORIAN).start #=> -Infinity - */ -static VALUE -d_lite_start(VALUE self) -{ - get_d1(self); - return DBL2NUM(m_sg(dat)); -} - -static void -clear_civil(union DateData *x) -{ - if (simple_dat_p(x)) { - x->s.year = 0; -#ifndef USE_PACK - x->s.mon = 0; - x->s.mday = 0; -#else - x->s.pc = 0; -#endif - x->s.flags &= ~HAVE_CIVIL; - } - else { - x->c.year = 0; -#ifndef USE_PACK - x->c.mon = 0; - x->c.mday = 0; - x->c.hour = 0; - x->c.min = 0; - x->c.sec = 0; -#else - x->c.pc = 0; -#endif - x->c.flags &= ~(HAVE_CIVIL | HAVE_TIME); - } -} - -static void -set_sg(union DateData *x, double sg) -{ - if (simple_dat_p(x)) { - get_s_jd(x); - clear_civil(x); - x->s.sg = (sg_cast)sg; - } else { - get_c_jd(x); - get_c_df(x); - clear_civil(x); - x->c.sg = (sg_cast)sg; - } -} - -static VALUE -dup_obj_with_new_start(VALUE obj, double sg) -{ - volatile VALUE dup = dup_obj(obj); - { - get_d1(dup); - set_sg(dat, sg); - } - return dup; -} - -/* - * call-seq: - * d.new_start([start=Date::ITALY]) -> date - * - * Duplicates self and resets its the day of calendar reform. - * - * For example: - * - * d = Date.new(1582,10,15) - * d.new_start(Date::JULIAN) #=> #<Date: 1582-10-05 ...> - */ -static VALUE -d_lite_new_start(int argc, VALUE *argv, VALUE self) -{ - VALUE vsg; - double sg; - - rb_scan_args(argc, argv, "01", &vsg); - - sg = DEFAULT_SG; - if (argc >= 1) - val2sg(vsg, sg); - - return dup_obj_with_new_start(self, sg); -} - -/* - * call-seq: - * d.italy -> date - * - * This method is equivalent to new_start(Date::ITALY). - */ -static VALUE -d_lite_italy(VALUE self) -{ - return dup_obj_with_new_start(self, ITALY); -} - -/* - * call-seq: - * d.england -> date - * - * This method is equivalent to new_start(Date::ENGLAND). - */ -static VALUE -d_lite_england(VALUE self) -{ - return dup_obj_with_new_start(self, ENGLAND); -} - -/* - * call-seq: - * d.julian -> date - * - * This method is equivalent to new_start(Date::JULIAN). - */ -static VALUE -d_lite_julian(VALUE self) -{ - return dup_obj_with_new_start(self, JULIAN); -} - -/* - * call-seq: - * d.gregorian -> date - * - * This method is equivalent to new_start(Date::GREGORIAN). - */ -static VALUE -d_lite_gregorian(VALUE self) -{ - return dup_obj_with_new_start(self, GREGORIAN); -} - -static void -set_of(union DateData *x, int of) -{ - assert(complex_dat_p(x)); - get_c_jd(x); - get_c_df(x); - clear_civil(x); - x->c.of = of; -} - -static VALUE -dup_obj_with_new_offset(VALUE obj, int of) -{ - volatile VALUE dup = dup_obj_as_complex(obj); - { - get_d1(dup); - set_of(dat, of); - } - return dup; -} - -/* - * call-seq: - * d.new_offset([offset=0]) -> date - * - * Duplicates self and resets its offset. - * - * For example: - * - * d = DateTime.new(2001,2,3,4,5,6,'-02:00') - * #=> #<DateTime: 2001-02-03T04:05:06-02:00 ...> - * d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...> - */ -static VALUE -d_lite_new_offset(int argc, VALUE *argv, VALUE self) -{ - VALUE vof; - int rof; - - rb_scan_args(argc, argv, "01", &vof); - - rof = 0; - if (argc >= 1) - val2off(vof, rof); - - return dup_obj_with_new_offset(self, rof); -} - -/* - * call-seq: - * d + other -> date - * - * Returns a date object pointing other days after self. The other - * should be a numeric value. If the other is flonum, assumes its - * precision is at most nanosecond. - * - * For example: - * - * Date.new(2001,2,3) + 1 #=> #<Date: 2001-02-04 ...> - * DateTime.new(2001,2,3) + Rational(1,2) - * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...> - * DateTime.new(2001,2,3) + Rational(-1,2) - * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...> - * DateTime.jd(0,12) + DateTime.new(2001,2,3).ajd - * #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> - */ -static VALUE -d_lite_plus(VALUE self, VALUE other) -{ - get_d1(self); - - switch (TYPE(other)) { - case T_FIXNUM: - { - VALUE nth; - long t; - int jd; - - nth = m_nth(dat); - t = FIX2LONG(other); - if (DIV(t, CM_PERIOD)) { - nth = f_add(nth, INT2FIX(DIV(t, CM_PERIOD))); - t = MOD(t, CM_PERIOD); - } - - if (!t) - jd = m_jd(dat); - else { - jd = m_jd(dat) + (int)t; - - if (jd < 0) { - nth = f_sub(nth, INT2FIX(1)); - jd += CM_PERIOD; - } - else if (jd >= CM_PERIOD) { - nth = f_add(nth, INT2FIX(1)); - jd -= CM_PERIOD; - } - } - - if (simple_dat_p(dat)) - return d_simple_new_internal(rb_obj_class(self), - nth, jd, - dat->s.sg, - 0, 0, 0, - (dat->s.flags | HAVE_JD) & - ~HAVE_CIVIL); - else - return d_complex_new_internal(rb_obj_class(self), - nth, jd, - dat->c.df, dat->c.sf, - dat->c.of, dat->c.sg, - 0, 0, 0, -#ifndef USE_PACK - dat->c.hour, - dat->c.min, - dat->c.sec, -#else - EX_HOUR(dat->c.pc), - EX_MIN(dat->c.pc), - EX_SEC(dat->c.pc), -#endif - (dat->c.flags | HAVE_JD) & - ~HAVE_CIVIL); - } - break; - case T_BIGNUM: - { - VALUE nth; - int jd, s; - - if (f_positive_p(other)) - s = +1; - else { - s = -1; - other = f_negate(other); - } - - nth = f_idiv(other, INT2FIX(CM_PERIOD)); - jd = FIX2INT(f_mod(other, INT2FIX(CM_PERIOD))); - - if (s < 0) { - nth = f_negate(nth); - jd = -jd; - } - - if (!jd) - jd = m_jd(dat); - else { - jd = m_jd(dat) + jd; - if (jd < 0) { - nth = f_sub(nth, INT2FIX(1)); - jd += CM_PERIOD; - } - else if (jd >= CM_PERIOD) { - nth = f_add(nth, INT2FIX(1)); - jd -= CM_PERIOD; - } - } - - if (f_zero_p(nth)) - nth = m_nth(dat); - else - nth = f_add(m_nth(dat), nth); - - if (simple_dat_p(dat)) - return d_simple_new_internal(rb_obj_class(self), - nth, jd, - dat->s.sg, - 0, 0, 0, - (dat->s.flags | HAVE_JD) & - ~HAVE_CIVIL); - else - return d_complex_new_internal(rb_obj_class(self), - nth, jd, - dat->c.df, dat->c.sf, - dat->c.of, dat->c.sg, - 0, 0, 0, -#ifndef USE_PACK - dat->c.hour, - dat->c.min, - dat->c.sec, -#else - EX_HOUR(dat->c.pc), - EX_MIN(dat->c.pc), - EX_SEC(dat->c.pc), -#endif - (dat->c.flags | HAVE_JD) & - ~HAVE_CIVIL); - } - break; - case T_FLOAT: - { - double jd, o, tmp; - int s, df; - VALUE nth, sf; - - o = RFLOAT_VALUE(other); - - if (o > 0) - s = +1; - else { - s = -1; - o = -o; - } - - o = modf(o, &tmp); - - if (!floor(tmp / CM_PERIOD)) { - nth = INT2FIX(0); - jd = (int)tmp; - } - else { - double i, f; - - f = modf(tmp / CM_PERIOD, &i); - nth = f_floor(DBL2NUM(i)); - jd = (int)(f * CM_PERIOD); - } - - o *= DAY_IN_SECONDS; - o = modf(o, &tmp); - df = (int)tmp; - o *= SECOND_IN_NANOSECONDS; - sf = INT2FIX((int)round(o)); - - if (s < 0) { - jd = -jd; - df = -df; - sf = f_negate(sf); - } - - if (f_zero_p(sf)) - sf = m_sf(dat); - else { - sf = f_add(m_sf(dat), sf); - if (f_lt_p(sf, INT2FIX(0))) { - df -= 1; - sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { - df += 1; - sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - } - - if (!df) - df = m_df(dat); - else { - df = m_df(dat) + df; - if (df < 0) { - jd -= 1; - df += DAY_IN_SECONDS; - } - else if (df >= DAY_IN_SECONDS) { - jd += 1; - df -= DAY_IN_SECONDS; - } - } - - if (!jd) - jd = m_jd(dat); - else { - jd = m_jd(dat) + jd; - if (jd < 0) { - nth = f_sub(nth, INT2FIX(1)); - jd += CM_PERIOD; - } - else if (jd >= CM_PERIOD) { - nth = f_add(nth, INT2FIX(1)); - jd -= CM_PERIOD; - } - } - - if (f_zero_p(nth)) - nth = m_nth(dat); - else - nth = f_add(m_nth(dat), nth); - - if (!df && f_zero_p(sf) && !m_of(dat)) - return d_simple_new_internal(rb_obj_class(self), - nth, (int)jd, - m_sg(dat), - 0, 0, 0, - (dat->s.flags | HAVE_JD) & - ~(HAVE_CIVIL | HAVE_TIME | - COMPLEX_DAT)); - else - return d_complex_new_internal(rb_obj_class(self), - nth, (int)jd, - df, sf, - m_of(dat), m_sg(dat), - 0, 0, 0, - 0, 0, 0, - (dat->c.flags | - HAVE_JD | HAVE_DF) & - ~(HAVE_CIVIL | HAVE_TIME)); - } - break; - default: - if (!k_numeric_p(other)) - rb_raise(rb_eTypeError, "expected numeric"); - other = f_to_r(other); -#ifdef CANONICALIZATION_FOR_MATHN - if (!k_rational_p(other)) - return d_lite_plus(self, other); -#endif - /* fall through */ - case T_RATIONAL: - { - VALUE nth, sf, t; - int jd, df, s; - - if (wholenum_p(other)) - return d_lite_plus(self, RRATIONAL(other)->num); - - if (f_positive_p(other)) - s = +1; - else { - s = -1; - other = f_negate(other); - } - - nth = f_idiv(other, INT2FIX(CM_PERIOD)); - t = f_mod(other, INT2FIX(CM_PERIOD)); - - jd = FIX2INT(f_idiv(t, INT2FIX(1))); - t = f_mod(t, INT2FIX(1)); - - t = f_mul(t, INT2FIX(DAY_IN_SECONDS)); - df = FIX2INT(f_idiv(t, INT2FIX(1))); - t = f_mod(t, INT2FIX(1)); - - sf = f_mul(t, INT2FIX(SECOND_IN_NANOSECONDS)); - - if (s < 0) { - nth = f_negate(nth); - jd = -jd; - df = -df; - sf = f_negate(sf); - } - - if (f_zero_p(sf)) - sf = m_sf(dat); - else { - sf = f_add(m_sf(dat), sf); - if (f_lt_p(sf, INT2FIX(0))) { - df -= 1; - sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { - df += 1; - sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - } - - if (!df) - df = m_df(dat); - else { - df = m_df(dat) + df; - if (df < 0) { - jd -= 1; - df += DAY_IN_SECONDS; - } - else if (df >= DAY_IN_SECONDS) { - jd += 1; - df -= DAY_IN_SECONDS; - } - } - - if (!jd) - jd = m_jd(dat); - else { - jd = m_jd(dat) + jd; - if (jd < 0) { - nth = f_sub(nth, INT2FIX(1)); - jd += CM_PERIOD; - } - else if (jd >= CM_PERIOD) { - nth = f_add(nth, INT2FIX(1)); - jd -= CM_PERIOD; - } - } - - if (f_zero_p(nth)) - nth = m_nth(dat); - else - nth = f_add(m_nth(dat), nth); - - if (!df && f_zero_p(sf) && !m_of(dat)) - return d_simple_new_internal(rb_obj_class(self), - nth, jd, - m_sg(dat), - 0, 0, 0, - (dat->s.flags | HAVE_JD) & - ~(HAVE_CIVIL | HAVE_TIME | - COMPLEX_DAT)); - else - return d_complex_new_internal(rb_obj_class(self), - nth, jd, - df, sf, - m_of(dat), m_sg(dat), - 0, 0, 0, - 0, 0, 0, - (dat->c.flags | - HAVE_JD | HAVE_DF) & - ~(HAVE_CIVIL | HAVE_TIME)); - } - break; - } -} - -static VALUE -minus_dd(VALUE self, VALUE other) -{ - get_d2(self, other); - - { - int d, df; - VALUE n, sf, r; - - n = f_sub(m_nth(adat), m_nth(bdat)); - d = m_jd(adat) - m_jd(bdat); - df = m_df(adat) - m_df(bdat); - sf = f_sub(m_sf(adat), m_sf(bdat)); - - if (d < 0) { - n = f_sub(n, INT2FIX(1)); - d += CM_PERIOD; - } - else if (d >= CM_PERIOD) { - n = f_add(n, INT2FIX(1)); - d -= CM_PERIOD; - } - - if (df < 0) { - d -= 1; - df += DAY_IN_SECONDS; - } - else if (df >= DAY_IN_SECONDS) { - d += 1; - df -= DAY_IN_SECONDS; - } - - if (f_lt_p(sf, INT2FIX(0))) { - df -= 1; - sf = f_add(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - else if (f_ge_p(sf, INT2FIX(SECOND_IN_NANOSECONDS))) { - df += 1; - sf = f_sub(sf, INT2FIX(SECOND_IN_NANOSECONDS)); - } - - if (f_zero_p(n)) - r = INT2FIX(0); - else - r = f_mul(n, INT2FIX(CM_PERIOD)); - - if (d) - r = f_add(r, rb_rational_new1(INT2FIX(d))); - if (df) - r = f_add(r, isec_to_day(df)); - if (f_nonzero_p(sf)) - r = f_add(r, ns_to_day(sf)); - - if (TYPE(r) == T_RATIONAL) - return r; - return rb_rational_new1(r); - } -} - -/* - * call-seq: - * d - other -> date or rational - * - * Returns the difference between the two dates if the other is a date - * object. If the other is a numeric value, returns a date object - * pointing other days before self. If the other is flonum, assumes - * its precision is at most nanosecond. - * - * For example: - * - * Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...> - * DateTime.new(2001,2,3) - Rational(1,2) - * #=> #<DateTime: 2001-02-02T12:00:00+00:00 ...> - * Date.new(2001,2,3) - Date.new(2001) - * #=> (33/1) - * DateTime.new(2001,2,3) - DateTime.new(2001,2,2,12) - * #=> (1/2) - */ -static VALUE -d_lite_minus(VALUE self, VALUE other) -{ - if (k_date_p(other)) - return minus_dd(self, other); - - switch (TYPE(other)) { - case T_FIXNUM: - return d_lite_plus(self, LONG2NUM(-FIX2LONG(other))); - case T_FLOAT: - return d_lite_plus(self, DBL2NUM(-RFLOAT_VALUE(other))); - default: - if (!k_numeric_p(other)) - rb_raise(rb_eTypeError, "expected numeric"); - /* fall through */ - case T_BIGNUM: - case T_RATIONAL: - return d_lite_plus(self, f_negate(other)); - } -} - -/* - * call-seq: - * d.next_day([n=1]) -> date - * - * This method is equivalent to d + n. - */ -static VALUE -d_lite_next_day(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_plus(self, n); -} - -/* - * call-seq: - * d.prev_day([n=1]) -> date - * - * This method is equivalent to d - n. - */ -static VALUE -d_lite_prev_day(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_minus(self, n); -} - -/* - * call-seq: - * d.next -> date - * - * Returns a date object denoting the following day. - */ -static VALUE -d_lite_next(VALUE self) -{ - return d_lite_next_day(0, (VALUE *)NULL, self); -} - -/* - * call-seq: - * d >> n -> date - * - * Returns a date object pointing n months after self. The n should - * be a numeric value. - * - * For example: - * - * Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...> - * Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...> - * Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...> - */ -static VALUE -d_lite_rshift(VALUE self, VALUE other) -{ - VALUE t, y, nth, rjd2; - int m, d, rjd; - double sg; - - get_d1(self); - t = f_add3(f_mul(m_real_year(dat), INT2FIX(12)), - INT2FIX(m_mon(dat) - 1), - other); - if (FIXNUM_P(t)) { - long it = FIX2LONG(t); - y = LONG2NUM(DIV(it, 12)); - it = MOD(it, 12); - m = (int)it + 1; - } - else { - y = f_idiv(t, INT2FIX(12)); - t = f_mod(t, INT2FIX(12)); - m = FIX2INT(t) + 1; - } - d = m_mday(dat); - sg = m_sg(dat); - - while (1) { - int ry, rm, rd, ns; - - if (valid_civil_p(y, m, d, sg, - &nth, &ry, - &rm, &rd, &rjd, &ns)) - break; - if (--d < 1) - rb_raise(rb_eArgError, "invalid date"); - } - encode_jd(nth, rjd, &rjd2); - return d_lite_plus(self, f_sub(rjd2, m_real_local_jd(dat))); -} - -/* - * call-seq: - * d << n -> date - * - * Returns a date object pointing n months before self. The n should - * be a numeric value. - * - * For example: - * - * Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...> - * Date.new(2001,1,31) << 11 #=> #<Date: 2000-02-29 ...> - * Date.new(2001,2,3) << -1 #=> #<Date: 2001-03-03 ...> - */ -static VALUE -d_lite_lshift(VALUE self, VALUE other) -{ - return d_lite_rshift(self, f_negate(other)); -} - -/* - * call-seq: - * d.next_month([n=1]) -> date - * - * This method is equivalent to d >> n - */ -static VALUE -d_lite_next_month(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_rshift(self, n); -} - -/* - * call-seq: - * d.prev_month([n=1]) -> date - * - * This method is equivalent to d << n - */ -static VALUE -d_lite_prev_month(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_lshift(self, n); -} - -/* - * call-seq: - * d.next_year([n=1]) -> date - * - * This method is equivalent to d >> (n * 12) - */ -static VALUE -d_lite_next_year(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_rshift(self, f_mul(n, INT2FIX(12))); -} - -/* - * call-seq: - * d.prev_year([n=1]) -> date - * - * This method is equivalent to d << (n * 12) - */ -static VALUE -d_lite_prev_year(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - if (argc < 1) - n = INT2FIX(1); - return d_lite_lshift(self, f_mul(n, INT2FIX(12))); -} - -static VALUE d_lite_cmp(VALUE, VALUE); - -/* - * call-seq: - * d.step(limit[, step=1]) -> enumerator - * d.step(limit[, step=1]){|date| ...} -> self - * - * Iterates evaluation of the given block, which takes a date object. - * The limit should be a date object. - * - * For example: - * - * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size - * #=> 52 - */ -static VALUE -d_lite_step(int argc, VALUE *argv, VALUE self) -{ - VALUE limit, step, date; - - rb_scan_args(argc, argv, "11", &limit, &step); - - if (argc < 2) - step = INT2FIX(1); - -#if 0 - if (f_zero_p(step)) - rb_raise(rb_eArgError, "step can't be 0"); -#endif - - RETURN_ENUMERATOR(self, argc, argv); - - date = self; - switch (FIX2INT(f_cmp(step, INT2FIX(0)))) { - case -1: - while (FIX2INT(d_lite_cmp(date, limit)) >= 0) { - rb_yield(date); - date = d_lite_plus(date, step); - } - break; - case 0: - while (1) - rb_yield(date); - break; - case 1: - while (FIX2INT(d_lite_cmp(date, limit)) <= 0) { - rb_yield(date); - date = d_lite_plus(date, step); - } - break; - default: - abort(); - } - return self; -} - -/* - * call-seq: - * d.upto(max) -> enumerator - * d.upto(max){|date| ...} -> self - * - * This method is equivalent to step(max, 1){|date| ...}. - */ -static VALUE -d_lite_upto(VALUE self, VALUE max) -{ - VALUE date; - - RETURN_ENUMERATOR(self, 1, &max); - - date = self; - while (FIX2INT(d_lite_cmp(date, max)) <= 0) { - rb_yield(date); - date = d_lite_plus(date, INT2FIX(1)); - } - return self; -} - -/* - * call-seq: - * d.downto(min) -> enumerator - * d.downto(min){|date| ...} -> self - * - * This method is equivalent to step(min, -1){|date| ...}. - */ -static VALUE -d_lite_downto(VALUE self, VALUE min) -{ - VALUE date; - - RETURN_ENUMERATOR(self, 1, &min); - - date = self; - while (FIX2INT(d_lite_cmp(date, min)) >= 0) { - rb_yield(date); - date = d_lite_plus(date, INT2FIX(-1)); - } - return self; -} - -static VALUE -cmp_gen(VALUE self, VALUE other) -{ - get_d1(self); - - if (k_numeric_p(other)) - return f_cmp(m_ajd(dat), other); - else if (k_date_p(other)) - return f_cmp(m_ajd(dat), f_ajd(other)); - return rb_num_coerce_cmp(self, other, rb_intern("<=>")); -} - -static VALUE -cmp_dd(VALUE self, VALUE other) -{ - get_d2(self, other); - - { - VALUE a_nth, b_nth, - a_sf, b_sf; - int a_jd, b_jd, - a_df, b_df; - - a_nth = m_nth(adat); - b_nth = m_nth(bdat); - if (f_eqeq_p(a_nth, b_nth)) { - a_jd = m_jd(adat); - b_jd = m_jd(bdat); - if (a_jd == b_jd) { - a_df = m_df(adat); - b_df = m_df(bdat); - if (a_df == b_df) { - a_sf = m_sf(adat); - b_sf = m_sf(bdat); - if (f_eqeq_p(a_sf, b_sf)) { - return INT2FIX(0); - } - else if (f_lt_p(a_sf, b_sf)) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (a_df < b_df) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (a_jd < b_jd) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (f_lt_p(a_nth, b_nth)) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } -} - -/* - * call-seq: - * d <=> other -> -1, 0, +1 or nil - * - * Compares the two dates and returns -1, zero, 1 or nil. The other - * should be a date object or a numeric value as an astronomical - * Julian day number. - * - * For example: - * - * Date.new(2001,2,3) <=> Date.new(2001,2,4) #=> -1 - * Date.new(2001,2,3) <=> Date.new(2001,2,3) #=> 0 - * Date.new(2001,2,3) <=> Date.new(2001,2,2) #=> 1 - * Date.new(2001,2,3) <=> Object.new #=> nil - * Date.new(2001,2,3) <=> Rational(4903887,2)#=> 0 - * - * See also Comparable. - */ -static VALUE -d_lite_cmp(VALUE self, VALUE other) -{ - if (!k_date_p(other)) - return cmp_gen(self, other); - - { - get_d2(self, other); - - if (!(simple_dat_p(adat) && simple_dat_p(bdat) && - m_gregorian_p(adat) == m_gregorian_p(bdat))) - return cmp_dd(self, other); - - if (have_jd_p(adat) && - have_jd_p(bdat)) { - VALUE a_nth, b_nth; - int a_jd, b_jd; - - a_nth = m_nth(adat); - b_nth = m_nth(bdat); - if (f_eqeq_p(a_nth, b_nth)) { - a_jd = m_jd(adat); - b_jd = m_jd(bdat); - if (a_jd == b_jd) { - return INT2FIX(0); - } - else if (a_jd < b_jd) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (a_nth < b_nth) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else { -#ifndef USE_PACK - VALUE a_nth, b_nth; - int a_year, b_year, - a_mon, b_mon, - a_mday, b_mday; -#else - VALUE a_nth, b_nth; - int a_year, b_year, - a_pd, b_pd; -#endif - - a_nth = m_nth(adat); - b_nth = m_nth(bdat); - if (f_eqeq_p(a_nth, b_nth)) { - a_year = m_year(adat); - b_year = m_year(bdat); - if (a_year == b_year) { -#ifndef USE_PACK - a_mon = m_mon(adat); - b_mon = m_mon(bdat); - if (a_mon == b_mon) { - a_mday = m_mday(adat); - b_mday = m_mday(bdat); - if (a_mday == b_mday) { - return INT2FIX(0); - } - else if (a_mday < b_mday) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (a_mon < b_mon) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } -#else - a_pd = m_pc(adat); - b_pd = m_pc(bdat); - if (a_pd == b_pd) { - return INT2FIX(0); - } - else if (a_pd < b_pd) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } -#endif - } - else if (a_year < b_year) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - else if (f_lt_p(a_nth, b_nth)) { - return INT2FIX(-1); - } - else { - return INT2FIX(1); - } - } - } -} - -static VALUE -equal_gen(VALUE self, VALUE other) -{ - get_d1(self); - - if (k_numeric_p(other)) - return f_eqeq_p(m_real_local_jd(dat), other); - else if (k_date_p(other)) - return f_eqeq_p(m_real_local_jd(dat), f_jd(other)); - return rb_num_coerce_cmp(self, other, rb_intern("==")); -} - -/* - * call-seq: - * d === other -> bool - * - * Returns true if they are the same day. - * - * For example: - * - * Date.new(2001,2,3) === Date.new(2001,2,3) - * #=> true - * Date.new(2001,2,3) === Date.new(2001,2,4) - * #=> false - * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,12) - * #=> true - * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,0,0,0,'+24:00') - * #=> true - * DateTime.new(2001,2,3) === DateTime.new(2001,2,4,0,0,0,'+24:00') - * #=> false - */ -static VALUE -d_lite_equal(VALUE self, VALUE other) -{ - if (!k_date_p(other)) - return equal_gen(self, other); - - { - get_d2(self, other); - - if (!(m_gregorian_p(adat) == m_gregorian_p(bdat))) - return equal_gen(self, other); - - if (have_jd_p(adat) && - have_jd_p(bdat)) { - VALUE a_nth, b_nth; - int a_jd, b_jd; - - a_nth = m_nth(adat); - b_nth = m_nth(bdat); - a_jd = m_local_jd(adat); - b_jd = m_local_jd(bdat); - if (f_eqeq_p(a_nth, b_nth) && - a_jd == b_jd) - return Qtrue; - return Qfalse; - } - else { -#ifndef USE_PACK - VALUE a_nth, b_nth; - int a_year, b_year, - a_mon, b_mon, - a_mday, b_mday; -#else - VALUE a_nth, b_nth; - int a_year, b_year, - a_pd, b_pd; -#endif - - a_nth = m_nth(adat); - b_nth = m_nth(bdat); - if (f_eqeq_p(a_nth, b_nth)) { - a_year = m_year(adat); - b_year = m_year(bdat); - if (a_year == b_year) { -#ifndef USE_PACK - a_mon = m_mon(adat); - b_mon = m_mon(bdat); - if (a_mon == b_mon) { - a_mday = m_mday(adat); - b_mday = m_mday(bdat); - if (a_mday == b_mday) - return Qtrue; - } -#else - /* mon and mday only */ - a_pd = (m_pc(adat) >> MDAY_SHIFT); - b_pd = (m_pc(bdat) >> MDAY_SHIFT); - if (a_pd == b_pd) { - return Qtrue; - } -#endif - } - } - return Qfalse; - } - } -} - -/* :nodoc: */ -static VALUE -d_lite_eql_p(VALUE self, VALUE other) -{ - if (!k_date_p(other)) - return Qfalse; - return f_zero_p(d_lite_cmp(self, other)); -} - -/* :nodoc: */ -static VALUE -d_lite_hash(VALUE self) -{ - st_index_t v, h[4]; - - get_d1(self); - h[0] = m_nth(dat); - h[1] = m_jd(dat); - h[2] = m_df(dat); - h[3] = m_sf(dat); - v = rb_memhash(h, sizeof(h)); - return LONG2FIX(v); -} - -#include "date_tmx.h" -static void set_tmx(VALUE, struct tmx *); -static VALUE strftimev(const char *, VALUE, - void (*)(VALUE, struct tmx *)); - -/* - * call-seq: - * d.to_s -> string - * - * Returns a string in an ISO 8601 format (This method doesn't use the - * expanded representations). - * - * For example: - * - * Date.new(2001,2,3).to_s #=> "2001-02-03" - */ -static VALUE -d_lite_to_s(VALUE self) -{ - return strftimev("%Y-%m-%d", self, set_tmx); -} - -#ifndef NDEBUG -static VALUE -mk_inspect_flags(union DateData *x) -{ - return rb_enc_sprintf(rb_usascii_encoding(), - "%c%c%c%c%c", - (x->flags & COMPLEX_DAT) ? 'C' : 'S', - (x->flags & HAVE_JD) ? 'j' : '-', - (x->flags & HAVE_DF) ? 'd' : '-', - (x->flags & HAVE_CIVIL) ? 'c' : '-', - (x->flags & HAVE_TIME) ? 't' : '-'); -} - -static VALUE -mk_inspect_raw(union DateData *x, const char *klass) -{ - if (simple_dat_p(x)) { - VALUE nth, flags; - - RB_GC_GUARD(nth) = f_inspect(x->s.nth); - RB_GC_GUARD(flags) = mk_inspect_flags(x); - - return rb_enc_sprintf(rb_usascii_encoding(), - "#<%s: " - "(%sth,%dj),+0s,%.0fj; " - "%dy%dm%dd; %s>", - klass ? klass : "?", - RSTRING_PTR(nth), x->s.jd, x->s.sg, -#ifndef USE_PACK - x->s.year, x->s.mon, x->s.mday, -#else - x->s.year, - EX_MON(x->s.pc), EX_MDAY(x->s.pc), -#endif - RSTRING_PTR(flags)); - } - else { - VALUE nth, sf, flags; - - RB_GC_GUARD(nth) = f_inspect(x->c.nth); - RB_GC_GUARD(sf) = f_inspect(x->c.sf); - RB_GC_GUARD(flags) = mk_inspect_flags(x); - - return rb_enc_sprintf(rb_usascii_encoding(), - "#<%s: " - "(%sth,%dj,%ds,%sn),%+ds,%.0fj; " - "%dy%dm%dd %dh%dm%ds; %s>", - klass ? klass : "?", - RSTRING_PTR(nth), x->c.jd, x->c.df, - RSTRING_PTR(sf), - x->c.of, x->c.sg, -#ifndef USE_PACK - x->c.year, x->c.mon, x->c.mday, - x->c.hour, x->c.min, x->c.sec, -#else - x->c.year, - EX_MON(x->c.pc), EX_MDAY(x->c.pc), - EX_HOUR(x->c.pc), EX_MIN(x->c.pc), - EX_SEC(x->c.pc), -#endif - RSTRING_PTR(flags)); - } -} - -static VALUE -d_lite_inspect_raw(VALUE self) -{ - get_d1(self); - return mk_inspect_raw(dat, rb_obj_classname(self)); -} -#endif - -static VALUE -mk_inspect(union DateData *x, const char *klass, const char *to_s) -{ - VALUE jd, sf; - - RB_GC_GUARD(jd) = f_inspect(m_real_jd(x)); - RB_GC_GUARD(sf) = f_inspect(m_sf(x)); - - return rb_enc_sprintf(rb_usascii_encoding(), - "#<%s: %s ((%sj,%ds,%sn),%+ds,%.0fj)>", - klass ? klass : "?", - to_s ? to_s : "?", - RSTRING_PTR(jd), m_df(x), RSTRING_PTR(sf), - m_of(x), m_sg(x)); -} - -/* - * call-seq: - * d.inspect -> string - * - * Returns the value as a string for inspection. - * - * For example: - * - * Date.new(2001,2,3).inspect - * #=> "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>" - * DateTime.new(2001,2,3,4,5,6,'-7').inspect - * #=> "#<DateTime: 2001-02-03T04:05:06-07:00 ((2451944j,39906s,0n),-25200s,2299161j)>" - * - */ -static VALUE -d_lite_inspect(VALUE self) -{ - get_d1(self); - { - VALUE to_s; - - RB_GC_GUARD(to_s) = f_to_s(self); - return mk_inspect(dat, rb_obj_classname(self), RSTRING_PTR(to_s)); - } -} - -#include <errno.h> -#include "date_tmx.h" - -size_t date_strftime(char *s, size_t maxsize, const char *format, - const struct tmx *tmx); - -#define SMALLBUF 100 -static size_t -date_strftime_alloc(char **buf, const char *format, - struct tmx *tmx) -{ - size_t size, len, flen; - - (*buf)[0] = '\0'; - flen = strlen(format); - if (flen == 0) { - return 0; - } - errno = 0; - len = date_strftime(*buf, SMALLBUF, format, tmx); - if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len; - for (size=1024; ; size*=2) { - *buf = xmalloc(size); - (*buf)[0] = '\0'; - len = date_strftime(*buf, size, format, tmx); - /* - * buflen can be zero EITHER because there's not enough - * room in the string, or because the control command - * goes to the empty string. Make a reasonable guess that - * if the buffer is 1024 times bigger than the length of the - * format string, it's not failing for lack of room. - */ - if (len > 0) break; - xfree(*buf); - if (size >= 1024 * flen) { - rb_sys_fail(format); - break; - } - } - return len; -} - -static VALUE -tmx_m_secs(union DateData *x) -{ - VALUE s; - int df; - - s = day_to_sec(f_sub(m_real_jd(x), - UNIX_EPOCH_IN_CJD)); - if (simple_dat_p(x)) - return s; - df = m_df(x); - if (df) - s = f_add(s, INT2FIX(df)); - return s; -} - -#define MILLISECOND_IN_NANOSECONDS 1000000 - -static VALUE -tmx_m_msecs(union DateData *x) -{ - VALUE s, sf; - - s = sec_to_ms(tmx_m_secs(x)); - if (simple_dat_p(x)) - return s; - sf = m_sf(x); - if (f_nonzero_p(sf)) - s = f_add(s, f_div(sf, INT2FIX(MILLISECOND_IN_NANOSECONDS))); - return s; -} - -static VALUE -tmx_m_of(union DateData *x) -{ - return INT2FIX(m_of(x)); -} - -static char * -tmx_m_zone(union DateData *x) -{ - return RSTRING_PTR(m_zone(x)); -} - -static struct tmx_funcs tmx_funcs = { - (VALUE (*)(void *))m_real_year, - (int (*)(void *))m_yday, - (int (*)(void *))m_mon, - (int (*)(void *))m_mday, - (VALUE (*)(void *))m_real_cwyear, - (int (*)(void *))m_cweek, - (int (*)(void *))m_cwday, - (int (*)(void *))m_wnum0, - (int (*)(void *))m_wnum1, - (int (*)(void *))m_wday, - (int (*)(void *))m_hour, - (int (*)(void *))m_min, - (int (*)(void *))m_sec, - (VALUE (*)(void *))m_sf_in_sec, - (VALUE (*)(void *))tmx_m_secs, - (VALUE (*)(void *))tmx_m_msecs, - (VALUE (*)(void *))tmx_m_of, - (char *(*)(void *))tmx_m_zone -}; - -static void -set_tmx(VALUE self, struct tmx *tmx) -{ - get_d1(self); - tmx->dat = (void *)dat; - tmx->funcs = &tmx_funcs; -} - -static VALUE -date_strftime_internal(int argc, VALUE *argv, VALUE self, - const char *default_fmt, - void (*func)(VALUE, struct tmx *)) -{ - VALUE vfmt; - const char *fmt; - long len; - char buffer[SMALLBUF], *buf = buffer; - struct tmx tmx; - VALUE str; - - rb_scan_args(argc, argv, "01", &vfmt); - - if (argc < 1) - vfmt = rb_usascii_str_new2(default_fmt); - else { - StringValue(vfmt); - if (!rb_enc_str_asciicompat_p(vfmt)) { - rb_raise(rb_eArgError, - "format should have ASCII compatible encoding"); - } - } - fmt = RSTRING_PTR(vfmt); - len = RSTRING_LEN(vfmt); - (*func)(self, &tmx); - if (memchr(fmt, '\0', len)) { - /* Ruby string may contain \0's. */ - const char *p = fmt, *pe = fmt + len; - - str = rb_str_new(0, 0); - while (p < pe) { - len = date_strftime_alloc(&buf, p, &tmx); - rb_str_cat(str, buf, len); - p += strlen(p); - if (buf != buffer) { - xfree(buf); - buf = buffer; - } - for (fmt = p; p < pe && !*p; ++p); - if (p > fmt) rb_str_cat(str, fmt, p - fmt); - } - rb_enc_copy(str, vfmt); - OBJ_INFECT(str, vfmt); - return str; - } - else - len = date_strftime_alloc(&buf, fmt, &tmx); - - str = rb_str_new(buf, len); - if (buf != buffer) xfree(buf); - rb_enc_copy(str, vfmt); - OBJ_INFECT(str, vfmt); - return str; -} - -/* - * call-seq: - * d.strftime([format='%F']) -> string - * - * Formats date according to the directives in the given format - * string. - * The directives begins with a percent (%) character. - * Any text not listed as a directive will be passed through to the - * output string. - * - * The directive consists of a percent (%) character, - * zero or more flags, optional minimum field width, - * optional modifier and a conversion specifier - * as follows. - * - * %<flags><width><modifier><conversion> - * - * Flags: - * - don't pad a numerical output. - * _ use spaces for padding. - * 0 use zeros for padding. - * ^ upcase the result string. - * # change case. - * : use colons for %z. - * - * The minimum field width specifies the minimum width. - * - * The modifier is "E" and "O". - * They are ignored. - * - * Format directives: - * - * Date (Year, Month, Day): - * %Y - Year with century (can be negative, 4 digits at least) - * -0001, 0000, 1995, 2009, 14292, etc. - * %C - year / 100 (round down. 20 in 2009) - * %y - year % 100 (00..99) - * - * %m - Month of the year, zero-padded (01..12) - * %_m blank-padded ( 1..12) - * %-m no-padded (1..12) - * %B - The full month name (``January'') - * %^B uppercased (``JANUARY'') - * %b - The abbreviated month name (``Jan'') - * %^b uppercased (``JAN'') - * %h - Equivalent to %b - * - * %d - Day of the month, zero-padded (01..31) - * %-d no-padded (1..31) - * %e - Day of the month, blank-padded ( 1..31) - * - * %j - Day of the year (001..366) - * - * Time (Hour, Minute, Second, Subsecond): - * %H - Hour of the day, 24-hour clock, zero-padded (00..23) - * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23) - * %I - Hour of the day, 12-hour clock, zero-padded (01..12) - * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12) - * %P - Meridian indicator, lowercase (``am'' or ``pm'') - * %p - Meridian indicator, uppercase (``AM'' or ``PM'') - * - * %M - Minute of the hour (00..59) - * - * %S - Second of the minute (00..59) - * - * %L - Millisecond of the second (000..999) - * %N - Fractional seconds digits, default is 9 digits (nanosecond) - * %3N millisecond (3 digits) - * %6N microsecond (6 digits) - * %9N nanosecond (9 digits) - * %12N picosecond (12 digits) - * - * Time zone: - * %z - Time zone as hour and minute offset from UTC (e.g. +0900) - * %:z - hour and minute offset from UTC with a colon (e.g. +09:00) - * %::z - hour, minute and second offset from UTC (e.g. +09:00:00) - * %:::z - hour, minute and second offset from UTC - * (e.g. +09, +09:30, +09:30:30) - * %Z - Time zone abbreviation name - * - * Weekday: - * %A - The full weekday name (``Sunday'') - * %^A uppercased (``SUNDAY'') - * %a - The abbreviated name (``Sun'') - * %^a uppercased (``SUN'') - * %u - Day of the week (Monday is 1, 1..7) - * %w - Day of the week (Sunday is 0, 0..6) - * - * ISO 8601 week-based year and week number: - * The week 1 of YYYY starts with a Monday and includes YYYY-01-04. - * The days in the year before the first week are in the last week of - * the previous year. - * %G - The week-based year - * %g - The last 2 digits of the week-based year (00..99) - * %V - Week number of the week-based year (01..53) - * - * Week number: - * The week 1 of YYYY starts with a Sunday or Monday (according to %U - * or %W). The days in the year before the first week are in week 0. - * %U - Week number of the year. The week starts with Sunday. (00..53) - * %W - Week number of the year. The week starts with Monday. (00..53) - * - * Seconds since the Unix Epoch: - * %s - Number of seconds since 1970-01-01 00:00:00 UTC. - * %Q - Number of microseconds since 1970-01-01 00:00:00 UTC. - * - * Literal string: - * %n - Newline character (\n) - * %t - Tab character (\t) - * %% - Literal ``%'' character - * - * Combination: - * %c - date and time (%a %b %e %T %Y) - * %D - Date (%m/%d/%y) - * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) - * %x - Same as %D - * %X - Same as %T - * %r - 12-hour time (%I:%M:%S %p) - * %R - 24-hour time (%H:%M) - * %T - 24-hour time (%H:%M:%S) - * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y) - * - * This method is similar to strftime() function defined in ISO C and POSIX. - * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z) - * are locale dependent in the function. - * However this method is locale independent. - * So, the result may differ even if a same format string is used in other - * systems such as C. - * It is good practice to avoid %x and %X because there are corresponding - * locale independent representations, %D and %T. - * - * Examples: - * - * d = DateTime.new(2007,11,19,8,37,48,"-06:00") - * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...> - * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007" - * d.strftime("at %I:%M%p") #=> "at 08:37AM" - * - * Various ISO 8601 formats: - * %Y%m%d => 20071119 Calendar date (basic) - * %F => 2007-11-19 Calendar date (extended) - * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month - * %Y => 2007 Calendar date, reduced accuracy, specific year - * %C => 20 Calendar date, reduced accuracy, specific century - * %Y%j => 2007323 Ordinal date (basic) - * %Y-%j => 2007-323 Ordinal date (extended) - * %GW%V%u => 2007W471 Week date (basic) - * %G-W%V-%u => 2007-W47-1 Week date (extended) - * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic) - * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended) - * %H%M%S => 083748 Local time (basic) - * %T => 08:37:48 Local time (extended) - * %H%M => 0837 Local time, reduced accuracy, specific minute (basic) - * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended) - * %H => 08 Local time, reduced accuracy, specific hour - * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic) - * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended) - * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic) - * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended) - * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic) - * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended) - * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic) - * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended) - * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic) - * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended) - * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic) - * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended) - * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic) - * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended) - * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic) - * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended) - * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic) - * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended) - * - * See also strftime(3) and strptime. - */ -static VALUE -d_lite_strftime(int argc, VALUE *argv, VALUE self) -{ - return date_strftime_internal(argc, argv, self, - "%Y-%m-%d", set_tmx); -} - -static VALUE -strftimev(const char *fmt, VALUE self, - void (*func)(VALUE, struct tmx *)) -{ - char buffer[SMALLBUF], *buf = buffer; - struct tmx tmx; - long len; - VALUE str; - - (*func)(self, &tmx); - len = date_strftime_alloc(&buf, fmt, &tmx); - str = rb_usascii_str_new(buf, len); - if (buf != buffer) xfree(buf); - return str; -} - -/* - * call-seq: - * d.asctime -> string - * d.ctime -> string - * - * Returns a string in asctime(3) format (but without "\n\0" at the - * end). This method is equivalent to strftime('%c'). - * - * See also asctime(3) or ctime(3). - */ -static VALUE -d_lite_asctime(VALUE self) -{ - return strftimev("%a %b %e %H:%M:%S %Y", self, set_tmx); -} - -/* - * call-seq: - * d.iso8601 -> string - * d.xmlschema -> string - * - * This method is equivalent to strftime('%F'). - */ -static VALUE -d_lite_iso8601(VALUE self) -{ - return strftimev("%Y-%m-%d", self, set_tmx); -} - -/* - * call-seq: - * d.rfc3339 -> string - * - * This method is equivalent to strftime('%FT%T%:z'). - */ -static VALUE -d_lite_rfc3339(VALUE self) -{ - return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx); -} - -/* - * call-seq: - * d.rfc2822 -> string - * d.rfc822 -> string - * - * This method is equivalent to strftime('%a, %-d %b %Y %T %z'). - */ -static VALUE -d_lite_rfc2822(VALUE self) -{ - return strftimev("%a, %-d %b %Y %T %z", self, set_tmx); -} - -/* - * call-seq: - * d.httpdate -> string - * - * This method is equivalent to strftime('%a, %d %b %Y %T GMT'). - * See also RFC 2616. - */ -static VALUE -d_lite_httpdate(VALUE self) -{ - volatile VALUE dup = dup_obj_with_new_offset(self, 0); - return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx); -} - -static VALUE -jisx0301_date(VALUE jd, VALUE y) -{ - VALUE a[2]; - - if (f_lt_p(jd, INT2FIX(2405160))) - return rb_usascii_str_new2("%Y-%m-%d"); - if (f_lt_p(jd, INT2FIX(2419614))) { - a[0] = rb_usascii_str_new2("M%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1867)); - } - else if (f_lt_p(jd, INT2FIX(2424875))) { - a[0] = rb_usascii_str_new2("T%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1911)); - } - else if (f_lt_p(jd, INT2FIX(2447535))) { - a[0] = rb_usascii_str_new2("S%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1925)); - } - else { - a[0] = rb_usascii_str_new2("H%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1988)); - } - return rb_f_sprintf(2, a); -} - -/* - * call-seq: - * d.jisx0301 -> string - * - * Returns a string in a JIS X 0301 format. - * - * For example: - * - * Date.new(2001,2,3).jisx0301 #=> "H13.02.03" - */ -static VALUE -d_lite_jisx0301(VALUE self) -{ - VALUE s; - - get_d1(self); - s = jisx0301_date(m_real_local_jd(dat), - m_real_year(dat)); - return strftimev(RSTRING_PTR(s), self, set_tmx); -} - -#ifndef NDEBUG -static VALUE -d_lite_marshal_dump_old(VALUE self) -{ - VALUE a; - - get_d1(self); - - a = rb_ary_new3(3, - m_ajd(dat), - m_of_in_day(dat), - DBL2NUM(m_sg(dat))); - - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } - - return a; -} -#endif - -/* :nodoc: */ -static VALUE -d_lite_marshal_dump(VALUE self) -{ - VALUE a; - - get_d1(self); - - a = rb_ary_new3(6, - m_nth(dat), - INT2FIX(m_jd(dat)), - INT2FIX(m_df(dat)), - m_sf(dat), - INT2FIX(m_of(dat)), - DBL2NUM(m_sg(dat))); - - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } - - return a; -} - -/* :nodoc: */ -static VALUE -d_lite_marshal_load(VALUE self, VALUE a) -{ - get_d1(self); - - if (TYPE(a) != T_ARRAY) - rb_raise(rb_eTypeError, "expected an array"); - - switch (RARRAY_LEN(a)) { - case 3: - { - VALUE ajd, of, sg, nth, sf; - int jd, df, rof; - double rsg; - - ajd = RARRAY_PTR(a)[0]; - of = RARRAY_PTR(a)[1]; - sg = RARRAY_PTR(a)[2]; - - old_to_new(ajd, of, sg, - &nth, &jd, &df, &sf, &rof, &rsg); - - if (!df && f_zero_p(sf) && !rof) { - set_to_simple(&dat->s, nth, jd, rsg, 0, 0, 0, HAVE_JD); - } else { - if (!complex_dat_p(dat)) - rb_raise(rb_eArgError, - "cannot load complex into simple"); - - set_to_complex(&dat->c, nth, jd, df, sf, rof, rsg, - 0, 0, 0, 0, 0, 0, - HAVE_JD | HAVE_DF | COMPLEX_DAT); - } - } - break; - case 6: - { - VALUE nth, sf; - int jd, df, of; - double sg; - - nth = RARRAY_PTR(a)[0]; - jd = NUM2INT(RARRAY_PTR(a)[1]); - df = NUM2INT(RARRAY_PTR(a)[2]); - sf = RARRAY_PTR(a)[3]; - of = NUM2INT(RARRAY_PTR(a)[4]); - sg = NUM2DBL(RARRAY_PTR(a)[5]); - if (!df && f_zero_p(sf) && !of) { - set_to_simple(&dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD); - } else { - if (!complex_dat_p(dat)) - rb_raise(rb_eArgError, - "cannot load complex into simple"); - - set_to_complex(&dat->c, nth, jd, df, sf, of, sg, - 0, 0, 0, 0, 0, 0, - HAVE_JD | HAVE_DF | COMPLEX_DAT); - } - } - break; - default: - rb_raise(rb_eTypeError, "invalid size"); - break; - } - - if (FL_TEST(a, FL_EXIVAR)) { - rb_copy_generic_ivar(self, a); - FL_SET(self, FL_EXIVAR); - } - - return self; -} - - -/* datetime */ - -/* - * call-seq: - * DateTime.jd([jd=0[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]) -> datetime - * - * Creates a datetime object denoting the given chronological Julian - * day number. - * - * For example: - * - * DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> - * DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...> - * DateTime.jd(Rational('0.5')) - * #=> #<DateTime: -4712-01-01T12:00:00+00:00 ...> - */ -static VALUE -datetime_s_jd(int argc, VALUE *argv, VALUE klass) -{ - VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret; - int h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg); - - jd = INT2FIX(0); - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 6: - val2sg(vsg, sg); - case 5: - val2off(vof, rof); - case 4: - num2int_with_frac(s, positive_inf); - case 3: - num2int_with_frac(min, 3); - case 2: - num2int_with_frac(h, 2); - case 1: - num2num_with_frac(jd, 1); - } - - { - VALUE nth; - int rh, rmin, rs, rjd, rjd2; - - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - decode_jd(jd, &nth, &rjd); - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - 0, 0, 0, - rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * DateTime.ordinal([year=-4712[, yday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]) -> datetime - * - * Creates a date-time object denoting the given ordinal date. - * - * For example: - * - * DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> - * DateTime.ordinal(2001,34,4,5,6,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.ordinal(2001,-332,-20,-55,-54,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; - int d, h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg); - - y = INT2FIX(-4712); - d = 1; - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 7: - val2sg(vsg, sg); - case 6: - val2off(vof, rof); - case 5: - num2int_with_frac(s, positive_inf); - case 4: - num2int_with_frac(min, 4); - case 3: - num2int_with_frac(h, 3); - case 2: - num2int_with_frac(d, 2); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rd, rh, rmin, rs, rjd, rjd2, ns; - - if (!valid_ordinal_p(y, d, sg, - &nth, &ry, - &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - 0, 0, 0, - rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * DateTime.civil([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime - * DateTime.new([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime - * - * Creates a date-time object denoting the given calendar date. - * - * For example: - * - * DateTime.new(2001,2,3) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> - * DateTime.new(2001,2,3,4,5,6,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.new(2001,-11,-26,-20,-55,-54,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_civil(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; - int m, d, h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg); - - y = INT2FIX(-4712); - m = 1; - d = 1; - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 8: - val2sg(vsg, sg); - case 7: - val2off(vof, rof); - case 6: - num2int_with_frac(s, positive_inf); - case 5: - num2int_with_frac(min, 5); - case 4: - num2int_with_frac(h, 4); - case 3: - num2int_with_frac(d, 3); - case 2: - m = NUM2INT(vm); - case 1: - y = vy; - } - - if (guess_style(y, sg) < 0) { - VALUE nth; - int ry, rm, rd, rh, rmin, rs; - - if (!valid_gregorian_p(y, m, d, - &nth, &ry, - &rm, &rd)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - ret = d_complex_new_internal(klass, - nth, 0, - 0, INT2FIX(0), - rof, sg, - ry, rm, rd, - rh, rmin, rs, - HAVE_CIVIL | HAVE_TIME); - } - else { - VALUE nth; - int ry, rm, rd, rh, rmin, rs, rjd, rjd2, ns; - - if (!valid_civil_p(y, m, d, sg, - &nth, &ry, - &rm, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - ry, rm, rd, - rh, rmin, rs, - HAVE_JD | HAVE_CIVIL | HAVE_TIME); - } - add_frac(); - return ret; -} - -/* - * call-seq: - * DateTime.commercial([cwyear=-4712[, cweek=1[, cwday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime - * - * Creates a date-time object denoting the given week date. - * - * For example: - * - * DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...> - * DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...> - * DateTime.commercial(2001,5,6,4,5,6,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_commercial(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; - int w, d, h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg); - - y = INT2FIX(-4712); - w = 1; - d = 1; - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 8: - val2sg(vsg, sg); - case 7: - val2off(vof, rof); - case 6: - num2int_with_frac(s, positive_inf); - case 5: - num2int_with_frac(min, 5); - case 4: - num2int_with_frac(h, 4); - case 3: - num2int_with_frac(d, 3); - case 2: - w = NUM2INT(vw); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns; - - if (!valid_commercial_p(y, w, d, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - 0, 0, 0, - rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } - add_frac(); - return ret; -} - -#ifndef NDEBUG -static VALUE -datetime_s_weeknum(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; - int w, d, f, h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf, - &vh, &vmin, &vs, &vof, &vsg); - - y = INT2FIX(-4712); - w = 0; - d = 1; - f = 0; - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 9: - val2sg(vsg, sg); - case 8: - val2off(vof, rof); - case 7: - num2int_with_frac(s, positive_inf); - case 6: - num2int_with_frac(min, 6); - case 5: - num2int_with_frac(h, 5); - case 4: - f = NUM2INT(vf); - case 3: - num2int_with_frac(d, 4); - case 2: - w = NUM2INT(vw); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns; - - if (!valid_weeknum_p(y, w, d, f, sg, - &nth, &ry, - &rw, &rd, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - 0, 0, 0, - rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } - add_frac(); - return ret; -} - -static VALUE -datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass) -{ - VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; - int m, n, k, h, min, s, rof; - double sg; - - rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk, - &vh, &vmin, &vs, &vof, &vsg); - - y = INT2FIX(-4712); - m = 1; - n = 1; - k = 1; - - h = min = s = 0; - fr2 = INT2FIX(0); - rof = 0; - sg = DEFAULT_SG; - - switch (argc) { - case 9: - val2sg(vsg, sg); - case 8: - val2off(vof, rof); - case 7: - num2int_with_frac(s, positive_inf); - case 6: - num2int_with_frac(min, 6); - case 5: - num2int_with_frac(h, 5); - case 4: - num2int_with_frac(k, 4); - case 3: - n = NUM2INT(vn); - case 2: - m = NUM2INT(vm); - case 1: - y = vy; - } - - { - VALUE nth; - int ry, rm, rn, rk, rh, rmin, rs, rjd, rjd2, ns; - - if (!valid_nth_kday_p(y, m, n, k, sg, - &nth, &ry, - &rm, &rn, &rk, &rjd, - &ns)) - rb_raise(rb_eArgError, "invalid date"); - if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - canon24oc(); - - rjd2 = jd_local_to_utc(rjd, - time_to_df(rh, rmin, rs), - rof); - ret = d_complex_new_internal(klass, - nth, rjd2, - 0, INT2FIX(0), - rof, sg, - 0, 0, 0, - rh, rmin, rs, - HAVE_JD | HAVE_TIME); - } - add_frac(); - return ret; -} -#endif - -/* - * call-seq: - * DateTime.now([start=Date::ITALY]) -> datetime - * - * Creates a date-time object denoting the present time. - * - * For example: - * - * DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...> - */ -static VALUE -datetime_s_now(int argc, VALUE *argv, VALUE klass) -{ - VALUE vsg, nth, ret; - double sg; -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; -#else - struct timeval tv; -#endif - time_t sec; - struct tm tm; - long sf, of; - int y, ry, m, d, h, min, s; - - rb_scan_args(argc, argv, "01", &vsg); - - if (argc < 1) - sg = DEFAULT_SG; - else - sg = NUM2DBL(vsg); - -#ifdef HAVE_CLOCK_GETTIME - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) - rb_sys_fail("clock_gettime"); - sec = ts.tv_sec; -#else - if (gettimeofday(&tv, NULL) == -1) - rb_sys_fail("gettimeofday"); - sec = tv.tv_sec; -#endif - tzset(); - if (!localtime_r(&sec, &tm)) - rb_sys_fail("localtime"); - - y = tm.tm_year + 1900; - m = tm.tm_mon + 1; - d = tm.tm_mday; - h = tm.tm_hour; - min = tm.tm_min; - s = tm.tm_sec; - if (s == 60) - s = 59; -#ifdef HAVE_STRUCT_TM_TM_GMTOFF - of = tm.tm_gmtoff; -#elif defined(HAVE_VAR_TIMEZONE) -#ifdef HAVE_VAR_ALTZONE - of = (long)-((tm.tm_isdst > 0) ? altzone : timezone); -#else - of = (long)-timezone; - if (tm.tm_isdst) { - time_t sec2; - - tm.tm_isdst = 0; - sec2 = mktime(&tm); - of += (long)difftime(sec2, sec); - } -#endif -#elif defined(HAVE_TIMEGM) - { - time_t sec2; - - sec2 = timegm(&tm); - of = (long)difftime(sec2, sec); - } -#else - { - struct tm tm2; - time_t sec2; - - if (!gmtime_r(&sec, &tm2)) - rb_sys_fail("gmtime"); - tm2.tm_isdst = tm.tm_isdst; - sec2 = mktime(&tm2); - of = (long)difftime(sec, sec2); - } -#endif -#ifdef HAVE_CLOCK_GETTIME - sf = ts.tv_nsec; -#else - sf = tv.tv_usec * 1000; -#endif - - if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) { - of = 0; - rb_warning("invalid offset is ignored"); - } - - decode_year(INT2FIX(y), -1, &nth, &ry); - - ret = d_complex_new_internal(klass, - nth, 0, - 0, LONG2NUM(sf), - (int)of, GREGORIAN, - ry, m, d, - h, min, s, - HAVE_CIVIL | HAVE_TIME); - { - get_d1(ret); - set_sg(dat, sg); - } - return ret; -} - -static VALUE -dt_new_by_frags(VALUE klass, VALUE hash, VALUE sg) -{ - VALUE jd, sf, t; - int df, of; - - if (!c_valid_start_p(NUM2DBL(sg))) { - sg = INT2FIX(DEFAULT_SG); - rb_warning("invalid start is ignored"); - } - - if (NIL_P(hash)) - rb_raise(rb_eArgError, "invalid date"); - - if (NIL_P(ref_hash("jd")) && - NIL_P(ref_hash("yday")) && - !NIL_P(ref_hash("year")) && - !NIL_P(ref_hash("mon")) && - !NIL_P(ref_hash("mday"))) { - jd = rt__valid_civil_p(ref_hash("year"), - ref_hash("mon"), - ref_hash("mday"), sg); - - if (NIL_P(ref_hash("hour"))) - set_hash("hour", INT2FIX(0)); - if (NIL_P(ref_hash("min"))) - set_hash("min", INT2FIX(0)); - if (NIL_P(ref_hash("sec"))) - set_hash("sec", INT2FIX(0)); - else if (f_gt_p(ref_hash("sec"), INT2FIX(59))) - set_hash("sec", INT2FIX(59)); - } - else { - hash = rt_rewrite_frags(hash); - hash = rt_complete_frags(klass, hash); - jd = rt__valid_date_frags_p(hash, sg); - } - - if (NIL_P(jd)) - rb_raise(rb_eArgError, "invalid date"); - - { - int rh, rmin, rs; - - if (!c_valid_time_p(NUM2INT(ref_hash("hour")), - NUM2INT(ref_hash("min")), - NUM2INT(ref_hash("sec")), - &rh, &rmin, &rs)) - rb_raise(rb_eArgError, "invalid date"); - - df = time_to_df(rh, rmin, rs); - } - - t = ref_hash("sec_fraction"); - if (NIL_P(t)) - sf = INT2FIX(0); - else - sf = sec_to_ns(t); - - t = ref_hash("offset"); - if (NIL_P(t)) - of = 0; - else { - of = NUM2INT(t); - if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) { - of = 0; - rb_warning("invalid offset is ignored"); - } - } - { - VALUE nth; - int rjd, rjd2; - - decode_jd(jd, &nth, &rjd); - rjd2 = jd_local_to_utc(rjd, df, of); - df = df_local_to_utc(df, of); - - return d_complex_new_internal(klass, - nth, rjd2, - df, sf, - of, NUM2DBL(sg), - 0, 0, 0, - 0, 0, 0, - HAVE_JD | HAVE_DF); - } -} - -/* - * call-seq: - * DateTime._strptime(string[, format='%FT%T%z']) -> hash - * - * Parses the given representation of date and time with the given - * template, and returns a hash of parsed elements. - * - * See also strptime(3) and strftime. - */ -static VALUE -datetime_s__strptime(int argc, VALUE *argv, VALUE klass) -{ - return date_s__strptime_internal(argc, argv, klass, "%FT%T%z"); -} - -/* - * call-seq: - * DateTime.strptime([string='-4712-01-01T00:00:00+00:00'[, format='%FT%T%z'[ ,start=ITALY]]]) -> datetime - * - * Parses the given representation of date and time with the given - * template, and creates a date object. - * - * For example: - * - * DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p') - * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...> - * DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.strptime('-1', '%s') - * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...> - * DateTime.strptime('-1000', '%Q') - * #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...> - * DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z') - * #=> #<DateTime: 2001-02-03T16:00:00+07:00 ...> - * - * See also strptime(3) and strftime. - */ -static VALUE -datetime_s_strptime(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, fmt, sg; - - rb_scan_args(argc, argv, "03", &str, &fmt, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - fmt = rb_str_new2("%FT%T%z"); - case 2: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = fmt; - hash = date_s__strptime(2, argv2, klass); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=ITALY]]) -> datetime - * - * Parses the given representation of date and time, and creates a - * date object. - * - * If the optional second argument is true and the detected year is in - * the range "00" to "99", makes it full. - * - * For example: - * - * DateTime.parse('2001-02-03T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.parse('20010203T040506+0700') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.parse('3rd Feb 2001 04:05:06 PM') - * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...> - */ -static VALUE -datetime_s_parse(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, comp, sg; - - rb_scan_args(argc, argv, "03", &str, &comp, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - comp = Qtrue; - case 2: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some typical ISO 8601 formats. - * - * For example: - * - * DateTime.iso8601('2001-02-03T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.iso8601('20010203T040506+0700') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.iso8601('2001-W05-6T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__iso8601(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some typical RFC 3339 formats. - * - * For example: - * - * DateTime.rfc3339('2001-02-03T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__rfc3339(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some typical XML Schema formats. - * - * For example: - * - * DateTime.xmlschema('2001-02-03T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__xmlschema(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> datetime - * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some typical RFC 2822 formats. - * - * For example: - * - * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__rfc2822(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some RFC 2616 format. - * - * For example: - * - * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT') - * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...> - */ -static VALUE -datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__httpdate(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=ITALY]) -> datetime - * - * Creates a new Date object by parsing from a string according to - * some typical JIS X 0301 formats. - * - * For example: - * - * DateTime.jisx0301('H13.02.03T04:05:06+07:00') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - */ -static VALUE -datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) -{ - VALUE str, sg; - - rb_scan_args(argc, argv, "02", &str, &sg); - - switch (argc) { - case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); - case 1: - sg = INT2FIX(DEFAULT_SG); - } - - { - VALUE hash = date_s__jisx0301(klass, str); - return dt_new_by_frags(klass, hash, sg); - } -} - -/* - * call-seq: - * dt.to_s -> string - * - * Returns a string in an ISO 8601 format (This method doesn't use the - * expanded representations). - * - * For example: - * - * DateTime.new(2001,2,3,4,5,6,'-7').to_s - * #=> "2001-02-03T04:05:06-07:00" - */ -static VALUE -dt_lite_to_s(VALUE self) -{ - return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx); -} - -/* - * call-seq: - * dt.strftime([format='%FT%T%:z']) -> string - * - * Formats date according to the directives in the given format - * string. - * The directives begins with a percent (%) character. - * Any text not listed as a directive will be passed through to the - * output string. - * - * The directive consists of a percent (%) character, - * zero or more flags, optional minimum field width, - * optional modifier and a conversion specifier - * as follows. - * - * %<flags><width><modifier><conversion> - * - * Flags: - * - don't pad a numerical output. - * _ use spaces for padding. - * 0 use zeros for padding. - * ^ upcase the result string. - * # change case. - * : use colons for %z. - * - * The minimum field width specifies the minimum width. - * - * The modifier is "E" and "O". - * They are ignored. - * - * Format directives: - * - * Date (Year, Month, Day): - * %Y - Year with century (can be negative, 4 digits at least) - * -0001, 0000, 1995, 2009, 14292, etc. - * %C - year / 100 (round down. 20 in 2009) - * %y - year % 100 (00..99) - * - * %m - Month of the year, zero-padded (01..12) - * %_m blank-padded ( 1..12) - * %-m no-padded (1..12) - * %B - The full month name (``January'') - * %^B uppercased (``JANUARY'') - * %b - The abbreviated month name (``Jan'') - * %^b uppercased (``JAN'') - * %h - Equivalent to %b - * - * %d - Day of the month, zero-padded (01..31) - * %-d no-padded (1..31) - * %e - Day of the month, blank-padded ( 1..31) - * - * %j - Day of the year (001..366) - * - * Time (Hour, Minute, Second, Subsecond): - * %H - Hour of the day, 24-hour clock, zero-padded (00..23) - * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23) - * %I - Hour of the day, 12-hour clock, zero-padded (01..12) - * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12) - * %P - Meridian indicator, lowercase (``am'' or ``pm'') - * %p - Meridian indicator, uppercase (``AM'' or ``PM'') - * - * %M - Minute of the hour (00..59) - * - * %S - Second of the minute (00..59) - * - * %L - Millisecond of the second (000..999) - * %N - Fractional seconds digits, default is 9 digits (nanosecond) - * %3N millisecond (3 digits) - * %6N microsecond (6 digits) - * %9N nanosecond (9 digits) - * %12N picosecond (12 digits) - * - * Time zone: - * %z - Time zone as hour and minute offset from UTC (e.g. +0900) - * %:z - hour and minute offset from UTC with a colon (e.g. +09:00) - * %::z - hour, minute and second offset from UTC (e.g. +09:00:00) - * %:::z - hour, minute and second offset from UTC - * (e.g. +09, +09:30, +09:30:30) - * %Z - Time zone abbreviation name - * - * Weekday: - * %A - The full weekday name (``Sunday'') - * %^A uppercased (``SUNDAY'') - * %a - The abbreviated name (``Sun'') - * %^a uppercased (``SUN'') - * %u - Day of the week (Monday is 1, 1..7) - * %w - Day of the week (Sunday is 0, 0..6) - * - * ISO 8601 week-based year and week number: - * The week 1 of YYYY starts with a Monday and includes YYYY-01-04. - * The days in the year before the first week are in the last week of - * the previous year. - * %G - The week-based year - * %g - The last 2 digits of the week-based year (00..99) - * %V - Week number of the week-based year (01..53) - * - * Week number: - * The week 1 of YYYY starts with a Sunday or Monday (according to %U - * or %W). The days in the year before the first week are in week 0. - * %U - Week number of the year. The week starts with Sunday. (00..53) - * %W - Week number of the year. The week starts with Monday. (00..53) - * - * Seconds since the Unix Epoch: - * %s - Number of seconds since 1970-01-01 00:00:00 UTC. - * %Q - Number of microseconds since 1970-01-01 00:00:00 UTC. - * - * Literal string: - * %n - Newline character (\n) - * %t - Tab character (\t) - * %% - Literal ``%'' character - * - * Combination: - * %c - date and time (%a %b %e %T %Y) - * %D - Date (%m/%d/%y) - * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) - * %x - Same as %D - * %X - Same as %T - * %r - 12-hour time (%I:%M:%S %p) - * %R - 24-hour time (%H:%M) - * %T - 24-hour time (%H:%M:%S) - * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y) - * - * This method is similar to strftime() function defined in ISO C and POSIX. - * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z) - * are locale dependent in the function. - * However this method is locale independent. - * So, the result may differ even if a same format string is used in other - * systems such as C. - * It is good practice to avoid %x and %X because there are corresponding - * locale independent representations, %D and %T. - * - * Examples: - * - * d = DateTime.new(2007,11,19,8,37,48,"-06:00") - * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...> - * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007" - * d.strftime("at %I:%M%p") #=> "at 08:37AM" - * - * Various ISO 8601 formats: - * %Y%m%d => 20071119 Calendar date (basic) - * %F => 2007-11-19 Calendar date (extended) - * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month - * %Y => 2007 Calendar date, reduced accuracy, specific year - * %C => 20 Calendar date, reduced accuracy, specific century - * %Y%j => 2007323 Ordinal date (basic) - * %Y-%j => 2007-323 Ordinal date (extended) - * %GW%V%u => 2007W471 Week date (basic) - * %G-W%V-%u => 2007-W47-1 Week date (extended) - * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic) - * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended) - * %H%M%S => 083748 Local time (basic) - * %T => 08:37:48 Local time (extended) - * %H%M => 0837 Local time, reduced accuracy, specific minute (basic) - * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended) - * %H => 08 Local time, reduced accuracy, specific hour - * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic) - * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended) - * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic) - * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended) - * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic) - * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended) - * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic) - * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended) - * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic) - * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended) - * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic) - * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended) - * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic) - * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended) - * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic) - * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended) - * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic) - * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended) - * - * See also strftime(3) and strptime. - */ -static VALUE -dt_lite_strftime(int argc, VALUE *argv, VALUE self) -{ - return date_strftime_internal(argc, argv, self, - "%Y-%m-%dT%H:%M:%S%:z", set_tmx); -} - -static VALUE -iso8601_timediv(VALUE self, VALUE n) -{ - VALUE fmt; - - fmt = rb_usascii_str_new2("T%H:%M:%S"); - if (f_gt_p(n, INT2FIX(0))) { - VALUE argv[3]; - - get_d1(self); - - argv[0] = rb_usascii_str_new2(".%0*d"); - argv[1] = n; - argv[2] = f_round(f_quo(m_sf_in_sec(dat), - f_quo(INT2FIX(1), - f_expt(INT2FIX(10), n)))); - rb_str_append(fmt, rb_f_sprintf(3, argv)); - } - rb_str_append(fmt, rb_usascii_str_new2("%:z")); - return strftimev(RSTRING_PTR(fmt), self, set_tmx); -} - -/* - * call-seq: - * dt.iso8601([n=0]) -> string - * dt.xmlschema([n=0]) -> string - * - * This method is equivalent to strftime('%FT%T'). The optional - * argument n is length of fractional seconds. - * - * For example: - * - * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9) - * #=> "2001-02-03T04:05:06.123456789+07:00" - */ -static VALUE -dt_lite_iso8601(int argc, VALUE *argv, VALUE self) -{ - VALUE n; - - rb_scan_args(argc, argv, "01", &n); - - if (argc < 1) - n = INT2FIX(0); - - return f_add(strftimev("%Y-%m-%d", self, set_tmx), - iso8601_timediv(self, n)); -} - -/* - * call-seq: - * dt.rfc3339([n=0]) -> string - * - * This method is equivalent to strftime('%FT%T'). The optional - * argument n is length of fractional seconds. - * - * For example: - * - * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9) - * #=> "2001-02-03T04:05:06.123456789+07:00" - */ -static VALUE -dt_lite_rfc3339(int argc, VALUE *argv, VALUE self) -{ - return dt_lite_iso8601(argc, argv, self); -} - -/* - * call-seq: - * dt.jisx0301([n=0]) -> string - * - * Returns a string in a JIS X 0301 format. The optional argument n - * is length of fractional seconds. - * - * For example: - * - * DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9) - * #=> "H13.02.03T04:05:06.123456789+07:00" - */ -static VALUE -dt_lite_jisx0301(int argc, VALUE *argv, VALUE self) -{ - VALUE n, s; - - rb_scan_args(argc, argv, "01", &n); - - if (argc < 1) - n = INT2FIX(0); - - { - get_d1(self); - s = jisx0301_date(m_real_local_jd(dat), - m_real_year(dat)); - return rb_str_append(strftimev(RSTRING_PTR(s), self, set_tmx), - iso8601_timediv(self, n)); - } -} - -/* conversions */ - -#define f_getlocal(x) rb_funcall(x, rb_intern("getlocal"), 0) -#define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0) -#define f_utc_offset(x) rb_funcall(x, rb_intern("utc_offset"), 0) -#define f_local3(x,y,m,d) rb_funcall(x, rb_intern("local"), 3, y, m, d) -#define f_utc6(x,y,m,d,h,min,s) rb_funcall(x, rb_intern("utc"), 6,\ - y, m, d, h, min, s) - -/* - * call-seq: - * t.to_time -> time - * - * Returns a copy of self as local mode. - */ -static VALUE -time_to_time(VALUE self) -{ - return rb_funcall(self, rb_intern("getlocal"), 0); -} - -/* - * call-seq: - * t.to_date -> date - * - * Returns a Date object which denotes self. - */ -static VALUE -time_to_date(VALUE self) -{ - VALUE y, nth, ret; - int ry, m, d; - - y = f_year(self); - m = FIX2INT(f_mon(self)); - d = FIX2INT(f_mday(self)); - - decode_year(y, -1, &nth, &ry); - - ret = d_simple_new_internal(cDate, - nth, 0, - GREGORIAN, - ry, m, d, - HAVE_CIVIL); - { - get_d1(ret); - set_sg(dat, DEFAULT_SG); - } - return ret; -} - -/* - * call-seq: - * t.to_datetime -> datetime - * - * Returns a DateTime object which denotes self. - */ -static VALUE -time_to_datetime(VALUE self) -{ - VALUE y, sf, nth, ret; - int ry, m, d, h, min, s, of; - - y = f_year(self); - m = FIX2INT(f_mon(self)); - d = FIX2INT(f_mday(self)); - - h = FIX2INT(f_hour(self)); - min = FIX2INT(f_min(self)); - s = FIX2INT(f_sec(self)); - if (s == 60) - s = 59; - - sf = sec_to_ns(f_subsec(self)); - of = FIX2INT(f_utc_offset(self)); - - decode_year(y, -1, &nth, &ry); - - ret = d_complex_new_internal(cDateTime, - nth, 0, - 0, sf, - of, DEFAULT_SG, - ry, m, d, - h, min, s, - HAVE_CIVIL | HAVE_TIME); - { - get_d1(ret); - set_sg(dat, DEFAULT_SG); - } - return ret; -} - -/* - * call-seq: - * d.to_time -> time - * - * Returns a Time object which denotes self. - */ -static VALUE -date_to_time(VALUE self) -{ - get_d1(self); - - return f_local3(rb_cTime, - m_real_year(dat), - INT2FIX(m_mon(dat)), - INT2FIX(m_mday(dat))); -} - -/* - * call-seq: - * d.to_date -> self - * - * Returns self; - */ -static VALUE -date_to_date(VALUE self) -{ - return self; -} - -/* - * call-seq: - * d.to_datetime -> datetime - * - * Returns a DateTime object which denotes self. - */ -static VALUE -date_to_datetime(VALUE self) -{ - get_d1a(self); - - if (simple_dat_p(adat)) { - VALUE new = d_lite_s_alloc_simple(cDateTime); - { - get_d1b(new); - bdat->s = adat->s; - return new; - } - } - else { - VALUE new = d_lite_s_alloc_complex(cDateTime); - { - get_d1b(new); - bdat->c = adat->c; - bdat->c.df = 0; - bdat->c.sf = INT2FIX(0); -#ifndef USE_PACK - bdat->c.hour = 0; - bdat->c.min = 0; - bdat->c.sec = 0; -#else - bdat->c.pc = PACK5(EX_MON(adat->c.pc), EX_MDAY(adat->c.pc), - 0, 0, 0); - bdat->c.flags |= HAVE_DF | HAVE_TIME; -#endif - return new; - } - } -} - -/* - * call-seq: - * dt.to_time -> time - * - * Returns a Time object which denotes self. - */ -static VALUE -datetime_to_time(VALUE self) -{ - volatile VALUE dup = dup_obj_with_new_offset(self, 0); - { - VALUE t; - - get_d1(dup); - - t = f_utc6(rb_cTime, - m_real_year(dat), - INT2FIX(m_mon(dat)), - INT2FIX(m_mday(dat)), - INT2FIX(m_hour(dat)), - INT2FIX(m_min(dat)), - f_add(INT2FIX(m_sec(dat)), - m_sf_in_sec(dat))); - return f_getlocal(t); - } -} - -/* - * call-seq: - * dt.to_date -> date - * - * Returns a Date object which denotes self. - */ -static VALUE -datetime_to_date(VALUE self) -{ - get_d1a(self); - - if (simple_dat_p(adat)) { - VALUE new = d_lite_s_alloc_simple(cDate); - { - get_d1b(new); - bdat->s = adat->s; - bdat->s.jd = m_local_jd(adat); - return new; - } - } - else { - VALUE new = d_lite_s_alloc_simple(cDate); - { - get_d1b(new); - copy_complex_to_simple(&bdat->s, &adat->c) - bdat->s.jd = m_local_jd(adat); - bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT); - return new; - } - } -} - -/* - * call-seq: - * dt.to_datetime -> self - * - * Returns self. - */ -static VALUE -datetime_to_datetime(VALUE self) -{ - return self; -} - -#ifndef NDEBUG -/* tests */ - -#define MIN_YEAR -4713 -#define MAX_YEAR 1000000 -#define MIN_JD -327 -#define MAX_JD 366963925 - -static int -test_civil(int from, int to, double sg) -{ - int j; - - fprintf(stderr, "test_civil: %d...%d (%d) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - int y, m, d, rj, ns; - - c_jd_to_civil(j, sg, &y, &m, &d); - c_civil_to_jd(y, m, d, sg, &rj, &ns); - if (j != rj) { - fprintf(stderr, "%d != %d\n", j, rj); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_civil(VALUE klass) -{ - if (!test_civil(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_civil(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_civil(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_civil(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_civil(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_civil(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - -static int -test_ordinal(int from, int to, double sg) -{ - int j; - - fprintf(stderr, "test_ordinal: %d...%d (%d) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - int y, d, rj, ns; - - c_jd_to_ordinal(j, sg, &y, &d); - c_ordinal_to_jd(y, d, sg, &rj, &ns); - if (j != rj) { - fprintf(stderr, "%d != %d\n", j, rj); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_ordinal(VALUE klass) -{ - if (!test_ordinal(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_ordinal(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_ordinal(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_ordinal(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_ordinal(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_ordinal(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - -static int -test_commercial(int from, int to, double sg) -{ - int j; - - fprintf(stderr, "test_commercial: %d...%d (%d) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - int y, w, d, rj, ns; - - c_jd_to_commercial(j, sg, &y, &w, &d); - c_commercial_to_jd(y, w, d, sg, &rj, &ns); - if (j != rj) { - fprintf(stderr, "%d != %d\n", j, rj); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_commercial(VALUE klass) -{ - if (!test_commercial(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_commercial(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_commercial(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_commercial(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_commercial(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_commercial(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - -static int -test_weeknum(int from, int to, int f, double sg) -{ - int j; - - fprintf(stderr, "test_weeknum: %d...%d (%d) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - int y, w, d, rj, ns; - - c_jd_to_weeknum(j, f, sg, &y, &w, &d); - c_weeknum_to_jd(y, w, d, f, sg, &rj, &ns); - if (j != rj) { - fprintf(stderr, "%d != %d\n", j, rj); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_weeknum(VALUE klass) -{ - int f; - - for (f = 0; f <= 1; f++) { - if (!test_weeknum(MIN_JD, MIN_JD + 366, f, GREGORIAN)) - return Qfalse; - if (!test_weeknum(2305814, 2598007, f, GREGORIAN)) - return Qfalse; - if (!test_weeknum(MAX_JD - 366, MAX_JD, f, GREGORIAN)) - return Qfalse; - - if (!test_weeknum(MIN_JD, MIN_JD + 366, f, ITALY)) - return Qfalse; - if (!test_weeknum(2305814, 2598007, f, ITALY)) - return Qfalse; - if (!test_weeknum(MAX_JD - 366, MAX_JD, f, ITALY)) - return Qfalse; - } - - return Qtrue; -} - -static int -test_nth_kday(int from, int to, double sg) -{ - int j; - - fprintf(stderr, "test_nth_kday: %d...%d (%d) - %.0f\n", - from, to, to - from, sg); - for (j = from; j <= to; j++) { - int y, m, n, k, rj, ns; - - c_jd_to_nth_kday(j, sg, &y, &m, &n, &k); - c_nth_kday_to_jd(y, m, n, k, sg, &rj, &ns); - if (j != rj) { - fprintf(stderr, "%d != %d\n", j, rj); - return 0; - } - } - return 1; -} - -static VALUE -date_s_test_nth_kday(VALUE klass) -{ - if (!test_nth_kday(MIN_JD, MIN_JD + 366, GREGORIAN)) - return Qfalse; - if (!test_nth_kday(2305814, 2598007, GREGORIAN)) - return Qfalse; - if (!test_nth_kday(MAX_JD - 366, MAX_JD, GREGORIAN)) - return Qfalse; - - if (!test_nth_kday(MIN_JD, MIN_JD + 366, ITALY)) - return Qfalse; - if (!test_nth_kday(2305814, 2598007, ITALY)) - return Qfalse; - if (!test_nth_kday(MAX_JD - 366, MAX_JD, ITALY)) - return Qfalse; - - return Qtrue; -} - -static int -test_unit_v2v(VALUE i, - VALUE (* conv1)(VALUE), - VALUE (* conv2)(VALUE)) -{ - VALUE c, o; - c = (*conv1)(i); - o = (*conv2)(c); - return f_eqeq_p(o, i); -} - -static int -test_unit_v2v_iter2(VALUE (* conv1)(VALUE), - VALUE (* conv2)(VALUE)) -{ - if (!test_unit_v2v(INT2FIX(0), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(1), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(2), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(3), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(11), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(65535), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2FIX(1073741823), conv1, conv2)) - return 0; - if (!test_unit_v2v(INT2NUM(1073741824), conv1, conv2)) - return 0; - if (!test_unit_v2v(rb_rational_new2(INT2FIX(0), INT2FIX(1)), conv1, conv2)) - return 0; - if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(1)), conv1, conv2)) - return 0; - if (!test_unit_v2v(rb_rational_new2(INT2FIX(1), INT2FIX(2)), conv1, conv2)) - return 0; - if (!test_unit_v2v(rb_rational_new2(INT2FIX(2), INT2FIX(3)), conv1, conv2)) - return 0; - return 1; -} - -static int -test_unit_v2v_iter(VALUE (* conv1)(VALUE), - VALUE (* conv2)(VALUE)) -{ - if (!test_unit_v2v_iter2(conv1, conv2)) - return 0; - if (!test_unit_v2v_iter2(conv2, conv1)) - return 0; - return 1; -} - -static VALUE -date_s_test_unit_conv(VALUE klass) -{ - if (!test_unit_v2v_iter(sec_to_day, day_to_sec)) - return Qfalse; - if (!test_unit_v2v_iter(ms_to_sec, sec_to_ms)) - return Qfalse; - if (!test_unit_v2v_iter(ns_to_day, day_to_ns)) - return Qfalse; - if (!test_unit_v2v_iter(ns_to_sec, sec_to_ns)) - return Qfalse; - return Qtrue; -} - -static VALUE -date_s_test_all(VALUE klass) -{ - if (date_s_test_civil(klass) == Qfalse) - return Qfalse; - if (date_s_test_ordinal(klass) == Qfalse) - return Qfalse; - if (date_s_test_commercial(klass) == Qfalse) - return Qfalse; - if (date_s_test_weeknum(klass) == Qfalse) - return Qfalse; - if (date_s_test_nth_kday(klass) == Qfalse) - return Qfalse; - if (date_s_test_unit_conv(klass) == Qfalse) - return Qfalse; - return Qtrue; -} -#endif - -static const char *monthnames[] = { - NULL, - "January", "February", "March", - "April", "May", "June", - "July", "August", "September", - "October", "November", "December" -}; - -static const char *abbr_monthnames[] = { - NULL, - "Jan", "Feb", "Mar", "Apr", - "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" -}; - -static const char *daynames[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday" -}; - -static const char *abbr_daynames[] = { - "Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat" -}; - -static VALUE -mk_ary_of_str(long len, const char *a[]) -{ - VALUE o; - long i; - - o = rb_ary_new2(len); - for (i = 0; i < len; i++) { - VALUE e; - - if (!a[i]) - e = Qnil; - else { - e = rb_usascii_str_new2(a[i]); - rb_obj_freeze(e); - } - rb_ary_push(o, e); - } - rb_obj_freeze(o); - return o; -} - -void -Init_date_core(void) -{ -#undef rb_intern -#define rb_intern(str) rb_intern_const(str) - - assert(fprintf(stderr, "assert() is now active\n")); - - id_cmp = rb_intern("<=>"); - id_le_p = rb_intern("<="); - id_ge_p = rb_intern(">="); - id_eqeq_p = rb_intern("=="); - - half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2)); - -#if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS - day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS * - SECOND_IN_NANOSECONDS); -#elif defined HAVE_LONG_LONG - day_in_nanoseconds = LL2NUM((LONG_LONG)DAY_IN_SECONDS * - SECOND_IN_NANOSECONDS); -#else - day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS), - INT2FIX(SECOND_IN_NANOSECONDS)); -#endif - - rb_gc_register_mark_object(half_days_in_day); - rb_gc_register_mark_object(day_in_nanoseconds); - - positive_inf = +INFINITY; - negative_inf = -INFINITY; - - /* - * date and datetime class - Tadayoshi Funaba 1998-2011 - * - * 'date' provides two classes Date and DateTime. - * - * == Terms and definitions - * - * Some terms and definitions are based on ISO 8601 and JIS X 0301. - * - * === calendar date - * - * The calendar date is a particular day of a calendar year, - * identified by its ordinal number within a calendar month within - * that year. - * - * In those classes, this is so-called "civil". - * - * === ordinal date - * - * The ordinal date is a particular day of a calendar year identified - * by its ordinal number within the year. - * - * In those classes, this is so-called "ordinal". - * - * === week date - * - * The week date is a date identified by calendar week and day numbers. - * - * The calendar week is a seven day period within a calendar year, - * starting on a Monday and identified by its ordinal number within - * the year; the first calendar week of the year is the one that - * includes the first Thursday of that year. In the Gregorian - * calendar, this is equivalent to the week which includes January 4. - * - * In those classes, this so-called "commercial". - * - * === julian day number - * - * The Julian day number is in elapsed days since noon (Greenwich mean - * time) on January 1, 4713 BCE (in the Julian calendar). - * - * In this document, the astronomical Julian day number is same as the - * original Julian day number. And the chronological Julian day - * number is a variation of the Julian day number. Its days begin at - * midnight on local time. - * - * In this document, when the term "Julian day number" simply appears, - * it just refers to "chronological Julian day number", not the - * original. - * - * In those classes, those are so-called "ajd" and "jd". - * - * === modified julian day number - * - * The modified Julian day number is in elapsed days since midnight - * (Coordinated universal time) on November 17, 1858 CE (in the - * Gregorian calendar). - * - * In this document, the astronomical modified Julian day number is - * same as the original modified Julian day number. And the - * chronological modified Julian day number is a variation of the - * modified Julian day number. Its days begin at midnight on local - * time. - * - * In this document, when the term "modified Julian day number" simply - * appears, it just refers to "chronological modified Julian day - * number", not the original. - * - * In those classes, this is so-called "mjd". - * - * - * == Date - * - * A subclass of Object includes Comparable module, easily handles - * date. - * - * Date object is created with Date::new, Date::jd, Date::ordinal, - * Date::commercial, Date::parse, Date::strptime, Date::today, - * Time#to_date or etc. - * - * require 'date' - * - * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...> - * Date.jd(2451944) #=> #<Date: 2001-02-03 ...> - * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...> - * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...> - * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...> - * Date.strptime('03-02-2001', '%d-%m-%Y') - * #=> #<Date: 2001-02-03 ...> - * Time.new(2001,2,3).to_date #=> #<Date: 2001-02-03 ...> - * - * All date objects are immutable; hence cannot modify themselves. - * - * The concept of this date object can be represented as a tuple - * of the day count, the offset and the day of calendar reform. - * - * The day count denotes the absolute position of a temporal - * dimension. The offset is relative adjustment, which determines - * decoded local time with the day count. The day of calendar - * reform denotes the start day of the new style. The old style - * of the West is the Julian calendar which was adopted by - * Caersar. The new style is the Gregorian calendar, which is the - * current civil calendar of many countries. - * - * The day count is virtually the astronomical Julian day number. - * The offset in this class is usually zero, and cannot be - * specified directly. - * - * An optional argument the day of calendar reform (start) as a - * Julian day number, which should be 2298874 to 2426355 or -/+oo. - * The default value is Date::ITALY (2299161=1582-10-15). See - * also sample/cal.rb. - * - * $ ruby sample/cal.rb -c it 10 1582 - * October 1582 - * S M Tu W Th F S - * 1 2 3 4 15 16 - * 17 18 19 20 21 22 23 - * 24 25 26 27 28 29 30 - * 31 - * - * $ ruby sample/cal.rb -c gb 9 1752 - * September 1752 - * S M Tu W Th F S - * 1 2 14 15 16 - * 17 18 19 20 21 22 23 - * 24 25 26 27 28 29 30 - * - * Date object has various methods. See each reference. - * - * d = Date.parse('3rd Feb 2001') - * #=> #<Date: 2001-02-03 ...> - * d.year #=> 2001 - * d.mon #=> 2 - * d.mday #=> 3 - * d.wday #=> 6 - * d += 1 #=> #<Date: 2001-02-04 ...> - * d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001" - * - * - * == DateTime - * - * A subclass of Date easily handles date, hour, minute, second and - * offset. - * - * DateTime does not consider any leapseconds, does not track - * any summer time rules. - * - * DateTime object is created with DateTime::new, DateTime::jd, - * DateTime::ordinal, DateTime::commercial, DateTime::parse, - * DateTime::strptime, DateTime::now, Time#to_datetime or etc. - * - * require 'date' - * - * DateTime.new(2001,2,3,4,5,6) - * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...> - * - * The last element of day, hour, minute or senond can be - * fractional number. The fractional number's precision is assumed - * at most nanosecond. - * - * DateTime.new(2001,2,3.5) - * #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...> - * - * An optional argument the offset indicates the difference - * between the local time and UTC. For example, Rational(3,24) - * represents ahead of 3 hours of UTC, Rational(-5,24) represents - * behind of 5 hours of UTC. The offset should be -1 to +1, and - * its precision is assumed at most second. The default value is - * zero (equals to UTC). - * - * DateTime.new(2001,2,3,4,5,6,Rational(3,24)) - * #=> #<DateTime: 2001-02-03T03:04:05+03:00 ...> - * also accepts string form. - * - * DateTime.new(2001,2,3,4,5,6,'+03:00') - * #=> #<DateTime: 2001-02-03T03:04:05+03:00 ...> - * - * An optional argument the day of calendar reform (start) denotes - * a Julian day number, which should be 2298874 to 2426355 or - * -/+oo. The default value is Date::ITALY (2299161=1582-10-15). - * - * DateTime object has various methods. See each reference. - * - * d = DateTime.parse('3rd Feb 2001 04:05:06+03:30') - * #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...> - * d.hour #=> 4 - * d.min #=> 5 - * d.sec #=> 6 - * d.offset #=> (7/48) - * d.zone #=> "+03:30" - * d += Rational('1.5') - * #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...> - * d = d.new_offset('+09:00') - * #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...> - * d.strftime('%I:%M:%S %p') - * #=> "09:35:06 PM" - * d > DateTime.new(1999) - * #=> true - */ - cDate = rb_define_class("Date", rb_cObject); - - rb_include_module(cDate, rb_mComparable); - - /* An array of stirng of full month name in English. The first - * element is nil. - */ - rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames)); - - /* An array of string of abbreviated month name in English. The - * first element is nil. - */ - rb_define_const(cDate, "ABBR_MONTHNAMES", - mk_ary_of_str(13, abbr_monthnames)); - - /* An array of string of full name of days of the week in English. - * The first is "Sunday". - */ - rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames)); - - /* An array of string of abbreviated day name in English. The - * first is "Sun". - */ - rb_define_const(cDate, "ABBR_DAYNAMES", mk_ary_of_str(7, abbr_daynames)); - - /* The Julian day number of the day of calendar reform for Italy - * and some catholic countries. - */ - rb_define_const(cDate, "ITALY", INT2FIX(ITALY)); - - /* The Julian day number of the day of calendar reform for England - * and her colonies. - */ - rb_define_const(cDate, "ENGLAND", INT2FIX(ENGLAND)); - - /* The Julian day number of the day of calendar reform for the - * proleptic Julian calendar - */ - rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN)); - - /* The Julian day number of the day of calendar reform for the - * proleptic Gregorian calendar - */ - rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN)); - - rb_define_alloc_func(cDate, d_lite_s_alloc); - -#ifndef NDEBUG -#define de_define_private_method rb_define_private_method - de_define_private_method(CLASS_OF(cDate), "_valid_jd?", - date_s__valid_jd_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_ordinal?", - date_s__valid_ordinal_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_civil?", - date_s__valid_civil_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_date?", - date_s__valid_civil_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_commercial?", - date_s__valid_commercial_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_weeknum?", - date_s__valid_weeknum_p, -1); - de_define_private_method(CLASS_OF(cDate), "_valid_nth_kday?", - date_s__valid_nth_kday_p, -1); -#endif - - rb_define_singleton_method(cDate, "valid_jd?", date_s_valid_jd_p, -1); - rb_define_singleton_method(cDate, "valid_ordinal?", - date_s_valid_ordinal_p, -1); - rb_define_singleton_method(cDate, "valid_civil?", date_s_valid_civil_p, -1); - rb_define_singleton_method(cDate, "valid_date?", date_s_valid_civil_p, -1); - rb_define_singleton_method(cDate, "valid_commercial?", - date_s_valid_commercial_p, -1); - -#ifndef NDEBUG - de_define_private_method(CLASS_OF(cDate), "valid_weeknum?", - date_s_valid_weeknum_p, -1); - de_define_private_method(CLASS_OF(cDate), "valid_nth_kday?", - date_s_valid_nth_kday_p, -1); - de_define_private_method(CLASS_OF(cDate), "zone_to_diff", - date_s_zone_to_diff, 1); -#endif - - rb_define_singleton_method(cDate, "julian_leap?", date_s_julian_leap_p, 1); - rb_define_singleton_method(cDate, "gregorian_leap?", - date_s_gregorian_leap_p, 1); - rb_define_singleton_method(cDate, "leap?", - date_s_gregorian_leap_p, 1); - -#ifndef NDEBUG -#define de_define_singleton_method rb_define_singleton_method -#define de_define_alias rb_define_alias - de_define_singleton_method(cDate, "new!", date_s_new_bang, -1); - de_define_alias(rb_singleton_class(cDate), "new_l!", "new"); -#endif - - rb_define_singleton_method(cDate, "jd", date_s_jd, -1); - rb_define_singleton_method(cDate, "ordinal", date_s_ordinal, -1); - rb_define_singleton_method(cDate, "civil", date_s_civil, -1); - rb_define_singleton_method(cDate, "new", date_s_civil, -1); - rb_define_singleton_method(cDate, "commercial", date_s_commercial, -1); - -#ifndef NDEBUG - de_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1); - de_define_singleton_method(cDate, "nth_kday", date_s_nth_kday, -1); -#endif - - rb_define_singleton_method(cDate, "today", date_s_today, -1); - rb_define_singleton_method(cDate, "_strptime", date_s__strptime, -1); - rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1); - rb_define_singleton_method(cDate, "_parse", date_s__parse, -1); - rb_define_singleton_method(cDate, "parse", date_s_parse, -1); - rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1); - rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1); - rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1); - rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1); - rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1); - rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1); - rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1); - rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1); - rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1); - rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1); - rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1); - rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1); - rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1); - rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1); - -#ifndef NDEBUG -#define de_define_method rb_define_method - de_define_method(cDate, "initialize", d_lite_initialize, -1); -#endif - rb_define_method(cDate, "initialize_copy", d_lite_initialize_copy, 1); - -#ifndef NDEBUG - de_define_method(cDate, "fill", d_lite_fill, 0); -#endif - - rb_define_method(cDate, "ajd", d_lite_ajd, 0); - rb_define_method(cDate, "amjd", d_lite_amjd, 0); - rb_define_method(cDate, "jd", d_lite_jd, 0); - rb_define_method(cDate, "mjd", d_lite_mjd, 0); - rb_define_method(cDate, "ld", d_lite_ld, 0); - - rb_define_method(cDate, "year", d_lite_year, 0); - rb_define_method(cDate, "yday", d_lite_yday, 0); - rb_define_method(cDate, "mon", d_lite_mon, 0); - rb_define_method(cDate, "month", d_lite_mon, 0); - rb_define_method(cDate, "mday", d_lite_mday, 0); - rb_define_method(cDate, "day", d_lite_mday, 0); - rb_define_method(cDate, "day_fraction", d_lite_day_fraction, 0); - - rb_define_method(cDate, "cwyear", d_lite_cwyear, 0); - rb_define_method(cDate, "cweek", d_lite_cweek, 0); - rb_define_method(cDate, "cwday", d_lite_cwday, 0); - -#ifndef NDEBUG - de_define_private_method(cDate, "wnum0", d_lite_wnum0, 0); - de_define_private_method(cDate, "wnum1", d_lite_wnum1, 0); -#endif - - rb_define_method(cDate, "wday", d_lite_wday, 0); - - rb_define_method(cDate, "sunday?", d_lite_sunday_p, 0); - rb_define_method(cDate, "monday?", d_lite_monday_p, 0); - rb_define_method(cDate, "tuesday?", d_lite_tuesday_p, 0); - rb_define_method(cDate, "wednesday?", d_lite_wednesday_p, 0); - rb_define_method(cDate, "thursday?", d_lite_thursday_p, 0); - rb_define_method(cDate, "friday?", d_lite_friday_p, 0); - rb_define_method(cDate, "saturday?", d_lite_saturday_p, 0); - -#ifndef NDEBUG - de_define_method(cDate, "nth_kday?", d_lite_nth_kday_p, 2); -#endif - - rb_define_private_method(cDate, "hour", d_lite_hour, 0); - rb_define_private_method(cDate, "min", d_lite_min, 0); - rb_define_private_method(cDate, "minute", d_lite_min, 0); - rb_define_private_method(cDate, "sec", d_lite_sec, 0); - rb_define_private_method(cDate, "second", d_lite_sec, 0); - rb_define_private_method(cDate, "sec_fraction", d_lite_sec_fraction, 0); - rb_define_private_method(cDate, "second_fraction", d_lite_sec_fraction, 0); - rb_define_private_method(cDate, "offset", d_lite_offset, 0); - rb_define_private_method(cDate, "zone", d_lite_zone, 0); - - rb_define_method(cDate, "julian?", d_lite_julian_p, 0); - rb_define_method(cDate, "gregorian?", d_lite_gregorian_p, 0); - rb_define_method(cDate, "leap?", d_lite_leap_p, 0); - - rb_define_method(cDate, "start", d_lite_start, 0); - rb_define_method(cDate, "new_start", d_lite_new_start, -1); - rb_define_method(cDate, "italy", d_lite_italy, 0); - rb_define_method(cDate, "england", d_lite_england, 0); - rb_define_method(cDate, "julian", d_lite_julian, 0); - rb_define_method(cDate, "gregorian", d_lite_gregorian, 0); - - rb_define_private_method(cDate, "new_offset", d_lite_new_offset, -1); - - rb_define_method(cDate, "+", d_lite_plus, 1); - rb_define_method(cDate, "-", d_lite_minus, 1); - - rb_define_method(cDate, "next_day", d_lite_next_day, -1); - rb_define_method(cDate, "prev_day", d_lite_prev_day, -1); - rb_define_method(cDate, "next", d_lite_next, 0); - rb_define_method(cDate, "succ", d_lite_next, 0); - - rb_define_method(cDate, ">>", d_lite_rshift, 1); - rb_define_method(cDate, "<<", d_lite_lshift, 1); - - rb_define_method(cDate, "next_month", d_lite_next_month, -1); - rb_define_method(cDate, "prev_month", d_lite_prev_month, -1); - rb_define_method(cDate, "next_year", d_lite_next_year, -1); - rb_define_method(cDate, "prev_year", d_lite_prev_year, -1); - - rb_define_method(cDate, "step", d_lite_step, -1); - rb_define_method(cDate, "upto", d_lite_upto, 1); - rb_define_method(cDate, "downto", d_lite_downto, 1); - - rb_define_method(cDate, "<=>", d_lite_cmp, 1); - rb_define_method(cDate, "===", d_lite_equal, 1); - rb_define_method(cDate, "eql?", d_lite_eql_p, 1); - rb_define_method(cDate, "hash", d_lite_hash, 0); - - rb_define_method(cDate, "to_s", d_lite_to_s, 0); -#ifndef NDEBUG - de_define_method(cDate, "inspect_raw", d_lite_inspect_raw, 0); -#endif - rb_define_method(cDate, "inspect", d_lite_inspect, 0); - - rb_define_method(cDate, "strftime", d_lite_strftime, -1); - - rb_define_method(cDate, "asctime", d_lite_asctime, 0); - rb_define_method(cDate, "ctime", d_lite_asctime, 0); - rb_define_method(cDate, "iso8601", d_lite_iso8601, 0); - rb_define_method(cDate, "xmlschema", d_lite_iso8601, 0); - rb_define_method(cDate, "rfc3339", d_lite_rfc3339, 0); - rb_define_method(cDate, "rfc2822", d_lite_rfc2822, 0); - rb_define_method(cDate, "rfc822", d_lite_rfc2822, 0); - rb_define_method(cDate, "httpdate", d_lite_httpdate, 0); - rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0); - -#ifndef NDEBUG - de_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0); -#endif - rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0); - rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1); - - /* datetime */ - - cDateTime = rb_define_class("DateTime", cDate); - - rb_define_singleton_method(cDateTime, "jd", datetime_s_jd, -1); - rb_define_singleton_method(cDateTime, "ordinal", datetime_s_ordinal, -1); - rb_define_singleton_method(cDateTime, "civil", datetime_s_civil, -1); - rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1); - rb_define_singleton_method(cDateTime, "commercial", - datetime_s_commercial, -1); - -#ifndef NDEBUG - de_define_singleton_method(cDateTime, "weeknum", - datetime_s_weeknum, -1); - de_define_singleton_method(cDateTime, "nth_kday", - datetime_s_nth_kday, -1); -#endif - - rb_undef_method(CLASS_OF(cDateTime), "today"); - - rb_define_singleton_method(cDateTime, "now", datetime_s_now, -1); - rb_define_singleton_method(cDateTime, "_strptime", - datetime_s__strptime, -1); - rb_define_singleton_method(cDateTime, "strptime", - datetime_s_strptime, -1); - rb_define_singleton_method(cDateTime, "parse", - datetime_s_parse, -1); - rb_define_singleton_method(cDateTime, "iso8601", - datetime_s_iso8601, -1); - rb_define_singleton_method(cDateTime, "rfc3339", - datetime_s_rfc3339, -1); - rb_define_singleton_method(cDateTime, "xmlschema", - datetime_s_xmlschema, -1); - rb_define_singleton_method(cDateTime, "rfc2822", - datetime_s_rfc2822, -1); - rb_define_singleton_method(cDateTime, "rfc822", - datetime_s_rfc2822, -1); - rb_define_singleton_method(cDateTime, "httpdate", - datetime_s_httpdate, -1); - rb_define_singleton_method(cDateTime, "jisx0301", - datetime_s_jisx0301, -1); - -#define f_public(m,s) rb_funcall(m, rb_intern("public"), 1,\ - ID2SYM(rb_intern(s))) - - f_public(cDateTime, "hour"); - f_public(cDateTime, "min"); - f_public(cDateTime, "minute"); - f_public(cDateTime, "sec"); - f_public(cDateTime, "second"); - f_public(cDateTime, "sec_fraction"); - f_public(cDateTime, "second_fraction"); - f_public(cDateTime, "offset"); - f_public(cDateTime, "zone"); - f_public(cDateTime, "new_offset"); - - rb_define_method(cDateTime, "to_s", dt_lite_to_s, 0); - - rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1); - - rb_define_method(cDateTime, "iso8601", dt_lite_iso8601, -1); - rb_define_method(cDateTime, "xmlschema", dt_lite_iso8601, -1); - rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1); - rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1); - - /* conversions */ - - rb_define_method(rb_cTime, "to_time", time_to_time, 0); - rb_define_method(rb_cTime, "to_date", time_to_date, 0); - rb_define_method(rb_cTime, "to_datetime", time_to_datetime, 0); - - rb_define_method(cDate, "to_time", date_to_time, 0); - rb_define_method(cDate, "to_date", date_to_date, 0); - rb_define_method(cDate, "to_datetime", date_to_datetime, 0); - - rb_define_method(cDateTime, "to_time", datetime_to_time, 0); - rb_define_method(cDateTime, "to_date", datetime_to_date, 0); - rb_define_method(cDateTime, "to_datetime", datetime_to_datetime, 0); - -#ifndef NDEBUG - /* tests */ - - de_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0); - de_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0); - de_define_singleton_method(cDate, "test_commercial", - date_s_test_commercial, 0); - de_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0); - de_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0); - de_define_singleton_method(cDate, "test_unit_conv", - date_s_test_unit_conv, 0); - de_define_singleton_method(cDate, "test_all", date_s_test_all, 0); -#endif -} - -/* -Local variables: -c-file-style: "ruby" -End: -*/ diff --git a/ruby_1_9_3/ext/date/date_parse.c b/ruby_1_9_3/ext/date/date_parse.c deleted file mode 100644 index 903163003c..0000000000 --- a/ruby_1_9_3/ext/date/date_parse.c +++ /dev/null @@ -1,2425 +0,0 @@ -/* - date_parse.c: Coded by Tadayoshi Funaba 2011,2012 -*/ - -#include "ruby.h" -#include "ruby/encoding.h" -#include "ruby/re.h" -#include <ctype.h> - -#define sizeof_array(o) (sizeof o / sizeof o[0]) - -#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0) -#define f_add(x,y) rb_funcall(x, '+', 1, y) -#define f_sub(x,y) rb_funcall(x, '-', 1, y) -#define f_mul(x,y) rb_funcall(x, '*', 1, y) -#define f_div(x,y) rb_funcall(x, '/', 1, y) -#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y) -#define f_mod(x,y) rb_funcall(x, '%', 1, y) -#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y) - -#define f_lt_p(x,y) rb_funcall(x, '<', 1, y) -#define f_gt_p(x,y) rb_funcall(x, '>', 1, y) -#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y) -#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y) - -#define f_to_s(x) rb_funcall(x, rb_intern("to_s"), 0) - -#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s) -#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i) -#define f_aref2(o,i,j) rb_funcall(o, rb_intern("[]"), 2, i, j) -#define f_begin(o,i) rb_funcall(o, rb_intern("begin"), 1, i) -#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i) -#define f_aset(o,i,v) rb_funcall(o, rb_intern("[]="), 2, i, v) -#define f_aset2(o,i,j,v) rb_funcall(o, rb_intern("[]="), 3, i, j, v) -#define f_sub_bang(s,r,x) rb_funcall(s, rb_intern("sub!"), 2, r, x) -#define f_gsub_bang(s,r,x) rb_funcall(s, rb_intern("gsub!"), 2, r, x) - -#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v) -#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k))) -#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k))) - -#define cstr2num(s) rb_cstr_to_inum(s, 10, 0) -#define str2num(s) rb_str_to_inum(s, 10, 0) - -static const char *abbr_days[] = { - "sun", "mon", "tue", "wed", - "thu", "fri", "sat" -}; - -static const char *abbr_months[] = { - "jan", "feb", "mar", "apr", "may", "jun", - "jul", "aug", "sep", "oct", "nov", "dec" -}; - -#define issign(c) ((c) == '-' || (c) == '+') -#define asp_string() rb_str_new(" ", 1) - -static void -s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) -{ - VALUE c = Qnil; - - if (TYPE(m) != T_STRING) - m = f_to_s(m); - - if (!NIL_P(y) && !NIL_P(m) && NIL_P(d)) { - VALUE oy = y; - VALUE om = m; - VALUE od = d; - - y = od; - m = oy; - d = om; - } - - if (NIL_P(y)) { - if (!NIL_P(d) && RSTRING_LEN(d) > 2) { - y = d; - d = Qnil; - } - if (!NIL_P(d) && *RSTRING_PTR(d) == '\'') { - y = d; - d = Qnil; - } - } - - if (!NIL_P(y)) { - const char *s, *bp, *ep; - size_t l; - - s = RSTRING_PTR(y); - while (!issign(*s) && !isdigit(*s)) - s++; - bp = s; - if (issign(*s)) - s++; - l = strspn(s, "0123456789"); - ep = s + l; - if (*ep) { - y = d; - d = rb_str_new(bp, ep - bp); - } - } - - if (!NIL_P(m)) { - const char *s; - - s = RSTRING_PTR(m); - if (*s == '\'' || RSTRING_LEN(m) > 2) { - /* us -> be */ - VALUE oy = y; - VALUE om = m; - VALUE od = d; - - y = om; - m = od; - d = oy; - } - } - - if (!NIL_P(d)) { - const char *s; - - s = RSTRING_PTR(d); - if (*s == '\'' || RSTRING_LEN(d) > 2) { - VALUE oy = y; - VALUE od = d; - - y = od; - d = oy; - } - } - - if (!NIL_P(y)) { - const char *s, *bp, *ep; - int sign = 0; - size_t l; - VALUE iy; - - s = RSTRING_PTR(y); - while (!issign(*s) && !isdigit(*s)) - s++; - bp = s; - if (issign(*s)) { - s++; - sign = 1; - } - if (sign) - c = Qfalse; - l = strspn(s, "0123456789"); - ep = s + l; - if (l > 2) - c = Qfalse; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - iy = cstr2num(buf); - } - if (bc) - iy = f_add(f_negate(iy), INT2FIX(1)); - set_hash("year", iy); - } - - if (!NIL_P(m)) { - const char *s, *bp, *ep; - size_t l; - VALUE im; - - s = RSTRING_PTR(m); - while (!isdigit(*s)) - s++; - bp = s; - l = strspn(s, "0123456789"); - ep = s + l; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - im = cstr2num(buf); - } - set_hash("mon", im); - } - - if (!NIL_P(d)) { - const char *s, *bp, *ep; - size_t l; - VALUE id; - - s = RSTRING_PTR(d); - while (!isdigit(*s)) - s++; - bp = s; - l = strspn(s, "0123456789"); - ep = s + l; - { - char *buf; - - buf = ALLOCA_N(char, ep - bp + 1); - memcpy(buf, bp, ep - bp); - buf[ep - bp] = '\0'; - id = cstr2num(buf); - } - set_hash("mday", id); - } - - if (!NIL_P(c)) - set_hash("_comp", c); -} - -#define DAYS "sunday|monday|tuesday|wednesday|thursday|friday|saturday" -#define MONTHS "january|february|march|april|may|june|july|august|september|october|november|december" -#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat" -#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec" - -static VALUE -regcomp(const char *source, long len, int opt) -{ - VALUE pat; - - pat = rb_reg_new(source, len, opt); - rb_gc_register_mark_object(pat); - return pat; -} - -#define REGCOMP(pat,opt) \ -{ \ - if (NIL_P(pat)) \ - pat = regcomp(pat##_source, sizeof pat##_source - 1, opt); \ -} - -#define REGCOMP_0(pat) REGCOMP(pat, 0) -#define REGCOMP_I(pat) REGCOMP(pat, ONIG_OPTION_IGNORECASE) - -#define MATCH(s,p,c) \ -{ \ - return match(s, p, hash, c); \ -} - -static int -match(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE)) -{ - VALUE m; - - m = f_match(pat, str); - - if (NIL_P(m)) - return 0; - - (*cb)(m, hash); - - return 1; -} - -#define SUBS(s,p,c) \ -{ \ - return subs(s, p, hash, c); \ -} - -static int -subs(VALUE str, VALUE pat, VALUE hash, int (*cb)(VALUE, VALUE)) -{ - VALUE m; - - m = f_match(pat, str); - - if (NIL_P(m)) - return 0; - - { - VALUE be, en; - - be = f_begin(m, INT2FIX(0)); - en = f_end(m, INT2FIX(0)); - f_aset2(str, be, LONG2NUM(NUM2LONG(en) - NUM2LONG(be)), asp_string()); - (*cb)(m, hash); - } - - return 1; -} - -struct zone { - const char *name; - int offset; -}; - -static struct zone zones_source[] = { - {"ut", 0*3600}, {"gmt", 0*3600}, {"est", -5*3600}, {"edt", -4*3600}, - {"cst", -6*3600}, {"cdt", -5*3600}, {"mst", -7*3600}, {"mdt", -6*3600}, - {"pst", -8*3600}, {"pdt", -7*3600}, - {"a", 1*3600}, {"b", 2*3600}, {"c", 3*3600}, {"d", 4*3600}, - {"e", 5*3600}, {"f", 6*3600}, {"g", 7*3600}, {"h", 8*3600}, - {"i", 9*3600}, {"k", 10*3600}, {"l", 11*3600}, {"m", 12*3600}, - {"n", -1*3600}, {"o", -2*3600}, {"p", -3*3600}, {"q", -4*3600}, - {"r", -5*3600}, {"s", -6*3600}, {"t", -7*3600}, {"u", -8*3600}, - {"v", -9*3600}, {"w", -10*3600}, {"x", -11*3600}, {"y", -12*3600}, - {"z", 0*3600}, - - {"utc", 0*3600}, {"wet", 0*3600}, - {"at", -2*3600}, {"brst",-2*3600}, {"ndt", -(2*3600+1800)}, - {"art", -3*3600}, {"adt", -3*3600}, {"brt", -3*3600}, {"clst",-3*3600}, - {"nst", -(3*3600+1800)}, - {"ast", -4*3600}, {"clt", -4*3600}, - {"akdt",-8*3600}, {"ydt", -8*3600}, - {"akst",-9*3600}, {"hadt",-9*3600}, {"hdt", -9*3600}, {"yst", -9*3600}, - {"ahst",-10*3600},{"cat",-10*3600}, {"hast",-10*3600},{"hst",-10*3600}, - {"nt", -11*3600}, - {"idlw",-12*3600}, - {"bst", 1*3600}, {"cet", 1*3600}, {"fwt", 1*3600}, {"met", 1*3600}, - {"mewt", 1*3600}, {"mez", 1*3600}, {"swt", 1*3600}, {"wat", 1*3600}, - {"west", 1*3600}, - {"cest", 2*3600}, {"eet", 2*3600}, {"fst", 2*3600}, {"mest", 2*3600}, - {"mesz", 2*3600}, {"sast", 2*3600}, {"sst", 2*3600}, - {"bt", 3*3600}, {"eat", 3*3600}, {"eest", 3*3600}, {"msk", 3*3600}, - {"msd", 4*3600}, {"zp4", 4*3600}, - {"zp5", 5*3600}, {"ist", (5*3600+1800)}, - {"zp6", 6*3600}, - {"wast", 7*3600}, - {"cct", 8*3600}, {"sgt", 8*3600}, {"wadt", 8*3600}, - {"jst", 9*3600}, {"kst", 9*3600}, - {"east",10*3600}, {"gst", 10*3600}, - {"eadt",11*3600}, - {"idle",12*3600}, {"nzst",12*3600}, {"nzt", 12*3600}, - {"nzdt",13*3600}, - - {"afghanistan", 16200}, {"alaskan", -32400}, - {"arab", 10800}, {"arabian", 14400}, - {"arabic", 10800}, {"atlantic", -14400}, - {"aus central", 34200}, {"aus eastern", 36000}, - {"azores", -3600}, {"canada central", -21600}, - {"cape verde", -3600}, {"caucasus", 14400}, - {"cen. australia", 34200}, {"central america", -21600}, - {"central asia", 21600}, {"central europe", 3600}, - {"central european", 3600}, {"central pacific", 39600}, - {"central", -21600}, {"china", 28800}, - {"dateline", -43200}, {"e. africa", 10800}, - {"e. australia", 36000}, {"e. europe", 7200}, - {"e. south america", -10800}, {"eastern", -18000}, - {"egypt", 7200}, {"ekaterinburg", 18000}, - {"fiji", 43200}, {"fle", 7200}, - {"greenland", -10800}, {"greenwich", 0}, - {"gtb", 7200}, {"hawaiian", -36000}, - {"india", 19800}, {"iran", 12600}, - {"jerusalem", 7200}, {"korea", 32400}, - {"mexico", -21600}, {"mid-atlantic", -7200}, - {"mountain", -25200}, {"myanmar", 23400}, - {"n. central asia", 21600}, {"nepal", 20700}, - {"new zealand", 43200}, {"newfoundland", -12600}, - {"north asia east", 28800}, {"north asia", 25200}, - {"pacific sa", -14400}, {"pacific", -28800}, - {"romance", 3600}, {"russian", 10800}, - {"sa eastern", -10800}, {"sa pacific", -18000}, - {"sa western", -14400}, {"samoa", -39600}, - {"se asia", 25200}, {"malay peninsula", 28800}, - {"south africa", 7200}, {"sri lanka", 21600}, - {"taipei", 28800}, {"tasmania", 36000}, - {"tokyo", 32400}, {"tonga", 46800}, - {"us eastern", -18000}, {"us mountain", -25200}, - {"vladivostok", 36000}, {"w. australia", 28800}, - {"w. central africa", 3600}, {"w. europe", 3600}, - {"west asia", 18000}, {"west pacific", 36000}, - {"yakutsk", 32400} -}; - -VALUE -date_zone_to_diff(VALUE str) -{ - VALUE offset = Qnil; - - long l, i; - char *s, *dest, *d; - int sp = 1; - - l = RSTRING_LEN(str); - s = RSTRING_PTR(str); - - dest = d = ALLOCA_N(char, l + 1); - - for (i = 0; i < l; i++) { - if (isspace(s[i]) || s[i] == '\0') { - if (!sp) - *d++ = ' '; - sp = 1; - } - else { - if (isalpha(s[i])) - *d++ = tolower(s[i]); - else - *d++ = s[i]; - sp = 0; - } - } - if (d > dest) { - if (*(d - 1) == ' ') - --d; - *d = '\0'; - } - str = rb_str_new2(dest); - { -#define STD " standard time" -#define DST " daylight time" - char *ss, *ds; - long sl, dl; - int dst = 0; - - sl = RSTRING_LEN(str) - (sizeof STD - 1); - ss = RSTRING_PTR(str) + sl; - dl = RSTRING_LEN(str) - (sizeof DST - 1); - ds = RSTRING_PTR(str) + dl; - - if (sl >= 0 && strcmp(ss, STD) == 0) { - str = rb_str_new(RSTRING_PTR(str), sl); - } - else if (dl >= 0 && strcmp(ds, DST) == 0) { - str = rb_str_new(RSTRING_PTR(str), dl); - dst = 1; - } -#undef STD -#undef DST - else { -#define DST " dst" - char *ds; - long dl; - - dl = RSTRING_LEN(str) - (sizeof DST - 1); - ds = RSTRING_PTR(str) + dl; - - if (dl >= 0 && strcmp(ds, DST) == 0) { - str = rb_str_new(RSTRING_PTR(str), dl); - dst = 1; - } -#undef DST - } - { - static VALUE zones = Qnil; - - if (NIL_P(zones)) { - int i; - - zones = rb_hash_new(); - rb_gc_register_mark_object(zones); - for (i = 0; i < (int)sizeof_array(zones_source); i++) { - VALUE name = rb_str_new2(zones_source[i].name); - VALUE offset = INT2FIX(zones_source[i].offset); - rb_hash_aset(zones, name, offset); - } - } - - offset = f_aref(zones, str); - if (!NIL_P(offset)) { - if (dst) - offset = f_add(offset, INT2FIX(3600)); - goto ok; - } - } - { - char *s, *p; - VALUE sign; - VALUE hour = Qnil, min = Qnil, sec = Qnil; - VALUE str_orig; - - s = RSTRING_PTR(str); - str_orig = str; - - if (strncmp(s, "gmt", 3) == 0 || - strncmp(s, "utc", 3) == 0) - s += 3; - if (issign(*s)) { - sign = rb_str_new(s, 1); - s++; - - str = rb_str_new2(s); - - if (p = strchr(s, ':')) { - hour = rb_str_new(s, p - s); - s = ++p; - if (p = strchr(s, ':')) { - min = rb_str_new(s, p - s); - s = ++p; - if (p = strchr(s, ':')) { - sec = rb_str_new(s, p - s); - } - else - sec = rb_str_new2(s); - } - else - min = rb_str_new2(s); - RB_GC_GUARD(str_orig); - goto num; - } - if (strpbrk(RSTRING_PTR(str), ",.")) { - char *a, *b; - - a = ALLOCA_N(char, RSTRING_LEN(str) + 1); - strcpy(a, RSTRING_PTR(str)); - b = strpbrk(a, ",."); - *b = '\0'; - b++; - - hour = cstr2num(a); - min = f_mul(rb_rational_new2 - (cstr2num(b), - f_expt(INT2FIX(10), - LONG2NUM((long)strlen(b)))), - INT2FIX(60)); - goto num; - } - { - const char *cs = RSTRING_PTR(str); - long cl = RSTRING_LEN(str); - - if (cl % 2) { - if (cl >= 1) - hour = rb_str_new(&cs[0], 1); - if (cl >= 3) - min = rb_str_new(&cs[1], 2); - if (cl >= 5) - min = rb_str_new(&cs[3], 2); - } - else { - if (cl >= 2) - hour = rb_str_new(&cs[0], 2); - if (cl >= 4) - min = rb_str_new(&cs[2], 2); - if (cl >= 6) - sec = rb_str_new(&cs[4], 2); - } - goto num; - } - num: - if (NIL_P(hour)) - offset = INT2FIX(0); - else { - if (TYPE(hour) == T_STRING) - hour = str2num(hour); - offset = f_mul(hour, INT2FIX(3600)); - } - if (!NIL_P(min)) { - if (TYPE(min) == T_STRING) - min = str2num(min); - offset = f_add(offset, f_mul(min, INT2FIX(60))); - } - if (!NIL_P(sec)) - offset = f_add(offset, str2num(sec)); - if (!NIL_P(sign) && - RSTRING_LEN(sign) == 1 && - *RSTRING_PTR(sign) == '-') - offset = f_negate(offset); - } - } - } - RB_GC_GUARD(str); - ok: - return offset; -} - -static int -day_num(VALUE s) -{ - int i; - - for (i = 0; i < (int)sizeof_array(abbr_days); i++) - if (strncasecmp(abbr_days[i], RSTRING_PTR(s), 3) == 0) - break; - return i; -} - -static int -mon_num(VALUE s) -{ - int i; - - for (i = 0; i < (int)sizeof_array(abbr_months); i++) - if (strncasecmp(abbr_months[i], RSTRING_PTR(s), 3) == 0) - break; - return i + 1; -} - -static int -parse_day_cb(VALUE m, VALUE hash) -{ - VALUE s; - - s = rb_reg_nth_match(1, m); - set_hash("wday", INT2FIX(day_num(s))); - return 1; -} - -static int -parse_day(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b(" ABBR_DAYS ")[^-\\d\\s]*"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_day_cb); -} - -static int -parse_time2_cb(VALUE m, VALUE hash) -{ - VALUE h, min, s, f, p; - - h = rb_reg_nth_match(1, m); - h = str2num(h); - - min = rb_reg_nth_match(2, m); - if (!NIL_P(min)) - min = str2num(min); - - s = rb_reg_nth_match(3, m); - if (!NIL_P(s)) - s = str2num(s); - - f = rb_reg_nth_match(4, m); - - if (!NIL_P(f)) - f = rb_rational_new2(str2num(f), - f_expt(INT2FIX(10), LONG2NUM(RSTRING_LEN(f)))); - - p = rb_reg_nth_match(5, m); - - if (!NIL_P(p)) { - int ih = NUM2INT(h); - ih %= 12; - if (*RSTRING_PTR(p) == 'P' || *RSTRING_PTR(p) == 'p') - ih += 12; - h = INT2FIX(ih); - } - - set_hash("hour", h); - if (!NIL_P(min)) - set_hash("min", min); - if (!NIL_P(s)) - set_hash("sec", s); - if (!NIL_P(f)) - set_hash("sec_fraction", f); - - return 1; -} - -static int -parse_time_cb(VALUE m, VALUE hash) -{ - static const char pat_source[] = - "\\A(\\d+)h?" - "(?:\\s*:?\\s*(\\d+)m?" - "(?:" - "\\s*:?\\s*(\\d+)(?:[,.](\\d+))?s?" - ")?" - ")?" - "(?:\\s*([ap])(?:m\\b|\\.m\\.))?"; - static VALUE pat = Qnil; - VALUE s1, s2; - - s1 = rb_reg_nth_match(1, m); - s2 = rb_reg_nth_match(2, m); - - if (!NIL_P(s2)) - set_hash("zone", s2); - - REGCOMP_I(pat); - - { - VALUE m = f_match(pat, s1); - - if (NIL_P(m)) - return 0; - parse_time2_cb(m, hash); - } - - return 1; -} - -static int -parse_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "(" - "(?:" - "\\d+\\s*:\\s*\\d+" - "(?:" - "\\s*:\\s*\\d+(?:[,.]\\d*)?" - ")?" - "|" - "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?" - ")" - "(?:" - "\\s*" - "[ap](?:m\\b|\\.m\\.)" - ")?" - "|" - "\\d+\\s*[ap](?:m\\b|\\.m\\.)" - ")" - "(?:" - "\\s*" - "(" - "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?" - "|" - "[[:alpha:].\\s]+(?:standard|daylight)\\stime\\b" - "|" - "[[:alpha:]]+(?:\\sdst)?\\b" - ")" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_time_cb); -} - -static int -parse_eu_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d, b; - - d = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - b = rb_reg_nth_match(3, m); - y = rb_reg_nth_match(4, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, !NIL_P(b) && - (*RSTRING_PTR(b) == 'B' || - *RSTRING_PTR(b) == 'b')); - return 1; -} - -static int -parse_eu(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "'?(\\d+)[^-\\d\\s]*" - "\\s*" - "(" ABBR_MONTHS ")[^-\\d\\s']*" - "(?:" - "\\s*" - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" - "\\s*" - "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_eu_cb); -} - -static int -parse_us_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d, b; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - b = rb_reg_nth_match(3, m); - y = rb_reg_nth_match(4, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, !NIL_P(b) && - (*RSTRING_PTR(b) == 'B' || - *RSTRING_PTR(b) == 'b')); - return 1; -} - -static int -parse_us(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(" ABBR_MONTHS ")[^-\\d\\s']*" - "\\s*" - "('?\\d+)[^-\\d\\s']*" - "(?:" - "\\s*" - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" - "\\s*" - "('?-?\\d+)" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_us_cb); -} - -static int -parse_iso_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_iso(VALUE str, VALUE hash) -{ - static const char pat_source[] = "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso_cb); -} - -static int -parse_iso21_cb(VALUE m, VALUE hash) -{ - VALUE y, w, d; - - y = rb_reg_nth_match(1, m); - w = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - if (!NIL_P(y)) - set_hash("cwyear", str2num(y)); - set_hash("cweek", str2num(w)); - if (!NIL_P(d)) - set_hash("cwday", str2num(d)); - - return 1; -} - -static int -parse_iso21(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(\\d{2}|\\d{4})?-?w(\\d{2})(?:-?(\\d))?\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_iso21_cb); -} - -static int -parse_iso22_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("cwday", str2num(d)); - return 1; -} - -static int -parse_iso22(VALUE str, VALUE hash) -{ - static const char pat_source[] = "-w-(\\d)\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_iso22_cb); -} - -static int -parse_iso23_cb(VALUE m, VALUE hash) -{ - VALUE mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - if (!NIL_P(mon)) - set_hash("mon", str2num(mon)); - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_iso23(VALUE str, VALUE hash) -{ - static const char pat_source[] = "--(\\d{2})?-(\\d{2})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso23_cb); -} - -static int -parse_iso24_cb(VALUE m, VALUE hash) -{ - VALUE mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - set_hash("mon", str2num(mon)); - if (!NIL_P(d)) - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_iso24(VALUE str, VALUE hash) -{ - static const char pat_source[] = "--(\\d{2})(\\d{2})?\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_iso24_cb); -} - -static int -parse_iso25_cb(VALUE m, VALUE hash) -{ - VALUE y, d; - - y = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - - set_hash("year", str2num(y)); - set_hash("yday", str2num(d)); - - return 1; -} - -static int -parse_iso25(VALUE str, VALUE hash) -{ - static const char pat0_source[] = "[,.](\\d{2}|\\d{4})-\\d{3}\\b"; - static VALUE pat0 = Qnil; - static const char pat_source[] = "\\b(\\d{2}|\\d{4})-(\\d{3})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat0); - REGCOMP_0(pat); - - if (!NIL_P(f_match(pat0, str))) - return 0; - SUBS(str, pat, parse_iso25_cb); -} - -static int -parse_iso26_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("yday", str2num(d)); - - return 1; -} -static int -parse_iso26(VALUE str, VALUE hash) -{ - static const char pat0_source[] = "\\d-\\d{3}\\b"; - static VALUE pat0 = Qnil; - static const char pat_source[] = "\\b-(\\d{3})\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat0); - REGCOMP_0(pat); - - if (!NIL_P(f_match(pat0, str))) - return 0; - SUBS(str, pat, parse_iso26_cb); -} - -static int -parse_iso2(VALUE str, VALUE hash) -{ - if (parse_iso21(str, hash)) - goto ok; - if (parse_iso22(str, hash)) - goto ok; - if (parse_iso23(str, hash)) - goto ok; - if (parse_iso24(str, hash)) - goto ok; - if (parse_iso25(str, hash)) - goto ok; - if (parse_iso26(str, hash)) - goto ok; - return 0; - - ok: - return 1; -} - -static int -gengo(int c) -{ - int e; - - switch (c) { - case 'M': case 'm': e = 1867; break; - case 'T': case 't': e = 1911; break; - case 'S': case 's': e = 1925; break; - case 'H': case 'h': e = 1988; break; - default: e = 0; break; - } - return e; -} - -static int -parse_jis_cb(VALUE m, VALUE hash) -{ - VALUE e, y, mon, d; - int ep; - - e = rb_reg_nth_match(1, m); - y = rb_reg_nth_match(2, m); - mon = rb_reg_nth_match(3, m); - d = rb_reg_nth_match(4, m); - - ep = gengo(*RSTRING_PTR(e)); - - set_hash("year", f_add(str2num(y), INT2FIX(ep))); - set_hash("mon", str2num(mon)); - set_hash("mday", str2num(d)); - - return 1; -} - -static int -parse_jis(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b([mtsh])(\\d+)\\.(\\d+)\\.(\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_jis_cb); -} - -static int -parse_vms11_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - d = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - y = rb_reg_nth_match(3, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_vms11(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)-(" ABBR_MONTHS ")[^-]*" - "-('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_vms11_cb); -} - -static int -parse_vms12_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - mon = rb_reg_nth_match(1, m); - d = rb_reg_nth_match(2, m); - y = rb_reg_nth_match(3, m); - - mon = INT2FIX(mon_num(mon)); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_vms12(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(" ABBR_MONTHS ")[^-]*" - "-('?-?\\d+)(?:-('?-?\\d+))?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_vms12_cb); -} - -static int -parse_vms(VALUE str, VALUE hash) -{ - if (parse_vms11(str, hash)) - goto ok; - if (parse_vms12(str, hash)) - goto ok; - return 0; - - ok: - return 1; -} - -static int -parse_sla_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_sla(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_sla_cb); -} - -static int -parse_dot_cb(VALUE m, VALUE hash) -{ - VALUE y, mon, d; - - y = rb_reg_nth_match(1, m); - mon = rb_reg_nth_match(2, m); - d = rb_reg_nth_match(3, m); - - s3e(hash, y, mon, d, 0); - return 1; -} - -static int -parse_dot(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_dot_cb); -} - -static int -parse_year_cb(VALUE m, VALUE hash) -{ - VALUE y; - - y = rb_reg_nth_match(1, m); - set_hash("year", str2num(y)); - return 1; -} - -static int -parse_year(VALUE str, VALUE hash) -{ - static const char pat_source[] = "'(\\d+)\\b"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - SUBS(str, pat, parse_year_cb); -} - -static int -parse_mon_cb(VALUE m, VALUE hash) -{ - VALUE mon; - - mon = rb_reg_nth_match(1, m); - set_hash("mon", INT2FIX(mon_num(mon))); - return 1; -} - -static int -parse_mon(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\b(" ABBR_MONTHS ")\\S*"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_mon_cb); -} - -static int -parse_mday_cb(VALUE m, VALUE hash) -{ - VALUE d; - - d = rb_reg_nth_match(1, m); - set_hash("mday", str2num(d)); - return 1; -} - -static int -parse_mday(VALUE str, VALUE hash) -{ - static const char pat_source[] = "(\\d+)(st|nd|rd|th)\\b"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_mday_cb); -} - -static int -n2i(const char *s, long f, long w) -{ - long e, i; - int v; - - e = f + w; - v = 0; - for (i = f; i < e; i++) { - v *= 10; - v += s[i] - '0'; - } - return v; -} - -static int -parse_ddd_cb(VALUE m, VALUE hash) -{ - VALUE s1, s2, s3, s4, s5; - const char *cs2, *cs3, *cs5; - long l2, l3, l4, l5; - - s1 = rb_reg_nth_match(1, m); - s2 = rb_reg_nth_match(2, m); - s3 = rb_reg_nth_match(3, m); - s4 = rb_reg_nth_match(4, m); - s5 = rb_reg_nth_match(5, m); - - cs2 = RSTRING_PTR(s2); - l2 = RSTRING_LEN(s2); - - switch (l2) { - case 2: - if (NIL_P(s3) && !NIL_P(s4)) - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - else - set_hash("mday", INT2FIX(n2i(cs2, 0, 2))); - break; - case 4: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - } - else { - set_hash("mon", INT2FIX(n2i(cs2, 0, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 2, 2))); - } - break; - case 6: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - } - else { - int y = n2i(cs2, 0, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("mon", INT2FIX(n2i(cs2, 2, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 4, 2))); - } - break; - case 8: - case 10: - case 12: - case 14: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - set_hash("mday", INT2FIX(n2i(cs2, l2-8, 2))); - if (l2 >= 10) - set_hash("mon", INT2FIX(n2i(cs2, l2-10, 2))); - if (l2 == 12) { - int y = n2i(cs2, l2-12, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - } - if (l2 == 14) { - int y = n2i(cs2, l2-14, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("_comp", Qfalse); - } - } - else { - int y = n2i(cs2, 0, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("mon", INT2FIX(n2i(cs2, 4, 2))); - set_hash("mday", INT2FIX(n2i(cs2, 6, 2))); - if (l2 >= 10) - set_hash("hour", INT2FIX(n2i(cs2, 8, 2))); - if (l2 >= 12) - set_hash("min", INT2FIX(n2i(cs2, 10, 2))); - if (l2 >= 14) - set_hash("sec", INT2FIX(n2i(cs2, 12, 2))); - set_hash("_comp", Qfalse); - } - break; - case 3: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-3, 1))); - } - else - set_hash("yday", INT2FIX(n2i(cs2, 0, 3))); - break; - case 5: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-5, 1))); - } - else { - int y = n2i(cs2, 0, 2); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("yday", INT2FIX(n2i(cs2, 2, 3))); - } - break; - case 7: - if (NIL_P(s3) && !NIL_P(s4)) { - set_hash("sec", INT2FIX(n2i(cs2, l2-2, 2))); - set_hash("min", INT2FIX(n2i(cs2, l2-4, 2))); - set_hash("hour", INT2FIX(n2i(cs2, l2-6, 2))); - set_hash("mday", INT2FIX(n2i(cs2, l2-7, 1))); - } - else { - int y = n2i(cs2, 0, 4); - if (!NIL_P(s1) && *RSTRING_PTR(s1) == '-') - y = -y; - set_hash("year", INT2FIX(y)); - set_hash("yday", INT2FIX(n2i(cs2, 4, 3))); - } - break; - } - RB_GC_GUARD(s2); - if (!NIL_P(s3)) { - cs3 = RSTRING_PTR(s3); - l3 = RSTRING_LEN(s3); - - if (!NIL_P(s4)) { - switch (l3) { - case 2: - case 4: - case 6: - set_hash("sec", INT2FIX(n2i(cs3, l3-2, 2))); - if (l3 >= 4) - set_hash("min", INT2FIX(n2i(cs3, l3-4, 2))); - if (l3 >= 6) - set_hash("hour", INT2FIX(n2i(cs3, l3-6, 2))); - break; - } - } - else { - switch (l3) { - case 2: - case 4: - case 6: - set_hash("hour", INT2FIX(n2i(cs3, 0, 2))); - if (l3 >= 4) - set_hash("min", INT2FIX(n2i(cs3, 2, 2))); - if (l3 >= 6) - set_hash("sec", INT2FIX(n2i(cs3, 4, 2))); - break; - } - } - RB_GC_GUARD(s3); - } - if (!NIL_P(s4)) { - l4 = RSTRING_LEN(s4); - - set_hash("sec_fraction", - rb_rational_new2(str2num(s4), - f_expt(INT2FIX(10), LONG2NUM(l4)))); - } - if (!NIL_P(s5)) { - cs5 = RSTRING_PTR(s5); - l5 = RSTRING_LEN(s5); - - set_hash("zone", s5); - - if (*cs5 == '[') { - char *buf = ALLOCA_N(char, l5 + 1); - char *s1, *s2, *s3; - VALUE zone; - - memcpy(buf, cs5, l5); - buf[l5 - 1] = '\0'; - - s1 = buf + 1; - s2 = strchr(buf, ':'); - if (s2) { - *s2 = '\0'; - s2++; - } - if (s2) - s3 = s2; - else - s3 = s1; - zone = rb_str_new2(s3); - set_hash("zone", zone); - if (isdigit(*s1)) - *--s1 = '+'; - set_hash("offset", date_zone_to_diff(rb_str_new2(s1))); - } - RB_GC_GUARD(s5); - } - - return 1; -} - -static int -parse_ddd(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "([-+]?)(\\d{2,14})" - "(?:" - "\\s*" - "t?" - "\\s*" - "(\\d{2,6})?(?:[,.](\\d*))?" - ")?" - "(?:" - "\\s*" - "(" - "z\\b" - "|" - "[-+]\\d{1,4}\\b" - "|" - "\\[[-+]?\\d[^\\]]*\\]" - ")" - ")?"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_ddd_cb); -} - -static int -parse_bc_cb(VALUE m, VALUE hash) -{ - VALUE y; - - y = ref_hash("year"); - if (!NIL_P(y)) - set_hash("year", f_add(f_negate(y), INT2FIX(1))); - - return 1; -} - -static int -parse_bc(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\b(bc\\b|bce\\b|b\\.c\\.|b\\.c\\.e\\.)"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_bc_cb); -} - -static int -parse_frag_cb(VALUE m, VALUE hash) -{ - VALUE s, n; - - s = rb_reg_nth_match(1, m); - - if (!NIL_P(ref_hash("hour")) && NIL_P(ref_hash("mday"))) { - n = str2num(s); - if (f_ge_p(n, INT2FIX(1)) && - f_le_p(n, INT2FIX(31))) - set_hash("mday", n); - } - if (!NIL_P(ref_hash("mday")) && NIL_P(ref_hash("hour"))) { - n = str2num(s); - if (f_ge_p(n, INT2FIX(0)) && - f_le_p(n, INT2FIX(24))) - set_hash("hour", n); - } - - return 1; -} - -static int -parse_frag(VALUE str, VALUE hash) -{ - static const char pat_source[] = "\\A\\s*(\\d{1,2})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - SUBS(str, pat, parse_frag_cb); -} - -#define HAVE_ALPHA (1<<0) -#define HAVE_DIGIT (1<<1) -#define HAVE_DASH (1<<2) -#define HAVE_DOT (1<<3) -#define HAVE_SLASH (1<<4) - -static unsigned -check_class(VALUE s) -{ - unsigned flags; - long i; - - flags = 0; - for (i = 0; i < RSTRING_LEN(s); i++) { - if (isalpha(RSTRING_PTR(s)[i])) - flags |= HAVE_ALPHA; - if (isdigit(RSTRING_PTR(s)[i])) - flags |= HAVE_DIGIT; - if (RSTRING_PTR(s)[i] == '-') - flags |= HAVE_DASH; - if (RSTRING_PTR(s)[i] == '.') - flags |= HAVE_DOT; - if (RSTRING_PTR(s)[i] == '/') - flags |= HAVE_SLASH; - } - return flags; -} - -#define HAVE_ELEM_P(x) ((check_class(str) & (x)) == (x)) - -VALUE -date__parse(VALUE str, VALUE comp) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - { - static const char pat_source[] = "[^-+',./:@[:alnum:]\\[\\]]+"; - static VALUE pat = Qnil; - - REGCOMP_0(pat); - str = rb_str_dup(str); - f_gsub_bang(str, pat, asp_string()); - } - - hash = rb_hash_new(); - set_hash("_comp", comp); - - if (HAVE_ELEM_P(HAVE_ALPHA)) - parse_day(str, hash); - if (HAVE_ELEM_P(HAVE_DIGIT)) - parse_time(str, hash); - - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) - if (parse_eu(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT)) - if (parse_us(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DASH)) - if (parse_iso(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT)) - if (parse_jis(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA|HAVE_DIGIT|HAVE_DASH)) - if (parse_vms(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_SLASH)) - if (parse_sla(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT|HAVE_DOT)) - if (parse_dot(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_iso2(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_year(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_ALPHA)) - if (parse_mon(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_mday(str, hash)) - goto ok; - if (HAVE_ELEM_P(HAVE_DIGIT)) - if (parse_ddd(str, hash)) - goto ok; - - ok: - if (HAVE_ELEM_P(HAVE_ALPHA)) - parse_bc(str, hash); - if (HAVE_ELEM_P(HAVE_DIGIT)) - parse_frag(str, hash); - - { - if (RTEST(ref_hash("_comp"))) { - VALUE y; - - y = ref_hash("cwyear"); - if (!NIL_P(y)) - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) { - if (f_ge_p(y, INT2FIX(69))) - set_hash("cwyear", f_add(y, INT2FIX(1900))); - else - set_hash("cwyear", f_add(y, INT2FIX(2000))); - } - y = ref_hash("year"); - if (!NIL_P(y)) - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) { - if (f_ge_p(y, INT2FIX(69))) - set_hash("year", f_add(y, INT2FIX(1900))); - else - set_hash("year", f_add(y, INT2FIX(2000))); - } - } - } - - del_hash("_comp"); - - { - VALUE zone = ref_hash("zone"); - if (!NIL_P(zone) && NIL_P(ref_hash("offset"))) - set_hash("offset", date_zone_to_diff(zone)); - } - - rb_backref_set(backref); - - return hash; -} - -static VALUE -comp_year69(VALUE y) -{ - if (f_ge_p(y, INT2FIX(69))) - return f_add(y, INT2FIX(1900)); - return f_add(y, INT2FIX(2000)); -} - -static VALUE -comp_year50(VALUE y) -{ - if (f_ge_p(y, INT2FIX(50))) - return f_add(y, INT2FIX(1900)); - return f_add(y, INT2FIX(2000)); -} - -static VALUE -sec_fraction(VALUE f) -{ - return rb_rational_new2(str2num(f), - f_expt(INT2FIX(10), - LONG2NUM(RSTRING_LEN(f)))); -} - -#define SNUM 14 - -static int -iso8601_ext_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[3])) { - set_hash("mday", str2num(s[3])); - if (strcmp(RSTRING_PTR(s[1]), "-") != 0) { - y = str2num(s[1]); - if (RSTRING_LEN(s[1]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - if (NIL_P(s[2])) { - if (strcmp(RSTRING_PTR(s[1]), "-") != 0) - return 0; - } - else - set_hash("mon", str2num(s[2])); - } - else if (!NIL_P(s[5])) { - set_hash("yday", str2num(s[5])); - if (!NIL_P(s[4])) { - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - } - else if (!NIL_P(s[8])) { - set_hash("cweek", str2num(s[7])); - set_hash("cwday", str2num(s[8])); - if (!NIL_P(s[6])) { - y = str2num(s[6]); - if (RSTRING_LEN(s[6]) < 4) - y = comp_year69(y); - set_hash("cwyear", y); - } - } - else if (!NIL_P(s[9])) { - set_hash("cwday", str2num(s[9])); - } - if (!NIL_P(s[10])) { - set_hash("hour", str2num(s[10])); - set_hash("min", str2num(s[11])); - if (!NIL_P(s[12])) - set_hash("sec", str2num(s[12])); - } - if (!NIL_P(s[13])) { - set_hash("sec_fraction", sec_fraction(s[13])); - } - if (!NIL_P(s[14])) { - set_hash("zone", s[14]); - set_hash("offset", date_zone_to_diff(s[14])); - } - - return 1; -} - -static int -iso8601_ext_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:([-+]?\\d{2,}|-)-(\\d{2})?-(\\d{2})|" - "([-+]?\\d{2,})?-(\\d{3})|" - "(\\d{4}|\\d{2})?-w(\\d{2})-(\\d)|" - "-w-(\\d))" - "(?:t" - "(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(?::?\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_ext_datetime_cb); -} - -#undef SNUM -#define SNUM 17 - -static int -iso8601_bas_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[3])) { - set_hash("mday", str2num(s[3])); - if (strcmp(RSTRING_PTR(s[1]), "--") != 0) { - y = str2num(s[1]); - if (RSTRING_LEN(s[1]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - if (*RSTRING_PTR(s[2]) == '-') { - if (strcmp(RSTRING_PTR(s[1]), "--") != 0) - return 0; - } - else - set_hash("mon", str2num(s[2])); - } - else if (!NIL_P(s[5])) { - set_hash("yday", str2num(s[5])); - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year69(y); - set_hash("year", y); - } - else if (!NIL_P(s[6])) { - set_hash("yday", str2num(s[6])); - } - else if (!NIL_P(s[9])) { - set_hash("cweek", str2num(s[8])); - set_hash("cwday", str2num(s[9])); - y = str2num(s[7]); - if (RSTRING_LEN(s[7]) < 4) - y = comp_year69(y); - set_hash("cwyear", y); - } - else if (!NIL_P(s[11])) { - set_hash("cweek", str2num(s[10])); - set_hash("cwday", str2num(s[11])); - } - else if (!NIL_P(s[12])) { - set_hash("cwday", str2num(s[12])); - } - if (!NIL_P(s[13])) { - set_hash("hour", str2num(s[13])); - set_hash("min", str2num(s[14])); - if (!NIL_P(s[15])) - set_hash("sec", str2num(s[15])); - } - if (!NIL_P(s[16])) { - set_hash("sec_fraction", sec_fraction(s[16])); - } - if (!NIL_P(s[17])) { - set_hash("zone", s[17]); - set_hash("offset", date_zone_to_diff(s[17])); - } - - return 1; -} - -static int -iso8601_bas_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:([-+]?(?:\\d{4}|\\d{2})|--)(\\d{2}|-)(\\d{2})|" - "([-+]?(?:\\d{4}|\\d{2}))(\\d{3})|" - "-(\\d{3})|" - "(\\d{4}|\\d{2})w(\\d{2})(\\d)|" - "-w(\\d{2})(\\d)|" - "-w-(\\d))" - "(?:t?" - "(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(?:\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_bas_datetime_cb); -} - -#undef SNUM -#define SNUM 5 - -static int -iso8601_ext_time_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("hour", str2num(s[1])); - set_hash("min", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("sec", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("sec_fraction", sec_fraction(s[4])); - if (!NIL_P(s[5])) { - set_hash("zone", s[5]); - set_hash("offset", date_zone_to_diff(s[5])); - } - - return 1; -} - -#define iso8601_bas_time_cb iso8601_ext_time_cb - -static int -iso8601_ext_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(:?\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_ext_time_cb); -} - -static int -iso8601_bas_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(\\d{2})(\\d{2})(?:(\\d{2})(?:[,.](\\d+))?)?" - "(z|[-+]\\d{2}(\\d{2})?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, iso8601_bas_time_cb); -} - -VALUE -date__iso8601(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (iso8601_ext_datetime(str, hash)) - goto ok; - if (iso8601_bas_datetime(str, hash)) - goto ok; - if (iso8601_ext_time(str, hash)) - goto ok; - if (iso8601_bas_time(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -rfc3339_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("year", str2num(s[1])); - set_hash("mon", str2num(s[2])); - set_hash("mday", str2num(s[3])); - set_hash("hour", str2num(s[4])); - set_hash("min", str2num(s[5])); - set_hash("sec", str2num(s[6])); - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - if (!NIL_P(s[7])) - set_hash("sec_fraction", sec_fraction(s[7])); - - return 1; -} - -static int -rfc3339(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(-?\\d{4})-(\\d{2})-(\\d{2})" - "(?:t|\\s)" - "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?" - "(z|[-+]\\d{2}:\\d{2})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, rfc3339_cb); -} - -VALUE -date__rfc3339(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - rfc3339(str, hash); - rb_backref_set(backref); - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -xmlschema_datetime_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("year", str2num(s[1])); - if (!NIL_P(s[2])) - set_hash("mon", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("mday", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("hour", str2num(s[4])); - if (!NIL_P(s[5])) - set_hash("min", str2num(s[5])); - if (!NIL_P(s[6])) - set_hash("sec", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec_fraction", sec_fraction(s[7])); - if (!NIL_P(s[8])) { - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - } - - return 1; -} - -static int -xmlschema_datetime(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(-?\\d{4,})(?:-(\\d{2})(?:-(\\d{2}))?)?" - "(?:t" - "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_datetime_cb); -} - -#undef SNUM -#define SNUM 5 - -static int -xmlschema_time_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("hour", str2num(s[1])); - set_hash("min", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("sec", str2num(s[3])); - if (!NIL_P(s[4])) - set_hash("sec_fraction", sec_fraction(s[4])); - if (!NIL_P(s[5])) { - set_hash("zone", s[5]); - set_hash("offset", date_zone_to_diff(s[5])); - } - - return 1; -} - -static int -xmlschema_time(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_time_cb); -} - -#undef SNUM -#define SNUM 4 - -static int -xmlschema_trunc_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - if (!NIL_P(s[1])) - set_hash("mon", str2num(s[1])); - if (!NIL_P(s[2])) - set_hash("mday", str2num(s[2])); - if (!NIL_P(s[3])) - set_hash("mday", str2num(s[3])); - if (!NIL_P(s[4])) { - set_hash("zone", s[4]); - set_hash("offset", date_zone_to_diff(s[4])); - } - - return 1; -} - -static int -xmlschema_trunc(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:--(\\d{2})(?:-(\\d{2}))?|---(\\d{2}))" - "(z|[-+]\\d{2}:\\d{2})?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, xmlschema_trunc_cb); -} - -VALUE -date__xmlschema(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (xmlschema_datetime(str, hash)) - goto ok; - if (xmlschema_time(str, hash)) - goto ok; - if (xmlschema_trunc(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -rfc2822_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - y = str2num(s[4]); - if (RSTRING_LEN(s[4]) < 4) - y = comp_year50(y); - set_hash("year", y); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", date_zone_to_diff(s[8])); - - return 1; -} - -static int -rfc2822(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(?:(" ABBR_DAYS ")\\s*,\\s+)?" - "(\\d{1,2})\\s+" - "(" ABBR_MONTHS ")\\s+" - "(-?\\d{2,})\\s+" - "(\\d{2}):(\\d{2})(?::(\\d{2}))?\\s*" - "([-+]\\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, rfc2822_cb); -} - -VALUE -date__rfc2822(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - rfc2822(str, hash); - rb_backref_set(backref); - return hash; -} - -#undef SNUM -#define SNUM 8 - -static int -httpdate_type1_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - set_hash("year", str2num(s[4])); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", INT2FIX(0)); - - return 1; -} - -static int -httpdate_type1(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" ABBR_DAYS ")\\s*,\\s+" - "(\\d{2})\\s+" - "(" ABBR_MONTHS ")\\s+" - "(-?\\d{4})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(gmt)\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type1_cb); -} - -#undef SNUM -#define SNUM 8 - -static int -httpdate_type2_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1], y; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mday", str2num(s[2])); - set_hash("mon", INT2FIX(mon_num(s[3]))); - y = str2num(s[4]); - if (f_ge_p(y, INT2FIX(0)) && f_le_p(y, INT2FIX(99))) - y = comp_year69(y); - set_hash("year", y); - set_hash("hour", str2num(s[5])); - set_hash("min", str2num(s[6])); - set_hash("sec", str2num(s[7])); - set_hash("zone", s[8]); - set_hash("offset", INT2FIX(0)); - - return 1; -} - -static int -httpdate_type2(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" DAYS ")\\s*,\\s+" - "(\\d{2})\\s*-\\s*" - "(" ABBR_MONTHS ")\\s*-\\s*" - "(\\d{2})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(gmt)\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type2_cb); -} - -#undef SNUM -#define SNUM 7 - -static int -httpdate_type3_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - set_hash("wday", INT2FIX(day_num(s[1]))); - set_hash("mon", INT2FIX(mon_num(s[2]))); - set_hash("mday", str2num(s[3])); - set_hash("hour", str2num(s[4])); - set_hash("min", str2num(s[5])); - set_hash("sec", str2num(s[6])); - set_hash("year", str2num(s[7])); - - return 1; -} - -static int -httpdate_type3(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*(" ABBR_DAYS ")\\s+" - "(" ABBR_MONTHS ")\\s+" - "(\\d{1,2})\\s+" - "(\\d{2}):(\\d{2}):(\\d{2})\\s+" - "(\\d{4})\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, httpdate_type3_cb); -} - -VALUE -date__httpdate(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - - if (httpdate_type1(str, hash)) - goto ok; - if (httpdate_type2(str, hash)) - goto ok; - if (httpdate_type3(str, hash)) - goto ok; - - ok: - rb_backref_set(backref); - - return hash; -} - -#undef SNUM -#define SNUM 9 - -static int -jisx0301_cb(VALUE m, VALUE hash) -{ - VALUE s[SNUM + 1]; - int ep; - - { - int i; - s[0] = Qnil; - for (i = 1; i <= SNUM; i++) - s[i] = rb_reg_nth_match(i, m); - } - - ep = gengo(NIL_P(s[1]) ? 'h' : *RSTRING_PTR(s[1])); - set_hash("year", f_add(str2num(s[2]), INT2FIX(ep))); - set_hash("mon", str2num(s[3])); - set_hash("mday", str2num(s[4])); - if (!NIL_P(s[5])) { - set_hash("hour", str2num(s[5])); - if (!NIL_P(s[6])) - set_hash("min", str2num(s[6])); - if (!NIL_P(s[7])) - set_hash("sec", str2num(s[7])); - } - if (!NIL_P(s[8])) - set_hash("sec_fraction", sec_fraction(s[8])); - if (!NIL_P(s[9])) { - set_hash("zone", s[9]); - set_hash("offset", date_zone_to_diff(s[9])); - } - - return 1; -} - -static int -jisx0301(VALUE str, VALUE hash) -{ - static const char pat_source[] = - "\\A\\s*([mtsh])?(\\d{2})\\.(\\d{2})\\.(\\d{2})" - "(?:t" - "(?:(\\d{2}):(\\d{2})(?::(\\d{2})(?:[,.](\\d*))?)?" - "(z|[-+]\\d{2}(?::?\\d{2})?)?)?)?\\s*\\z"; - static VALUE pat = Qnil; - - REGCOMP_I(pat); - MATCH(str, pat, jisx0301_cb); -} - -VALUE -date__jisx0301(VALUE str) -{ - VALUE backref, hash; - - backref = rb_backref_get(); - rb_match_busy(backref); - - hash = rb_hash_new(); - if (jisx0301(str, hash)) - goto ok; - hash = date__iso8601(str); - - ok: - rb_backref_set(backref); - return hash; -} - -/* -Local variables: -c-file-style: "ruby" -End: -*/ diff --git a/ruby_1_9_3/ext/date/date_strftime.c b/ruby_1_9_3/ext/date/date_strftime.c deleted file mode 100644 index 71e1bd7f00..0000000000 --- a/ruby_1_9_3/ext/date/date_strftime.c +++ /dev/null @@ -1,1155 +0,0 @@ -/* -*- c-file-style: "linux" -*- */ - -/* - * strftime.c - * - * Public-domain implementation of ANSI C library routine. - * - * It's written in old-style C for maximal portability. - * However, since I'm used to prototypes, I've included them too. - * - * If you want stuff in the System V ascftime routine, add the SYSV_EXT define. - * For extensions from SunOS, add SUNOS_EXT. - * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE. - * For VMS dates, add VMS_EXT. - * For a an RFC822 time format, add MAILHEADER_EXT. - * For ISO week years, add ISO_DATE_EXT. - * For complete POSIX semantics, add POSIX_SEMANTICS. - * - * The code for %c, %x, and %X now follows the 1003.2 specification for - * the POSIX locale. - * This version ignores LOCALE information. - * It also doesn't worry about multi-byte characters. - * So there. - * - * This file is also shipped with GAWK (GNU Awk), gawk specific bits of - * code are included if GAWK is defined. - * - * Arnold Robbins - * January, February, March, 1991 - * Updated March, April 1992 - * Updated April, 1993 - * Updated February, 1994 - * Updated May, 1994 - * Updated January, 1995 - * Updated September, 1995 - * Updated January, 1996 - * - * Fixes from ado@elsie.nci.nih.gov - * February 1991, May 1992 - * Fixes from Tor Lillqvist tml@tik.vtt.fi - * May, 1993 - * Further fixes from ado@elsie.nci.nih.gov - * February 1994 - * %z code from chip@chinacat.unicom.com - * Applied September 1995 - * %V code fixed (again) and %G, %g added, - * January 1996 - */ - -#include "ruby/ruby.h" -#include "date_tmx.h" - -#ifndef GAWK -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <errno.h> -#endif -#if defined(TM_IN_SYS_TIME) || !defined(GAWK) -#include <sys/types.h> -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#endif -#include <math.h> - -/* defaults: season to taste */ -#define SYSV_EXT 1 /* stuff in System V ascftime routine */ -#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */ -#define POSIX2_DATE 1 /* stuff in Posix 1003.2 date command */ -#define VMS_EXT 1 /* include %v for VMS date format */ -#define MAILHEADER_EXT 1 /* add %z for HHMM format */ -#define ISO_DATE_EXT 1 /* %G and %g for year of ISO week */ - -#if defined(ISO_DATE_EXT) -#if ! defined(POSIX2_DATE) -#define POSIX2_DATE 1 -#endif -#endif - -#if defined(POSIX2_DATE) -#if ! defined(SYSV_EXT) -#define SYSV_EXT 1 -#endif -#if ! defined(SUNOS_EXT) -#define SUNOS_EXT 1 -#endif -#endif - -#if defined(POSIX2_DATE) -#define adddecl(stuff) stuff -#else -#define adddecl(stuff) -#endif - -#undef strchr /* avoid AIX weirdness */ - -#if 0 -#if !defined __STDC__ && !defined _WIN32 -#define const /**/ -static int weeknumber(); -adddecl(static int iso8601wknum();) -static int weeknumber_v(); -adddecl(static int iso8601wknum_v();) -#else -static int weeknumber(const struct tm *timeptr, int firstweekday); -adddecl(static int iso8601wknum(const struct tm *timeptr);) -static int weeknumber_v(const struct tmx *tmx, int firstweekday); -adddecl(static int iso8601wknum_v(const struct tmx *tmx);) -#endif -#endif - -#ifdef STDC_HEADERS -#include <stdlib.h> -#include <string.h> -#else -extern void *malloc(); -extern void *realloc(); -extern char *getenv(); -extern char *strchr(); -#endif - -#define range(low, item, hi) max((low), min((item), (hi))) - -#undef min /* just in case */ - -/* min --- return minimum of two numbers */ - -#ifndef __STDC__ -static inline int -min(a, b) -int a, b; -#else -static inline int -min(int a, int b) -#endif -{ - return (a < b ? a : b); -} - -#undef max /* also, just in case */ - -/* max --- return maximum of two numbers */ - -#ifndef __STDC__ -static inline int -max(a, b) -int a, b; -#else -static inline int -max(int a, int b) -#endif -{ - return (a > b ? a : b); -} - -#ifdef NO_STRING_LITERAL_CONCATENATION -#error No string literal concatenation -#endif - -#define add(x,y) (rb_funcall((x), '+', 1, (y))) -#define sub(x,y) (rb_funcall((x), '-', 1, (y))) -#define mul(x,y) (rb_funcall((x), '*', 1, (y))) -#define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y))) -#define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y))) -#define mod(x,y) (rb_funcall((x), '%', 1, (y))) - -/* strftime --- produce formatted time */ - -static size_t -date_strftime_with_tmx(char *s, size_t maxsize, const char *format, - const struct tmx *tmx) -{ - char *endp = s + maxsize; - char *start = s; - const char *sp, *tp; - auto char tbuf[100]; - long off; - ptrdiff_t i; - int w; - int precision, flags, colons; - char padding; - enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E}; -#define BIT_OF(n) (1U<<(n)) - - /* various tables, useful in North America */ - static const char days_l[][10] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", - }; - static const char months_l[][10] = { - "January", "February", "March", "April", - "May", "June", "July", "August", "September", - "October", "November", "December", - }; - static const char ampm[][3] = { "AM", "PM", }; - - if (s == NULL || format == NULL || tmx == NULL || maxsize == 0) - return 0; - - /* quick check if we even need to bother */ - if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize) { - err: - errno = ERANGE; - return 0; - } - - for (; *format && s < endp - 1; format++) { -#define FLAG_FOUND() do { \ - if (precision > 0 || flags & (BIT_OF(LOCALE_E)|BIT_OF(LOCALE_O))) \ - goto unknown; \ - } while (0) -#define NEEDS(n) do if (s >= endp || (n) >= endp - s - 1) goto err; while (0) -#define FILL_PADDING(i) do { \ - if (!(flags & BIT_OF(LEFT)) && precision > (i)) { \ - NEEDS(precision); \ - memset(s, padding ? padding : ' ', precision - (i)); \ - s += precision - (i); \ - } \ - else { \ - NEEDS(i); \ - } \ -} while (0); -#define FMT(def_pad, def_prec, fmt, val) \ - do { \ - int l; \ - if (precision <= 0) precision = (def_prec); \ - if (flags & BIT_OF(LEFT)) precision = 1; \ - l = snprintf(s, endp - s, \ - ((padding == '0' || (!padding && (def_pad) == '0')) ? "%0*"fmt : "%*"fmt), \ - precision, (val)); \ - if (l < 0) goto err; \ - s += l; \ - } while (0) -#define STRFTIME(fmt) \ - do { \ - i = date_strftime_with_tmx(s, endp - s, (fmt), tmx); \ - if (!i) return 0; \ - if (precision > i) {\ - if (start + maxsize < s + precision) { \ - errno = ERANGE; \ - return 0; \ - } \ - memmove(s + precision - i, s, i);\ - memset(s, padding ? padding : ' ', precision - i); \ - s += precision; \ - }\ - else s += i; \ - } while (0) -#define FMTV(def_pad, def_prec, fmt, val) \ - do { \ - VALUE tmp = (val); \ - if (FIXNUM_P(tmp)) { \ - FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \ - } \ - else { \ - VALUE args[2], result; \ - size_t l; \ - if (precision <= 0) precision = (def_prec); \ - if (flags & BIT_OF(LEFT)) precision = 1; \ - args[0] = INT2FIX(precision); \ - args[1] = (val); \ - if (padding == '0' || (!padding && (def_pad) == '0')) \ - result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \ - else \ - result = rb_str_format(2, args, rb_str_new2("%*"fmt)); \ - l = strlcpy(s, StringValueCStr(result), endp-s); \ - if ((size_t)(endp-s) <= l) \ - goto err; \ - s += l; \ - } \ - } while (0) - - if (*format != '%') { - *s++ = *format; - continue; - } - tp = tbuf; - sp = format; - precision = -1; - flags = 0; - padding = 0; - colons = 0; - again: - switch (*++format) { - case '\0': - format--; - goto unknown; - - case '%': - FILL_PADDING(1); - *s++ = '%'; - continue; - - case 'a': /* abbreviated weekday name */ - if (flags & BIT_OF(CHCASE)) { - flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); - flags |= BIT_OF(UPPER); - } - { - int wday = tmx_wday; - if (wday < 0 || wday > 6) - i = 1, tp = "?"; - else - i = 3, tp = days_l[wday]; - } - break; - - case 'A': /* full weekday name */ - if (flags & BIT_OF(CHCASE)) { - flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); - flags |= BIT_OF(UPPER); - } - { - int wday = tmx_wday; - if (wday < 0 || wday > 6) - i = 1, tp = "?"; - else - i = strlen(tp = days_l[wday]); - } - break; - -#ifdef SYSV_EXT - case 'h': /* abbreviated month name */ -#endif - case 'b': /* abbreviated month name */ - if (flags & BIT_OF(CHCASE)) { - flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); - flags |= BIT_OF(UPPER); - } - { - int mon = tmx_mon; - if (mon < 1 || mon > 12) - i = 1, tp = "?"; - else - i = 3, tp = months_l[mon-1]; - } - break; - - case 'B': /* full month name */ - if (flags & BIT_OF(CHCASE)) { - flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); - flags |= BIT_OF(UPPER); - } - { - int mon = tmx_mon; - if (mon < 1 || mon > 12) - i = 1, tp = "?"; - else - i = strlen(tp = months_l[mon-1]); - } - break; - - case 'c': /* appropriate date and time representation */ - STRFTIME("%a %b %e %H:%M:%S %Y"); - continue; - - case 'd': /* day of the month, 01 - 31 */ - i = range(1, tmx_mday, 31); - FMT('0', 2, "d", (int)i); - continue; - - case 'H': /* hour, 24-hour clock, 00 - 23 */ - i = range(0, tmx_hour, 23); - FMT('0', 2, "d", (int)i); - continue; - - case 'I': /* hour, 12-hour clock, 01 - 12 */ - i = range(0, tmx_hour, 23); - if (i == 0) - i = 12; - else if (i > 12) - i -= 12; - FMT('0', 2, "d", (int)i); - continue; - - case 'j': /* day of the year, 001 - 366 */ - FMT('0', 3, "d", tmx_yday); - continue; - - case 'm': /* month, 01 - 12 */ - i = range(1, tmx_mon, 12); - FMT('0', 2, "d", (int)i); - continue; - - case 'M': /* minute, 00 - 59 */ - i = range(0, tmx_min, 59); - FMT('0', 2, "d", (int)i); - continue; - - case 'p': /* AM or PM based on 12-hour clock */ - case 'P': /* am or pm based on 12-hour clock */ - if ((*format == 'p' && (flags & BIT_OF(CHCASE))) || - (*format == 'P' && !(flags & (BIT_OF(CHCASE)|BIT_OF(UPPER))))) { - flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE)); - flags |= BIT_OF(LOWER); - } - i = range(0, tmx_hour, 23); - if (i < 12) - tp = ampm[0]; - else - tp = ampm[1]; - i = 2; - break; - - case 's': - FMTV('0', 1, "d", tmx_secs); - continue; - - case 'Q': - FMTV('0', 1, "d", tmx_msecs); - continue; - - case 'S': /* second, 00 - 59 */ - i = range(0, tmx_sec, 59); - FMT('0', 2, "d", (int)i); - continue; - - case 'U': /* week of year, Sunday is first day of week */ - FMT('0', 2, "d", tmx_wnum0); - continue; - - case 'w': /* weekday, Sunday == 0, 0 - 6 */ - i = range(0, tmx_wday, 6); - FMT('0', 1, "d", (int)i); - continue; - - case 'W': /* week of year, Monday is first day of week */ - FMT('0', 2, "d", tmx_wnum1); - continue; - - case 'x': /* appropriate date representation */ - STRFTIME("%m/%d/%y"); - continue; - - case 'X': /* appropriate time representation */ - STRFTIME("%H:%M:%S"); - continue; - - case 'y': /* year without a century, 00 - 99 */ - i = NUM2INT(mod(tmx_year, INT2FIX(100))); - FMT('0', 2, "d", (int)i); - continue; - - case 'Y': /* year with century */ - { - VALUE year = tmx_year; - if (FIXNUM_P(year)) { - long y = FIX2LONG(year); - FMT('0', 0 <= y ? 4 : 5, "ld", y); - } - else { - FMTV('0', 4, "d", year); - } - } - continue; - -#ifdef MAILHEADER_EXT - case 'z': /* time zone offset east of GMT e.g. -0600 */ - { - long aoff; - int hl, hw; - - off = NUM2LONG(rb_funcall(tmx_offset, rb_intern("round"), 0)); - - aoff = off; - if (aoff < 0) - aoff = -off; - - if ((aoff / 3600) < 10) - hl = 1; - else - hl = 2; - hw = 2; - if (flags & BIT_OF(LEFT) && hl == 1) - hw = 1; - - switch (colons) { - case 0: /* %z -> +hhmm */ - precision = precision <= (3 + hw) ? hw : precision-3; - NEEDS(precision + 3); - break; - - case 1: /* %:z -> +hh:mm */ - precision = precision <= (4 + hw) ? hw : precision-4; - NEEDS(precision + 4); - break; - - case 2: /* %::z -> +hh:mm:ss */ - precision = precision <= (7 + hw) ? hw : precision-7; - NEEDS(precision + 7); - break; - - case 3: /* %:::z -> +hh[:mm[:ss]] */ - { - if (aoff % 3600 == 0) { - precision = precision <= (1 + hw) ? hw : precision-1; - NEEDS(precision + 3); - } - else if (aoff % 60 == 0) { - precision = precision <= (4 + hw) ? hw : precision-4; - NEEDS(precision + 4); - } - else { - precision = precision <= (7 + hw) ? hw : precision-7; - NEEDS(precision + 7); - } - } - break; - - default: - format--; - goto unknown; - } - if (padding == ' ' && precision > hl) { - i = snprintf(s, endp - s, "%*s", precision - hl, ""); - precision = hl; - if (i < 0) goto err; - s += i; - } - if (off < 0) { - off = -off; - *s++ = '-'; - } else { - *s++ = '+'; - } - i = snprintf(s, endp - s, "%.*ld", precision, off / 3600); - if (i < 0) goto err; - s += i; - off = off % 3600; - if (colons == 3 && off == 0) - continue; - if (1 <= colons) - *s++ = ':'; - i = snprintf(s, endp - s, "%02d", (int)(off / 60)); - if (i < 0) goto err; - s += i; - off = off % 60; - if (colons == 3 && off == 0) - continue; - if (2 <= colons) { - *s++ = ':'; - i = snprintf(s, endp - s, "%02d", (int)off); - if (i < 0) goto err; - s += i; - } - } - continue; -#endif /* MAILHEADER_EXT */ - - case 'Z': /* time zone name or abbreviation */ - if (flags & BIT_OF(CHCASE)) { - flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE)); - flags |= BIT_OF(LOWER); - } - { - char *zone = tmx_zone; - if (zone == NULL) - tp = ""; - else - tp = zone; - i = strlen(tp); - } - break; - -#ifdef SYSV_EXT - case 'n': /* same as \n */ - FILL_PADDING(1); - *s++ = '\n'; - continue; - - case 't': /* same as \t */ - FILL_PADDING(1); - *s++ = '\t'; - continue; - - case 'D': /* date as %m/%d/%y */ - STRFTIME("%m/%d/%y"); - continue; - - case 'e': /* day of month, blank padded */ - FMT(' ', 2, "d", range(1, tmx_mday, 31)); - continue; - - case 'r': /* time as %I:%M:%S %p */ - STRFTIME("%I:%M:%S %p"); - continue; - - case 'R': /* time as %H:%M */ - STRFTIME("%H:%M"); - continue; - - case 'T': /* time as %H:%M:%S */ - STRFTIME("%H:%M:%S"); - continue; -#endif - -#ifdef SUNOS_EXT - case 'k': /* hour, 24-hour clock, blank pad */ - i = range(0, tmx_hour, 23); - FMT(' ', 2, "d", (int)i); - continue; - - case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */ - i = range(0, tmx_hour, 23); - if (i == 0) - i = 12; - else if (i > 12) - i -= 12; - FMT(' ', 2, "d", (int)i); - continue; -#endif - -#ifdef VMS_EXT - case 'v': /* date as dd-bbb-YYYY */ - STRFTIME("%e-%b-%Y"); - continue; -#endif - -#ifdef POSIX2_DATE - case 'C': - FMTV('0', 2, "d", div(tmx_year, INT2FIX(100))); - continue; - - case 'E': - /* POSIX locale extensions, ignored for now */ - flags |= BIT_OF(LOCALE_E); - if (*(format + 1) && strchr("cCxXyY", *(format + 1))) - goto again; - goto unknown; - case 'O': - /* POSIX locale extensions, ignored for now */ - flags |= BIT_OF(LOCALE_O); - if (*(format + 1) && strchr("deHImMSuUVwWy", - *(format + 1))) - goto again; - goto unknown; - case 'V': /* week of year according ISO 8601 */ - FMT('0', 2, "d", tmx_cweek); - continue; - - case 'u': - /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */ - FMT('0', 1, "d", tmx_cwday); - continue; -#endif /* POSIX2_DATE */ - -#ifdef ISO_DATE_EXT - case 'g': /* year of ISO week without a century */ - i = NUM2INT(mod(tmx_cwyear, INT2FIX(100))); - FMT('0', 2, "d", (int)i); - continue; - - case 'G': /* year of ISO week with century */ - { - VALUE year = tmx_cwyear; - if (FIXNUM_P(year)) { - long y = FIX2LONG(year); - FMT('0', 0 <= y ? 4 : 5, "ld", y); - } - else { - FMTV('0', 4, "d", year); - } - continue; - } - -#endif /* ISO_DATE_EXT */ - - case 'L': - w = 3; - goto subsec; - - case 'N': - /* - * fractional second digits. default is 9 digits - * (nanosecond). - * - * %3N millisecond (3 digits) - * %6N microsecond (6 digits) - * %9N nanosecond (9 digits) - */ - w = 9; - subsec: - if (precision <= 0) { - precision = w; - } - NEEDS(precision); - - { - VALUE subsec = tmx_sec_fraction; - int ww; - long n; - - ww = precision; - while (9 <= ww) { - subsec = mul(subsec, INT2FIX(1000000000)); - ww -= 9; - } - n = 1; - for (; 0 < ww; ww--) - n *= 10; - if (n != 1) - subsec = mul(subsec, INT2FIX(n)); - subsec = div(subsec, INT2FIX(1)); - - if (FIXNUM_P(subsec)) { - (void)snprintf(s, endp - s, "%0*ld", precision, FIX2LONG(subsec)); - s += precision; - } - else { - VALUE args[2], result; - args[0] = INT2FIX(precision); - args[1] = subsec; - result = rb_str_format(2, args, rb_str_new2("%0*d")); - (void)strlcpy(s, StringValueCStr(result), endp-s); - s += precision; - } - } - continue; - - case 'F': /* Equivalent to %Y-%m-%d */ - STRFTIME("%Y-%m-%d"); - continue; - case '+': - STRFTIME("%a %b %e %H:%M:%S %Z %Y"); - continue; - - case '-': - FLAG_FOUND(); - flags |= BIT_OF(LEFT); - padding = precision = 0; - goto again; - - case '^': - FLAG_FOUND(); - flags |= BIT_OF(UPPER); - goto again; - - case '#': - FLAG_FOUND(); - flags |= BIT_OF(CHCASE); - goto again; - - case '_': - FLAG_FOUND(); - padding = ' '; - goto again; - - case ':': - colons++; - goto again; - - case '0': - padding = '0'; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - char *e; - precision = (int)strtoul(format, &e, 10); - format = e - 1; - goto again; - } - - default: - unknown: - i = format - sp + 1; - tp = sp; - precision = -1; - flags = 0; - padding = 0; - colons = 0; - break; - } - if (i) { - FILL_PADDING(i); - memcpy(s, tp, i); - switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) { - case BIT_OF(UPPER): - do { - if (ISLOWER(*s)) *s = TOUPPER(*s); - } while (s++, --i); - break; - case BIT_OF(LOWER): - do { - if (ISUPPER(*s)) *s = TOLOWER(*s); - } while (s++, --i); - break; - default: - s += i; - break; - } - } - } - if (s >= endp) { - goto err; - } - if (*format == '\0') { - *s = '\0'; - return (s - start); - } else - return 0; -} - -size_t -date_strftime(char *s, size_t maxsize, const char *format, - const struct tmx *tmx) -{ - return date_strftime_with_tmx(s, maxsize, format, tmx); -} - -#if 0 -/* isleap --- is a year a leap year? */ - -#ifndef __STDC__ -static int -isleap(year) -long year; -#else -static int -isleap(long year) -#endif -{ - return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); -} - -static void -tmx2tm_noyear(const struct tmx *tmx, struct tm *result) -{ - struct tm tm; - - /* for isleap() in iso8601wknum. +100 is -1900 (mod 400). */ - tm.tm_year = FIX2INT(mod(tmx_year, INT2FIX(400))) + 100; - - tm.tm_mon = tmx_mon-1; - tm.tm_mday = tmx_mday; - tm.tm_hour = tmx_hour; - tm.tm_min = tmx_min; - tm.tm_sec = tmx_sec; - tm.tm_wday = tmx_wday; - tm.tm_yday = tmx_yday-1; - tm.tm_isdst = 0; -#if defined(HAVE_STRUCT_TM_TM_GMTOFF) - tm.tm_gmtoff = NUM2LONG(tmx_offset); -#endif -#if defined(HAVE_TM_ZONE) - tm.tm_zone = (char *)tmx_zone; -#endif - *result = tm; -} - -#ifdef POSIX2_DATE -/* iso8601wknum --- compute week number according to ISO 8601 */ - -#ifndef __STDC__ -static int -iso8601wknum(timeptr) -const struct tm *timeptr; -#else -static int -iso8601wknum(const struct tm *timeptr) -#endif -{ - /* - * From 1003.2: - * If the week (Monday to Sunday) containing January 1 - * has four or more days in the new year, then it is week 1; - * otherwise it is the highest numbered week of the previous - * year (52 or 53), and the next week is week 1. - * - * ADR: This means if Jan 1 was Monday through Thursday, - * it was week 1, otherwise week 52 or 53. - * - * XPG4 erroneously included POSIX.2 rationale text in the - * main body of the standard. Thus it requires week 53. - */ - - int weeknum, jan1day; - - /* get week number, Monday as first day of the week */ - weeknum = weeknumber(timeptr, 1); - - /* - * With thanks and tip of the hatlo to tml@tik.vtt.fi - * - * What day of the week does January 1 fall on? - * We know that - * (timeptr->tm_yday - jan1.tm_yday) MOD 7 == - * (timeptr->tm_wday - jan1.tm_wday) MOD 7 - * and that - * jan1.tm_yday == 0 - * and that - * timeptr->tm_wday MOD 7 == timeptr->tm_wday - * from which it follows that. . . - */ - jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7); - if (jan1day < 0) - jan1day += 7; - - /* - * If Jan 1 was a Monday through Thursday, it was in - * week 1. Otherwise it was last year's highest week, which is - * this year's week 0. - * - * What does that mean? - * If Jan 1 was Monday, the week number is exactly right, it can - * never be 0. - * If it was Tuesday through Thursday, the weeknumber is one - * less than it should be, so we add one. - * Otherwise, Friday, Saturday or Sunday, the week number is - * OK, but if it is 0, it needs to be 52 or 53. - */ - switch (jan1day) { - case 1: /* Monday */ - break; - case 2: /* Tuesday */ - case 3: /* Wednesday */ - case 4: /* Thursday */ - weeknum++; - break; - case 5: /* Friday */ - case 6: /* Saturday */ - case 0: /* Sunday */ - if (weeknum == 0) { -#ifdef USE_BROKEN_XPG4 - /* XPG4 (as of March 1994) says 53 unconditionally */ - weeknum = 53; -#else - /* get week number of last week of last year */ - struct tm dec31ly; /* 12/31 last year */ - dec31ly = *timeptr; - dec31ly.tm_year--; - dec31ly.tm_mon = 11; - dec31ly.tm_mday = 31; - dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1; - dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900L); - weeknum = iso8601wknum(& dec31ly); -#endif - } - break; - } - - if (timeptr->tm_mon == 11) { - /* - * The last week of the year - * can be in week 1 of next year. - * Sigh. - * - * This can only happen if - * M T W - * 29 30 31 - * 30 31 - * 31 - */ - int wday, mday; - - wday = timeptr->tm_wday; - mday = timeptr->tm_mday; - if ( (wday == 1 && (mday >= 29 && mday <= 31)) - || (wday == 2 && (mday == 30 || mday == 31)) - || (wday == 3 && mday == 31)) - weeknum = 1; - } - - return weeknum; -} - -static int -iso8601wknum_v(const struct tmx *tmx) -{ - struct tm tm; - tmx2tm_noyear(tmx, &tm); - return iso8601wknum(&tm); -} - -#endif - -/* weeknumber --- figure how many weeks into the year */ - -/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */ - -#ifndef __STDC__ -static int -weeknumber(timeptr, firstweekday) -const struct tm *timeptr; -int firstweekday; -#else -static int -weeknumber(const struct tm *timeptr, int firstweekday) -#endif -{ - int wday = timeptr->tm_wday; - int ret; - - if (firstweekday == 1) { - if (wday == 0) /* sunday */ - wday = 6; - else - wday--; - } - ret = ((timeptr->tm_yday + 7 - wday) / 7); - if (ret < 0) - ret = 0; - return ret; -} - -static int -weeknumber_v(const struct tmx *tmx, int firstweekday) -{ - struct tm tm; - tmx2tm_noyear(tmx, &tm); - return weeknumber(&tm, firstweekday); -} -#endif - -#if 0 -/* ADR --- I'm loathe to mess with ado's code ... */ - -Date: Wed, 24 Apr 91 20:54:08 MDT -From: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK> -To: arnold@audiofax.com - -Hi Arnold, -in a process of fixing of strftime() in libraries on Atari ST I grabbed -some pieces of code from your own strftime. When doing that it came -to mind that your weeknumber() function compiles a little bit nicer -in the following form: -/* - * firstweekday is 0 if starting in Sunday, non-zero if in Monday - */ -{ - return (timeptr->tm_yday - timeptr->tm_wday + - (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7; -} -How nicer it depends on a compiler, of course, but always a tiny bit. - - Cheers, - Michal - ntomczak@vm.ucs.ualberta.ca -#endif - -#ifdef TEST_STRFTIME - -/* - * NAME: - * tst - * - * SYNOPSIS: - * tst - * - * DESCRIPTION: - * "tst" is a test driver for the function "strftime". - * - * OPTIONS: - * None. - * - * AUTHOR: - * Karl Vogel - * Control Data Systems, Inc. - * vogelke@c-17igp.wpafb.af.mil - * - * BUGS: - * None noticed yet. - * - * COMPILE: - * cc -o tst -DTEST_STRFTIME strftime.c - */ - -/* ADR: I reformatted this to my liking, and deleted some unneeded code. */ - -#ifndef NULL -#include <stdio.h> -#endif -#include <time.h> -#include <sys/time.h> -#include <string.h> - -#define MAXTIME 132 - -/* - * Array of time formats. - */ - -static char *array[] = -{ - "(%%A) full weekday name, var length (Sunday..Saturday) %A", - "(%%B) full month name, var length (January..December) %B", - "(%%C) Century %C", - "(%%D) date (%%m/%%d/%%y) %D", - "(%%E) Locale extensions (ignored) %E", - "(%%H) hour (24-hour clock, 00..23) %H", - "(%%I) hour (12-hour clock, 01..12) %I", - "(%%M) minute (00..59) %M", - "(%%O) Locale extensions (ignored) %O", - "(%%R) time, 24-hour (%%H:%%M) %R", - "(%%S) second (00..60) %S", - "(%%T) time, 24-hour (%%H:%%M:%%S) %T", - "(%%U) week of year, Sunday as first day of week (00..53) %U", - "(%%V) week of year according to ISO 8601 %V", - "(%%W) week of year, Monday as first day of week (00..53) %W", - "(%%X) appropriate locale time representation (%H:%M:%S) %X", - "(%%Y) year with century (1970...) %Y", - "(%%Z) timezone (EDT), or blank if timezone not determinable %Z", - "(%%a) locale's abbreviated weekday name (Sun..Sat) %a", - "(%%b) locale's abbreviated month name (Jan..Dec) %b", - "(%%c) full date (Sat Nov 4 12:02:33 1989)%n%t%t%t %c", - "(%%d) day of the month (01..31) %d", - "(%%e) day of the month, blank-padded ( 1..31) %e", - "(%%h) should be same as (%%b) %h", - "(%%j) day of the year (001..366) %j", - "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k", - "(%%l) hour, 12-hour clock, blank pad ( 1..12) %l", - "(%%m) month (01..12) %m", - "(%%p) locale's AM or PM based on 12-hour clock %p", - "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r", - "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u", - "(%%v) VMS date (dd-bbb-YYYY) %v", - "(%%w) day of week (0..6, Sunday == 0) %w", - "(%%x) appropriate locale date representation %x", - "(%%y) last two digits of year (00..99) %y", - "(%%z) timezone offset east of GMT as HHMM (e.g. -0500) %z", - (char *) NULL -}; - -/* main routine. */ - -int -main(argc, argv) -int argc; -char **argv; -{ - char *next; - char string[MAXTIME]; - - int k; - int length; - - struct tm *tm; - - time_t clock; - - /* Call the function. */ - - clock = time(NULL); - tm = localtime(&clock); - - for (k = 0; next = array[k]; k++) { - length = strftime(string, MAXTIME, next, tm); - printf("%s\n", string); - } - - exit(0); -} -#endif /* TEST_STRFTIME */ diff --git a/ruby_1_9_3/ext/date/date_strptime.c b/ruby_1_9_3/ext/date/date_strptime.c deleted file mode 100644 index eaec8e716b..0000000000 --- a/ruby_1_9_3/ext/date/date_strptime.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - date_strptime.c: Coded by Tadayoshi Funaba 2011,2012 -*/ - -#include "ruby.h" -#include "ruby/encoding.h" -#include "ruby/re.h" -#include <ctype.h> - -static const char *day_names[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", - "Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat" -}; - -static const char *month_names[] = { - "January", "February", "March", "April", - "May", "June", "July", "August", "September", - "October", "November", "December", - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static const char *merid_names[] = { - "am", "pm", - "a.m.", "p.m." -}; - -static const char *extz_pats[] = { - ":z", - "::z", - ":::z" -}; - -#define sizeof_array(o) (sizeof o / sizeof o[0]) - -#define f_negate(x) rb_funcall(x, rb_intern("-@"), 0) -#define f_add(x,y) rb_funcall(x, '+', 1, y) -#define f_sub(x,y) rb_funcall(x, '-', 1, y) -#define f_mul(x,y) rb_funcall(x, '*', 1, y) -#define f_div(x,y) rb_funcall(x, '/', 1, y) -#define f_idiv(x,y) rb_funcall(x, rb_intern("div"), 1, y) -#define f_mod(x,y) rb_funcall(x, '%', 1, y) -#define f_expt(x,y) rb_funcall(x, rb_intern("**"), 1, y) - -#define f_lt_p(x,y) rb_funcall(x, '<', 1, y) -#define f_gt_p(x,y) rb_funcall(x, '>', 1, y) -#define f_le_p(x,y) rb_funcall(x, rb_intern("<="), 1, y) -#define f_ge_p(x,y) rb_funcall(x, rb_intern(">="), 1, y) - -#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s) -#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i) -#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i) - -#define issign(c) ((c) == '-' || (c) == '+') - -static int -num_pattern_p(const char *s) -{ - if (isdigit(*s)) - return 1; - if (*s == '%') { - s++; - if (*s == 'E' || *s == 'O') - s++; - if (*s && - (strchr("CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy", *s) || isdigit(*s))) - return 1; - } - return 0; -} - -#define NUM_PATTERN_P() num_pattern_p(&fmt[fi + 1]) - -static long -read_digits(const char *s, VALUE *n, size_t width) -{ - size_t l; - - l = strspn(s, "0123456789"); - - if (l == 0) - return 0; - - if (width < l) - l = width; - - if ((4 * l * sizeof(char)) <= (sizeof(long)*CHAR_BIT)) { - const char *os = s; - long v; - - v = 0; - while ((size_t)(s - os) < l) { - v *= 10; - v += *s - '0'; - s++; - } - if (os == s) - return 0; - *n = LONG2NUM(v); - return l; - } - else { - char *s2 = ALLOCA_N(char, l + 1); - memcpy(s2, s, l); - s2[l] = '\0'; - *n = rb_cstr_to_inum(s2, 10, 0); - return l; - } -} - -#define set_hash(k,v) rb_hash_aset(hash, ID2SYM(rb_intern(k)), v) -#define ref_hash(k) rb_hash_aref(hash, ID2SYM(rb_intern(k))) -#define del_hash(k) rb_hash_delete(hash, ID2SYM(rb_intern(k))) - -#define fail() \ -{ \ - set_hash("_fail", Qtrue); \ - return 0; \ -} - -#define fail_p() (!NIL_P(ref_hash("_fail"))) - -#define READ_DIGITS(n,w) \ -{ \ - size_t l; \ - l = read_digits(&str[si], &n, w); \ - if (l == 0) \ - fail(); \ - si += l; \ -} - -#define READ_DIGITS_MAX(n) READ_DIGITS(n, LONG_MAX) - -static int -valid_range_p(VALUE v, int a, int b) -{ - if (FIXNUM_P(v)) { - int vi = FIX2INT(v); - return !(vi < a || vi > b); - } - return !(f_lt_p(v, INT2NUM(a)) || f_gt_p(v, INT2NUM(b))); -} - -#define recur(fmt) \ -{ \ - size_t l; \ - l = date__strptime_internal(&str[si], slen - si, \ - fmt, sizeof fmt - 1, hash); \ - if (fail_p()) \ - return 0; \ - si += l; \ -} - -VALUE date_zone_to_diff(VALUE); - -static size_t -date__strptime_internal(const char *str, size_t slen, - const char *fmt, size_t flen, VALUE hash) -{ - size_t si, fi; - int c; - - si = fi = 0; - - while (fi < flen) { - - switch (fmt[fi]) { - case '%': - - again: - fi++; - c = fmt[fi]; - - switch (c) { - case 'E': - if (fmt[fi + 1] && strchr("cCxXyY", fmt[fi + 1])) - goto again; - fi--; - goto ordinal; - case 'O': - if (fmt[fi + 1] && strchr("deHImMSuUVwWy", fmt[fi + 1])) - goto again; - fi--; - goto ordinal; - case ':': - { - int i; - - for (i = 0; i < (int)sizeof_array(extz_pats); i++) - if (strncmp(extz_pats[i], &fmt[fi], - strlen(extz_pats[i])) == 0) { - fi += i; - goto again; - } - fail(); - } - - case 'A': - case 'a': - { - int i; - - for (i = 0; i < (int)sizeof_array(day_names); i++) { - size_t l = strlen(day_names[i]); - if (strncasecmp(day_names[i], &str[si], l) == 0) { - si += l; - set_hash("wday", INT2FIX(i % 7)); - goto matched; - } - } - fail(); - } - case 'B': - case 'b': - case 'h': - { - int i; - - for (i = 0; i < (int)sizeof_array(month_names); i++) { - size_t l = strlen(month_names[i]); - if (strncasecmp(month_names[i], &str[si], l) == 0) { - si += l; - set_hash("mon", INT2FIX((i % 12) + 1)); - goto matched; - } - } - fail(); - } - - case 'C': - { - VALUE n; - - if (NUM_PATTERN_P()) - READ_DIGITS(n, 2) - else - READ_DIGITS_MAX(n) - set_hash("_cent", n); - goto matched; - } - - case 'c': - recur("%a %b %e %H:%M:%S %Y"); - goto matched; - - case 'D': - recur("%m/%d/%y"); - goto matched; - - case 'd': - case 'e': - { - VALUE n; - - if (str[si] == ' ') { - si++; - READ_DIGITS(n, 1); - } else { - READ_DIGITS(n, 2); - } - if (!valid_range_p(n, 1, 31)) - fail(); - set_hash("mday", n); - goto matched; - } - - case 'F': - recur("%Y-%m-%d"); - goto matched; - - case 'G': - { - VALUE n; - - if (NUM_PATTERN_P()) - READ_DIGITS(n, 4) - else - READ_DIGITS_MAX(n) - set_hash("cwyear", n); - goto matched; - } - - case 'g': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 0, 99)) - fail(); - set_hash("cwyear",n); - set_hash("_cent", - INT2FIX(f_ge_p(n, INT2FIX(69)) ? 19 : 20)); - goto matched; - } - - case 'H': - case 'k': - { - VALUE n; - - if (str[si] == ' ') { - si++; - READ_DIGITS(n, 1); - } else { - READ_DIGITS(n, 2); - } - if (!valid_range_p(n, 0, 24)) - fail(); - set_hash("hour", n); - goto matched; - } - - case 'I': - case 'l': - { - VALUE n; - - if (str[si] == ' ') { - si++; - READ_DIGITS(n, 1); - } else { - READ_DIGITS(n, 2); - } - if (!valid_range_p(n, 1, 12)) - fail(); - set_hash("hour", n); - goto matched; - } - - case 'j': - { - VALUE n; - - READ_DIGITS(n, 3); - if (!valid_range_p(n, 1, 366)) - fail(); - set_hash("yday", n); - goto matched; - } - - case 'L': - case 'N': - { - VALUE n; - int sign = 1; - size_t osi; - - if (issign(str[si])) { - if (str[si] == '-') - sign = -1; - si++; - } - osi = si; - if (NUM_PATTERN_P()) - READ_DIGITS(n, c == 'L' ? 3 : 9) - else - READ_DIGITS_MAX(n) - if (sign == -1) - n = f_negate(n); - set_hash("sec_fraction", - rb_rational_new2(n, - f_expt(INT2FIX(10), - ULONG2NUM(si - osi)))); - goto matched; - } - - case 'M': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 0, 59)) - fail(); - set_hash("min", n); - goto matched; - } - - case 'm': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 1, 12)) - fail(); - set_hash("mon", n); - goto matched; - } - - case 'n': - case 't': - recur(" "); - goto matched; - - case 'P': - case 'p': - { - int i; - - for (i = 0; i < 4; i++) { - size_t l = strlen(merid_names[i]); - if (strncasecmp(merid_names[i], &str[si], l) == 0) { - si += l; - set_hash("_merid", INT2FIX((i % 2) == 0 ? 0 : 12)); - goto matched; - } - } - fail(); - } - - case 'Q': - { - VALUE n; - int sign = 1; - - if (str[si] == '-') { - sign = -1; - si++; - } - READ_DIGITS_MAX(n); - if (sign == -1) - n = f_negate(n); - set_hash("seconds", - rb_rational_new2(n, - f_expt(INT2FIX(10), - INT2FIX(3)))); - goto matched; - } - - case 'R': - recur("%H:%M"); - goto matched; - - case 'r': - recur("%I:%M:%S %p"); - goto matched; - - case 'S': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 0, 60)) - fail(); - set_hash("sec", n); - goto matched; - } - - case 's': - { - VALUE n; - int sign = 1; - - if (str[si] == '-') { - sign = -1; - si++; - } - READ_DIGITS_MAX(n); - if (sign == -1) - n = f_negate(n); - set_hash("seconds", n); - goto matched; - } - - case 'T': - recur("%H:%M:%S"); - goto matched; - - case 'U': - case 'W': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 0, 53)) - fail(); - set_hash(c == 'U' ? "wnum0" : "wnum1", n); - goto matched; - } - - case 'u': - { - VALUE n; - - READ_DIGITS(n, 1); - if (!valid_range_p(n, 1, 7)) - fail(); - set_hash("cwday", n); - goto matched; - } - - case 'V': - { - VALUE n; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 1, 53)) - fail(); - set_hash("cweek", n); - goto matched; - } - - case 'v': - recur("%e-%b-%Y"); - goto matched; - - case 'w': - { - VALUE n; - - READ_DIGITS(n, 1); - if (!valid_range_p(n, 0, 6)) - fail(); - set_hash("wday", n); - goto matched; - } - - case 'X': - recur("%H:%M:%S"); - goto matched; - - case 'x': - recur("%m/%d/%y"); - goto matched; - - case 'Y': - { - VALUE n; - int sign = 1; - - if (issign(str[si])) { - if (str[si] == '-') - sign = -1; - si++; - } - if (NUM_PATTERN_P()) - READ_DIGITS(n, 4) - else - READ_DIGITS_MAX(n) - if (sign == -1) - n = f_negate(n); - set_hash("year", n); - goto matched; - } - - case 'y': - { - VALUE n; - int sign = 1; - - READ_DIGITS(n, 2); - if (!valid_range_p(n, 0, 99)) - fail(); - if (sign == -1) - n = f_negate(n); - set_hash("year", n); - set_hash("_cent", - INT2FIX(f_ge_p(n, INT2FIX(69)) ? 19 : 20)); - goto matched; - } - - case 'Z': - case 'z': - { - static const char pat_source[] = - "\\A(" - "(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?" - "|[[:alpha:].\\s]+(?:standard|daylight)\\s+time\\b" - "|[[:alpha:]]+(?:\\s+dst)?\\b" - ")"; - static VALUE pat = Qnil; - VALUE m, b; - - if (NIL_P(pat)) { - pat = rb_reg_new(pat_source, sizeof pat_source - 1, - ONIG_OPTION_IGNORECASE); - rb_gc_register_mark_object(pat); - } - - b = rb_backref_get(); - rb_match_busy(b); - m = f_match(pat, rb_usascii_str_new2(&str[si])); - - if (!NIL_P(m)) { - VALUE s, l, o; - - s = rb_reg_nth_match(1, m); - l = f_end(m, INT2FIX(0)); - o = date_zone_to_diff(s); - si += NUM2LONG(l); - set_hash("zone", s); - set_hash("offset", o); - rb_backref_set(b); - goto matched; - } - rb_backref_set(b); - fail(); - } - - case '%': - if (str[si] != '%') - fail(); - si++; - goto matched; - - case '+': - recur("%a %b %e %H:%M:%S %Z %Y"); - goto matched; - - default: - if (str[si] != '%') - fail(); - si++; - if (fi < flen) - if (str[si] != fmt[fi]) - fail(); - si++; - goto matched; - } - case ' ': - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - while (isspace(str[si])) - si++; - fi++; - break; - default: - ordinal: - if (str[si] != fmt[fi]) - fail(); - si++; - fi++; - break; - matched: - fi++; - break; - } - } - - return si; -} - -VALUE -date__strptime(const char *str, size_t slen, - const char *fmt, size_t flen, VALUE hash) -{ - size_t si; - VALUE cent, merid; - - si = date__strptime_internal(str, slen, fmt, flen, hash); - - if (slen > si) { - VALUE s; - - s = rb_usascii_str_new(&str[si], slen - si); - set_hash("leftover", s); - } - - if (fail_p()) - return Qnil; - - cent = ref_hash("_cent"); - if (!NIL_P(cent)) { - VALUE year; - - year = ref_hash("cwyear"); - if (!NIL_P(year)) - set_hash("cwyear", f_add(year, f_mul(cent, INT2FIX(100)))); - year = ref_hash("year"); - if (!NIL_P(year)) - set_hash("year", f_add(year, f_mul(cent, INT2FIX(100)))); - del_hash("_cent"); - } - - merid = ref_hash("_merid"); - if (!NIL_P(merid)) { - VALUE hour; - - hour = ref_hash("hour"); - if (!NIL_P(hour)) { - hour = f_mod(hour, INT2FIX(12)); - set_hash("hour", f_add(hour, merid)); - } - del_hash("_merid"); - } - - return hash; -} - -/* -Local variables: -c-file-style: "ruby" -End: -*/ diff --git a/ruby_1_9_3/ext/date/date_tmx.h b/ruby_1_9_3/ext/date/date_tmx.h deleted file mode 100644 index 0e56c9b4f0..0000000000 --- a/ruby_1_9_3/ext/date/date_tmx.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef DATE_TMX_H -#define DATE_TMX_H - -struct tmx_funcs { - VALUE (*year)(void *dat); - int (*yday)(void *dat); - int (*mon)(void *dat); - int (*mday)(void *dat); - VALUE (*cwyear)(void *dat); - int (*cweek)(void *dat); - int (*cwday)(void *dat); - int (*wnum0)(void *dat); - int (*wnum1)(void *dat); - int (*wday)(void *dat); - int (*hour)(void *dat); - int (*min)(void *dat); - int (*sec)(void *dat); - VALUE (*sec_fraction)(void *dat); - VALUE (*secs)(void *dat); - VALUE (*msecs)(void *dat); - VALUE (*offset)(void *dat); - char *(*zone)(void *dat); -}; -struct tmx { - void *dat; - struct tmx_funcs *funcs; -}; - -#define tmx_attr(x) (tmx->funcs->x)(tmx->dat) - -#define tmx_year tmx_attr(year) -#define tmx_yday tmx_attr(yday) -#define tmx_mon tmx_attr(mon) -#define tmx_mday tmx_attr(mday) -#define tmx_cwyear tmx_attr(cwyear) -#define tmx_cweek tmx_attr(cweek) -#define tmx_cwday tmx_attr(cwday) -#define tmx_wnum0 tmx_attr(wnum0) -#define tmx_wnum1 tmx_attr(wnum1) -#define tmx_wday tmx_attr(wday) -#define tmx_hour tmx_attr(hour) -#define tmx_min tmx_attr(min) -#define tmx_sec tmx_attr(sec) -#define tmx_sec_fraction tmx_attr(sec_fraction) -#define tmx_secs tmx_attr(secs) -#define tmx_msecs tmx_attr(msecs) -#define tmx_offset tmx_attr(offset) -#define tmx_zone tmx_attr(zone) - -#endif - -/* -Local variables: -c-file-style: "ruby" -End: -*/ diff --git a/ruby_1_9_3/ext/date/depend b/ruby_1_9_3/ext/date/depend deleted file mode 100644 index 7e5d62e79d..0000000000 --- a/ruby_1_9_3/ext/date/depend +++ /dev/null @@ -1,2 +0,0 @@ -date_core.o: date_tmx.h -date_strftime.o: date_tmx.h diff --git a/ruby_1_9_3/ext/date/extconf.rb b/ruby_1_9_3/ext/date/extconf.rb deleted file mode 100644 index 9f7d3e8f0b..0000000000 --- a/ruby_1_9_3/ext/date/extconf.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'mkmf' -create_makefile('date_core') diff --git a/ruby_1_9_3/ext/date/lib/date.rb b/ruby_1_9_3/ext/date/lib/date.rb deleted file mode 100644 index d235d76e6f..0000000000 --- a/ruby_1_9_3/ext/date/lib/date.rb +++ /dev/null @@ -1,61 +0,0 @@ -# date.rb: Written by Tadayoshi Funaba 1998-2011 - -require 'date_core' -require 'date/format' - -class Date - - class Infinity < Numeric # :nodoc: - - include Comparable - - def initialize(d=1) @d = d <=> 0 end - - def d() @d end - - protected :d - - def zero? () false end - def finite? () false end - def infinite? () d.nonzero? end - def nan? () d.zero? end - - def abs() self.class.new end - - def -@ () self.class.new(-d) end - def +@ () self.class.new(+d) end - - def <=> (other) - case other - when Infinity; return d <=> other.d - when Numeric; return d - else - begin - l, r = other.coerce(self) - return l <=> r - rescue NoMethodError - end - end - nil - end - - def coerce(other) - case other - when Numeric; return -d, d - else - super - end - end - - def to_f - return 0 if @d == 0 - if @d > 0 - Float::INFINITY - else - -Float::INFINITY - end - end - - end - -end diff --git a/ruby_1_9_3/ext/date/lib/date/format.rb b/ruby_1_9_3/ext/date/lib/date/format.rb deleted file mode 100644 index 892e7aacaa..0000000000 --- a/ruby_1_9_3/ext/date/lib/date/format.rb +++ /dev/null @@ -1 +0,0 @@ -# format.rb: Written by Tadayoshi Funaba 1999-2011 |