summaryrefslogtreecommitdiff
path: root/ext/date/date_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/date/date_core.c')
-rw-r--r--ext/date/date_core.c6575
1 files changed, 6104 insertions, 471 deletions
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index b6e2688299..12c393515c 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -10,21 +10,26 @@
#define NDEBUG
#include <assert.h>
+/* #define FORCE_RIGHT */
+
#ifdef RUBY_EXTCONF_H
#include RUBY_EXTCONF_H
#endif
-#define LIGHT_MODE (1 << 0)
-#define HAVE_JD (1 << 1)
-#define HAVE_DF (1 << 2)
-#define HAVE_CIVIL (1 << 3)
-#define HAVE_TIME (1 << 4)
+#define LIGHT_MODE (1 << 0)
+#define HAVE_JD (1 << 1)
+#define HAVE_DF (1 << 2)
+#define HAVE_CIVIL (1 << 3)
+#define HAVE_TIME (1 << 4)
+#define DATETIME_OBJ (1 << 7)
#define light_mode_p(x) ((x)->flags & LIGHT_MODE)
#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 datetime_obj_p(x) ((x)->flags & DATETIME_OBJ)
+#define date_obj_p(x) (!datetime_obj_p(x))
#define MIN_YEAR -4713
#define MAX_YEAR 1000000
@@ -40,15 +45,10 @@
#define JULIAN (NUM2DBL(rb_const_get(rb_cFloat, rb_intern("INFINITY"))))
#define GREGORIAN (-NUM2DBL(rb_const_get(rb_cFloat, rb_intern("INFINITY"))))
+#define MINUTE_IN_SECONDS 60
+#define HOUR_IN_SECONDS 3600
#define DAY_IN_SECONDS 86400
#define SECOND_IN_NANOSECONDS 1000000000
-#if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
-#define DAY_IN_NANOSECONDS LONG2NUM((long)DAY_IN_SECONDS * SECOND_IN_NANOSECONDS)
-#elif defined HAVE_LONG_LONG
-#define DAY_IN_NANOSECONDS LL2NUM((LONG_LONG)DAY_IN_SECONDS * SECOND_IN_NANOSECONDS)
-#else
-#define DAY_IN_NANOSECONDS f_mul(INT2FIX(DAY_IN_SECONDS), INT2FIX(SECOND_IN_NANOSECONDS))
-#endif
/* copied from time.c */
#define NDIV(x,y) (-(-((x)+1)/(y))-1)
@@ -106,33 +106,43 @@ union DateTimeData
#define get_d1(x)\
union DateData *dat;\
- Data_Get_Struct(x, union DateData, dat)
+ Data_Get_Struct(x, union DateData, dat);\
+ assert(date_obj_p(dat))
#define get_d2(x,y)\
union DateData *adat, *bdat;\
Data_Get_Struct(x, union DateData, adat);\
- Data_Get_Struct(y, union DateData, bdat)
+ Data_Get_Struct(y, union DateData, bdat);\
+ assert(date_obj_p(adat));\
+ assert(date_obj_p(bdat))
#define get_d1_dt1(x,y)\
union DateData *adat;\
union DateTimeData *bdat;\
Data_Get_Struct(x, union DateData, adat);\
- Data_Get_Struct(y, union DateTimeData, bdat)
+ Data_Get_Struct(y, union DateTimeData, bdat)\
+ assert(date_obj_p(adat));\
+ assert(datetime_obj_p(bdat))
#define get_dt1(x)\
union DateTimeData *dat;\
- Data_Get_Struct(x, union DateTimeData, dat)
+ Data_Get_Struct(x, union DateTimeData, dat);\
+ assert(datetime_obj_p(dat))
#define get_dt2(x,y)\
union DateTimeData *adat, *bdat;\
Data_Get_Struct(x, union DateTimeData, adat);\
- Data_Get_Struct(y, union DateTimeData, bdat)
+ Data_Get_Struct(y, union DateTimeData, bdat);\
+ assert(datetime_obj_p(adat));\
+ assert(datetime_obj_p(bdat))
#define get_dt1_d1(x,y)\
union DateTimeData *adat;\
union DateData *bdat;\
Data_Get_Struct(x, union DateTimeData, adat);\
- Data_Get_Struct(y, union DateData, bdat)
+ Data_Get_Struct(y, union DateData, bdat);\
+ assert(datetime_obj_p(adat));\
+ assert(date_obj_p(bdat))
#define get_dt2_cast(x,y)\
union DateData *atmp, *btmp;\
@@ -152,7 +162,7 @@ union DateTimeData
abuf.l.hour = 0;\
abuf.l.min = 0;\
abuf.l.sec = 0;\
- abuf.flags = HAVE_DF | HAVE_TIME | atmp->l.flags;\
+ abuf.flags = HAVE_DF | HAVE_TIME | DATETIME_OBJ | atmp->l.flags;\
adat = &abuf;\
}\
if (k_datetime_p(y))\
@@ -170,29 +180,614 @@ union DateTimeData
bbuf.l.hour = 0;\
bbuf.l.min = 0;\
bbuf.l.sec = 0;\
- bbuf.flags = HAVE_DF | HAVE_TIME | btmp->l.flags;\
+ bbuf.flags = HAVE_DF | HAVE_TIME | DATETIME_OBJ | btmp->l.flags;\
bdat = &bbuf;\
}
+#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 forward0(k,m) rb_funcall(k, rb_intern(m), 0)
-#define cforward0(m) forward0(klass, m)
-#define iforward0(m) forward0(self, m)
-#define forward1(k,m,a) rb_funcall(k, rb_intern(m), 1, a)
-#define iforward1(m,a) forward1(self, m, a)
-#define forwardv(k,m) rb_funcall2(k, rb_intern(m), argc, argv)
-#define cforwardv(m) forwardv(klass, m)
-#define iforwardv(m) forwardv(self, m)
-#define forwardop(k,m) rb_funcall(k, rb_intern(m), 1, other)
-#define iforwardop(m) forwardop(self, m)
+#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_add3(x,y,z) f_add(f_add(x, y), z)
+#define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
+
+#define f_cmp(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_eqeq_p(x,y) rb_funcall(x, rb_intern("=="), 1, y)
+#define f_equal_p(x,y) rb_funcall(x, rb_intern("==="), 1, y)
+#define f_zero_p(x) rb_funcall(x, rb_intern("zero?"), 0)
+#define f_negative_p(x) f_lt_p(x, INT2FIX(0))
+#define f_positive_p(x) (!f_negative_p(x))
+
+#define f_compact(x) rb_funcall(x, rb_intern("compact"), 0)
+
+#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)
+#define f_start(x) rb_funcall(x, rb_intern("start"), 0)
static VALUE cDate, cDateTime;
static VALUE rzero, rhalf, day_in_nanoseconds;
+/* right base */
+
+#define HALF_DAYS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(2))
+#define HOURS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(24))
+#define MINUTES_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(1440))
+#define SECONDS_IN_DAY rb_rational_new2(INT2FIX(1), INT2FIX(86400))
+#define MILLISECONDS_IN_DAY\
+ rb_rational_new2(INT2FIX(1), f_mul(INT2FIX(86400), INT2FIX(1000)))
+#define NANOSECONDS_IN_DAY\
+ rb_rational_new2(INT2FIX(1), f_mul(INT2FIX(86400), INT2FIX(1000000000)))
+#define MILLISECONDS_IN_SECOND rb_rational_new2(INT2FIX(1), INT2FIX(1000))
+#define NANOSECONDS_IN_SECOND rb_rational_new2(INT2FIX(1), INT2FIX(1000000000))
+
+#define MJD_EPOCH_IN_AJD\
+ rb_rational_new2(INT2FIX(4800001), INT2FIX(2)) /* 1858-11-17 */
+#define UNIX_EPOCH_IN_AJD\
+ rb_rational_new2(INT2FIX(4881175), INT2FIX(2)) /* 1970-01-01 */
+#define MJD_EPOCH_IN_CJD INT2FIX(2400001)
+#define UNIX_EPOCH_IN_CJD INT2FIX(2440588)
+#define LD_EPOCH_IN_CJD INT2FIX(2299160)
+
+static VALUE rt__valid_civil_p(VALUE, VALUE, VALUE, VALUE);
+
+static VALUE
+rt_find_fdoy(VALUE y, VALUE sg)
+{
+ int d;
+
+ for (d = 1; d < 31; d++) {
+ VALUE j = rt__valid_civil_p(y, INT2FIX(1), INT2FIX(d), sg);
+ if (!NIL_P(j))
+ return j;
+ }
+ return Qnil;
+}
+
+static VALUE
+rt_find_ldoy(VALUE y, VALUE sg)
+{
+ int i;
+
+ for (i = 0; i < 30; i++) {
+ VALUE j = rt__valid_civil_p(y, INT2FIX(12), INT2FIX(31 - i), sg);
+ if (!NIL_P(j))
+ return j;
+ }
+ return Qnil;
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_find_fdom(VALUE y, VALUE m, VALUE sg)
+{
+ int d;
+
+ for (d = 1; d < 31; d++) {
+ VALUE j = rt__valid_civil_p(y, m, INT2FIX(d), sg);
+ if (!NIL_P(j))
+ return j;
+ }
+ return Qnil;
+}
+#endif
+
+static VALUE
+rt_find_ldom(VALUE y, VALUE m, VALUE sg)
+{
+ int i;
+
+ for (i = 0; i < 30; i++) {
+ VALUE j = rt__valid_civil_p(y, m, INT2FIX(31 - i), sg);
+ if (!NIL_P(j))
+ return j;
+ }
+ return Qnil;
+}
+
+static VALUE
+rt_ordinal_to_jd(VALUE y, VALUE d, VALUE sg)
+{
+ return f_sub(f_add(rt_find_fdoy(y, sg), d), INT2FIX(1));
+}
+
+static VALUE rt_jd_to_civil(VALUE jd, VALUE sg);
+
+static VALUE
+rt_jd_to_ordinal(VALUE jd, VALUE sg)
+{
+ VALUE a, y, j, doy;
+
+ a = rt_jd_to_civil(jd, sg);
+ y = RARRAY_PTR(a)[0];
+ j = rt_find_fdoy(y, sg);
+ doy = f_add(f_sub(jd, j), INT2FIX(1));
+ return rb_assoc_new(y, doy);
+}
+
+static VALUE
+rt_civil_to_jd(VALUE y, VALUE m, VALUE d, VALUE sg)
+{
+ VALUE a, b, jd;
+
+ if (f_le_p(m, INT2FIX(2))) {
+ y = f_sub(y, INT2FIX(1));
+ m = f_add(m, INT2FIX(12));
+ }
+ a = f_floor(f_div(y, DBL2NUM(100.0)));
+ b = f_add(f_sub(INT2FIX(2), a), f_floor(f_div(a, DBL2NUM(4.0))));
+ jd = f_add3(f_floor(f_mul(DBL2NUM(365.25), f_add(y, INT2FIX(4716)))),
+ f_floor(f_mul(DBL2NUM(30.6001), f_add(m, INT2FIX(1)))),
+ f_sub(f_add(d, b), INT2FIX(1524)));
+ if (f_lt_p(jd, sg))
+ jd = f_sub(jd, b);
+ return jd;
+}
+
+static VALUE
+rt_jd_to_civil(VALUE jd, VALUE sg)
+{
+ VALUE a, x, b, c, d, e, dom, m, y;
+
+ if (f_lt_p(jd, sg))
+ a = jd;
+ else {
+ x = f_floor(f_div(f_sub(jd, DBL2NUM(1867216.25)), DBL2NUM(36524.25)));
+ a = f_sub(f_add3(jd, INT2FIX(1), x), f_floor(f_div(x, DBL2NUM(4.0))));
+ }
+ b = f_add(a, INT2FIX(1524));
+ c = f_floor(f_div(f_sub(b, DBL2NUM(122.1)), DBL2NUM(365.25)));
+ d = f_floor(f_mul(DBL2NUM(365.25), c));
+ e = f_floor(f_div(f_sub(b, d), DBL2NUM(30.6001)));
+ dom = f_sub3(b, d, f_floor(f_mul(DBL2NUM(30.6001), e)));
+ if (f_le_p(e, INT2FIX(13))) {
+ m = f_sub(e, INT2FIX(1));
+ y = f_sub(c, INT2FIX(4716));
+ }
+ else {
+ m = f_sub(e, INT2FIX(13));
+ y = f_sub(c, INT2FIX(4715));
+ }
+ return rb_ary_new3(3, y, m, dom);
+}
+
+static VALUE
+rt_commercial_to_jd(VALUE y, VALUE w, VALUE d, VALUE sg)
+{
+ VALUE j;
+
+ j = f_add(rt_find_fdoy(y, sg), INT2FIX(3));
+ return f_add3(f_sub(j, f_mod(j, INT2FIX(7))),
+ f_mul(INT2FIX(7), f_sub(w, INT2FIX(1))),
+ f_sub(d, INT2FIX(1)));
+}
+
+static VALUE
+rt_jd_to_commercial(VALUE jd, VALUE sg)
+{
+ VALUE t, a, j, y, w, d;
+
+ t = rt_jd_to_civil(f_sub(jd, INT2FIX(3)), sg);
+ a = RARRAY_PTR(t)[0];
+ j = rt_commercial_to_jd(f_add(a, INT2FIX(1)), INT2FIX(1), INT2FIX(1), sg);
+ if (f_ge_p(jd, j))
+ y = f_add(a, INT2FIX(1));
+ else {
+ j = rt_commercial_to_jd(a, INT2FIX(1), INT2FIX(1), sg);
+ y = a;
+ }
+ w = f_add(INT2FIX(1), f_idiv(f_sub(jd, j), INT2FIX(7)));
+ d = f_mod(f_add(jd, INT2FIX(1)), INT2FIX(7));
+ if (f_zero_p(d))
+ d = INT2FIX(7);
+ return rb_ary_new3(3, y, w, d);
+}
+
+static VALUE
+rt_weeknum_to_jd(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
+{
+ VALUE a;
+
+ a = f_add(rt_find_fdoy(y, sg), INT2FIX(6));
+ return f_add3(f_sub3(a,
+ f_mod(f_add(f_sub(a, f), INT2FIX(1)), INT2FIX(7)),
+ INT2FIX(7)),
+ f_mul(INT2FIX(7), w),
+ d);
+}
+
+static VALUE
+rt_jd_to_weeknum(VALUE jd, VALUE f, VALUE sg)
+{
+ VALUE t, y, d, a, w;
+
+ t = rt_jd_to_civil(jd, sg);
+ y = RARRAY_PTR(t)[0];
+ d = RARRAY_PTR(t)[2];
+ a = f_add(rt_find_fdoy(y, sg), INT2FIX(6));
+ t = f_add(f_sub(jd,
+ f_sub(a, f_mod(f_add(f_sub(a, f), INT2FIX(1)),
+ INT2FIX(7)))),
+ INT2FIX(7));
+ w = f_idiv(t, INT2FIX(7));
+ d = f_mod(t, INT2FIX(7));
+ return rb_ary_new3(3, y, w, d);
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_nth_kday_to_jd(VALUE y, VALUE m, VALUE n, VALUE k, VALUE sg)
+{
+ VALUE j;
+
+ if (f_gt_p(n, INT2FIX(0)))
+ j = f_sub(rt_find_fdom(y, m, sg), INT2FIX(1));
+ else
+ j = f_add(rt_find_ldom(y, m, sg), INT2FIX(7));
+ return f_add(f_sub(j,
+ f_mod(f_add(f_sub(j, k), INT2FIX(1)), INT2FIX(7))),
+ f_mul(INT2FIX(7), n));
+}
+
+static VALUE rt_jd_to_wday(VALUE);
+
+static VALUE
+rt_jd_to_nth_kday(VALUE jd, VALUE sg)
+{
+ VALUE t, y, m, n, k, j;
+
+ t = rt_jd_to_civil(jd, sg);
+ y = RARRAY_PTR(t)[0];
+ m = RARRAY_PTR(t)[1];
+ j = rt_find_fdom(y, m, sg);
+ n = f_add(f_idiv(f_sub(jd, j), INT2FIX(7)), INT2FIX(1));
+ k = rt_jd_to_wday(jd);
+ return rb_ary_new3(4, y, m, n, k);
+}
+#endif
+
+static VALUE
+rt_ajd_to_jd(VALUE ajd, VALUE of)
+{
+ VALUE t, jd, fr;
+
+ t = f_add3(ajd, of, HALF_DAYS_IN_DAY);
+ jd = f_idiv(t, INT2FIX(1));
+ fr = f_mod(t, INT2FIX(1));
+ return rb_assoc_new(jd, fr);
+}
+
+static VALUE
+rt_jd_to_ajd(VALUE jd, VALUE fr, VALUE of)
+{
+ return f_sub3(f_add(jd, fr), of, HALF_DAYS_IN_DAY);
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_day_fraction_to_time(VALUE fr)
+{
+ VALUE h, min, s, ss;
+
+ ss = f_idiv(fr, SECONDS_IN_DAY);
+ fr = f_mod(fr, SECONDS_IN_DAY);
+
+ h = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS));
+ ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS));
+
+ min = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS));
+ s = f_mod(ss, INT2FIX(MINUTE_IN_SECONDS));
+
+ return rb_ary_new3(4, h, min, s, f_mul(fr, INT2FIX(DAY_IN_SECONDS)));
+}
+#endif
+
+static VALUE
+rt_day_fraction_to_time_wo_sf(VALUE fr)
+{
+ VALUE h, min, s, ss;
+
+ ss = f_idiv(fr, SECONDS_IN_DAY);
+
+ h = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS));
+ ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS));
+
+ min = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS));
+ s = f_mod(ss, INT2FIX(MINUTE_IN_SECONDS));
+
+ return rb_ary_new3(3, h, min, s);
+}
+
+static VALUE
+rt_time_to_day_fraction(VALUE h, VALUE min, VALUE s)
+{
+ return rb_Rational(f_add3(f_mul(h, INT2FIX(HOUR_IN_SECONDS)),
+ f_mul(min, INT2FIX(MINUTE_IN_SECONDS)),
+ s),
+ INT2FIX(DAY_IN_SECONDS));
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_amjd_to_ajd(VALUE amjd)
+{
+ return f_add(amjd, MJD_EPOCH_IN_AJD);
+}
+#endif
+
+static VALUE
+rt_ajd_to_amjd(VALUE ajd)
+{
+ return f_sub(ajd, MJD_EPOCH_IN_AJD);
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_mjd_to_jd(VALUE mjd)
+{
+ return f_add(mjd, MJD_EPOCH_IN_CJD);
+}
+#endif
+
+static VALUE
+rt_jd_to_mjd(VALUE jd)
+{
+ return f_sub(jd, MJD_EPOCH_IN_CJD);
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_ld_to_jd(VALUE ld)
+{
+ return f_add(ld, LD_EPOCH_IN_CJD);
+}
+#endif
+
+static VALUE
+rt_jd_to_ld(VALUE jd)
+{
+ return f_sub(jd, LD_EPOCH_IN_CJD);
+}
+
+static VALUE
+rt_jd_to_wday(VALUE jd)
+{
+ return f_mod(f_add(jd, INT2FIX(1)), INT2FIX(7));
+}
+
+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 jd, t, ny, nd;
+
+ if (f_negative_p(d)) {
+ VALUE j;
+
+ j = rt_find_ldoy(y, sg);
+ if (NIL_P(j))
+ return Qnil;
+ t = rt_jd_to_ordinal(f_add3(j, d, INT2FIX(1)), sg);
+ ny = RARRAY_PTR(t)[0];
+ nd = RARRAY_PTR(t)[1];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ d = nd;
+ }
+ jd = rt_ordinal_to_jd(y, d, sg);
+ t = rt_jd_to_ordinal(jd, sg);
+ ny = RARRAY_PTR(t)[0];
+ nd = RARRAY_PTR(t)[1];
+ if (!f_eqeq_p(y, ny))
+ return Qnil;
+ if (!f_eqeq_p(d, nd))
+ return Qnil;
+ return jd;
+}
+
+static VALUE
+rt__valid_civil_p(VALUE y, VALUE m, VALUE d, VALUE sg)
+{
+ VALUE t, ny, nm, nd, jd;
+
+ if (f_negative_p(m))
+ m = f_add(m, INT2FIX(13));
+ if (f_negative_p(d)) {
+ VALUE j;
+
+ j = rt_find_ldom(y, m, sg);
+ if (NIL_P(j))
+ return Qnil;
+ t = rt_jd_to_civil(f_add3(j, d, INT2FIX(1)), sg);
+ ny = RARRAY_PTR(t)[0];
+ nm = RARRAY_PTR(t)[1];
+ nd = RARRAY_PTR(t)[2];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ if (!f_eqeq_p(nm, m))
+ return Qnil;
+ d = nd;
+ }
+ jd = rt_civil_to_jd(y, m, d, sg);
+ t = rt_jd_to_civil(jd, sg);
+ ny = RARRAY_PTR(t)[0];
+ nm = RARRAY_PTR(t)[1];
+ nd = RARRAY_PTR(t)[2];
+ if (!f_eqeq_p(y, ny))
+ return Qnil;
+ if (!f_eqeq_p(m, nm))
+ return Qnil;
+ if (!f_eqeq_p(d, nd))
+ return Qnil;
+ return jd;
+}
+
+static VALUE
+rt__valid_commercial_p(VALUE y, VALUE w, VALUE d, VALUE sg)
+{
+ VALUE t, ny, nw, nd, jd;
+
+ if (f_negative_p(d))
+ d = f_add(d, INT2FIX(8));
+ if (f_negative_p(w)) {
+ VALUE j;
+
+ j = rt_commercial_to_jd(f_add(y, INT2FIX(1)),
+ INT2FIX(1), INT2FIX(1), sg);
+ t = rt_jd_to_commercial(f_add(j, f_mul(w, INT2FIX(7))), sg);
+ ny = RARRAY_PTR(t)[0];
+ nw = RARRAY_PTR(t)[1];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ w = nw;
+ }
+ jd = rt_commercial_to_jd(y, w, d, sg);
+ t = rt_jd_to_commercial(jd, sg);
+ ny = RARRAY_PTR(t)[0];
+ nw = RARRAY_PTR(t)[1];
+ nd = RARRAY_PTR(t)[2];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ if (!f_eqeq_p(nw, w))
+ return Qnil;
+ if (!f_eqeq_p(nd, d))
+ return Qnil;
+ return jd;
+}
+
+static VALUE
+rt__valid_weeknum_p(VALUE y, VALUE w, VALUE d, VALUE f, VALUE sg)
+{
+ VALUE t, ny, nw, nd, jd;
+
+ if (f_negative_p(d))
+ d = f_add(d, INT2FIX(7));
+ if (f_negative_p(w)) {
+ VALUE j;
+
+ j = rt_weeknum_to_jd(f_add(y, INT2FIX(1)),
+ INT2FIX(1), f, f, sg);
+ t = rt_jd_to_weeknum(f_add(j, f_mul(w, INT2FIX(7))), f, sg);
+ ny = RARRAY_PTR(t)[0];
+ nw = RARRAY_PTR(t)[1];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ w = nw;
+ }
+ jd = rt_weeknum_to_jd(y, w, d, f, sg);
+ t = rt_jd_to_weeknum(jd, f, sg);
+ ny = RARRAY_PTR(t)[0];
+ nw = RARRAY_PTR(t)[1];
+ nd = RARRAY_PTR(t)[2];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ if (!f_eqeq_p(nw, w))
+ return Qnil;
+ if (!f_eqeq_p(nd, d))
+ return Qnil;
+ return jd;
+}
+
+#ifndef NDEBUG
+static VALUE
+rt__valid_nth_kday_p(VALUE y, VALUE m, VALUE n, VALUE k, VALUE sg)
+{
+ VALUE t, ny, nm, nn, nk, jd;
+
+ if (f_negative_p(k))
+ k = f_add(k, INT2FIX(7));
+ if (f_negative_p(n)) {
+ VALUE j;
+
+ t = f_add(f_mul(y, INT2FIX(12)), m);
+ ny = f_idiv(t, INT2FIX(12));
+ nm = f_mod(t, INT2FIX(12));
+ nm = f_floor(f_add(nm, INT2FIX(1)));
+
+ j = rt_nth_kday_to_jd(ny, nm, INT2FIX(1), k, sg);
+ t = rt_jd_to_nth_kday(f_add(j, f_mul(n, INT2FIX(7))), sg);
+ ny = RARRAY_PTR(t)[0];
+ nm = RARRAY_PTR(t)[1];
+ nn = RARRAY_PTR(t)[2];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ if (!f_eqeq_p(nm, m))
+ return Qnil;
+ n = nn;
+ }
+ jd = rt_nth_kday_to_jd(y, m, n, k, sg);
+ t = rt_jd_to_nth_kday(jd, sg);
+ ny = RARRAY_PTR(t)[0];
+ nm = RARRAY_PTR(t)[1];
+ nn = RARRAY_PTR(t)[2];
+ nk = RARRAY_PTR(t)[3];
+ if (!f_eqeq_p(ny, y))
+ return Qnil;
+ if (!f_eqeq_p(nm, m))
+ return Qnil;
+ if (!f_eqeq_p(nn, n))
+ return Qnil;
+ if (!f_eqeq_p(nk, k))
+ return Qnil;
+ return jd;
+}
+#endif
+
+static VALUE
+rt__valid_time_p(VALUE h, VALUE min, VALUE s)
+{
+ if (f_negative_p(h))
+ h = f_add(h, INT2FIX(24));
+ if (f_negative_p(min))
+ min = f_add(min, INT2FIX(MINUTE_IN_SECONDS));
+ if (f_negative_p(s))
+ s = f_add(s, INT2FIX(MINUTE_IN_SECONDS));
+ if (f_eqeq_p(h, INT2FIX(24))) {
+ if (!f_eqeq_p(min, INT2FIX(0)))
+ return Qnil;
+ if (!f_eqeq_p(s, INT2FIX(0)))
+ return Qnil;
+ }
+ else {
+ if (f_lt_p(h, INT2FIX(0)) || f_ge_p(h, INT2FIX(24)))
+ return Qnil;
+ if (f_lt_p(min, INT2FIX(0)) || f_ge_p(min, INT2FIX(60)))
+ return Qnil;
+ if (f_lt_p(s, INT2FIX(0)) || f_ge_p(s, INT2FIX(60)))
+ return Qnil;
+ }
+ return rt_time_to_day_fraction(h, min, s);
+}
+
+/* light base */
+
static int valid_civil_p(int y, int m, int d, double sg,
int *rm, int *rd, long *rjd, int *ns);
@@ -523,6 +1118,61 @@ valid_commercial_p(int y, int w, int d, double sg,
return 1;
}
+#ifndef NDEBUG
+static int
+valid_weeknum_p(int y, int w, int d, int f, double sg,
+ int *rw, int *rd, long *rjd, int *ns)
+{
+ int ns2, ry2, rw2, rd2;
+
+ if (d < 0)
+ d += 7;
+ if (w < 0) {
+ long rjd2;
+
+ weeknum_to_jd(y + 1, 1, f, f, sg, &rjd2, &ns2);
+ jd_to_weeknum(rjd2 + w * 7, f, sg, &ry2, &rw2, &rd2);
+ if (ry2 != y)
+ return 0;
+ w = rw2;
+ }
+ weeknum_to_jd(y, w, d, f, sg, rjd, ns);
+ jd_to_weeknum(*rjd, f, sg, &ry2, rw, rd);
+ if (y != ry2 || w != *rw || d != *rd)
+ return 0;
+ return 1;
+}
+
+static int
+valid_nth_kday_p(int y, int m, int n, int k, double sg,
+ int *rm, int *rn, int *rk, long *rjd, int *ns)
+{
+ int ns2, ry2, rm2, rn2, rk2;
+
+ if (k < 0)
+ k += 7;
+ if (n < 0) {
+ long rjd2;
+ int t, ny, nm;
+
+ t = y * 12 + m;
+ ny = DIV(t, 12);
+ nm = MOD(t, 12) + 1;
+
+ nth_kday_to_jd(ny, nm, 1, k, sg, &rjd2, &ns2);
+ jd_to_nth_kday(rjd2 + n * 7, sg, &ry2, &rm2, &rn2, &rk2);
+ if (ry2 != y || rm2 != m)
+ return 0;
+ n = rn2;
+ }
+ nth_kday_to_jd(y, m, n, k, sg, rjd, ns);
+ 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
valid_time_p(int h, int min, int s, int *rh, int *rmin, int *rs)
{
@@ -588,7 +1238,7 @@ jd_utc_to_local(long jd, int df, int of)
inline static int
time_to_df(int h, int min, int s)
{
- return h * 3600 + min * 60 + s;
+ return h * HOUR_IN_SECONDS + min * MINUTE_IN_SECONDS + s;
}
inline static int
@@ -597,11 +1247,7 @@ jd_to_wday(long jd)
return (int)MOD(jd + 1, 7);
}
-VALUE
-date_zone_to_diff(VALUE s)
-{
- return rb_funcall(cDate, rb_intern("zone_to_diff"), 1, s);
-}
+VALUE date_zone_to_diff(VALUE);
static int
daydiff_to_sec(VALUE vof, int *rof)
@@ -714,10 +1360,10 @@ get_dt_time(union DateTimeData *x)
assert(have_df_p(x));
r = df_utc_to_local(x->l.df, x->l.of);
- x->l.hour = r / 3600;
- r %= 3600;
- x->l.min = r / 60;
- x->l.sec = r % 60;
+ x->l.hour = r / HOUR_IN_SECONDS;
+ r %= HOUR_IN_SECONDS;
+ x->l.min = r / MINUTE_IN_SECONDS;
+ x->l.sec = r % MINUTE_IN_SECONDS;
x->l.flags |= HAVE_TIME;
}
}
@@ -799,10 +1445,19 @@ k_numeric_p(VALUE x)
return f_kind_of_p(x, rb_cNumeric);
}
+/* date light */
+
+static VALUE
+rtv__valid_jd_p(int argc, VALUE *argv)
+{
+ assert(argc == 2);
+ return rt__valid_jd_p(argv[0], argv[1]);
+}
+
static VALUE
valid_jd_sub(int argc, VALUE *argv, VALUE klass)
{
- return argv[0];
+ return rtv__valid_jd_p(argc, argv);
}
#ifndef NDEBUG
@@ -824,6 +1479,13 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
}
#endif
+/*
+ * call-seq:
+ * Date.valid_jd?(jd[, start=Date::ITALY])
+ *
+ * Is +jd+ a valid Julian Day Number?
+ * Returns true or false.
+ */
static VALUE
date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
{
@@ -844,19 +1506,30 @@ date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
}
static VALUE
+rtv__valid_civil_p(int argc, VALUE *argv)
+{
+ assert(argc == 4);
+ return rt__valid_civil_p(argv[0], argv[1], argv[2], argv[3]);
+}
+
+static VALUE
valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
{
int y, m, d, rm, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return rtv__valid_civil_p(argc, argv);
+#endif
+
if (!(FIXNUM_P(argv[0]) &&
FIXNUM_P(argv[1]) &&
FIXNUM_P(argv[2])))
- return cforwardv("_valid_civil_r?");
+ return rtv__valid_civil_p(argc, argv);
y = NUM2INT(argv[0]);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("_valid_civil_r?");
+ return rtv__valid_civil_p(argc, argv);
m = NUM2INT(argv[1]);
d = NUM2INT(argv[2]);
@@ -898,6 +1571,22 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
}
#endif
+/*
+ * call-seq:
+ * Date.valid_civil?(year, month, mday[, start=Date::ITALY])
+ *
+ * Do year +y+, month +m+, and day-of-month +d+ make a
+ * valid Civil Date? Returns true or false.
+ *
+ * +m+ and +d+ can be negative, in which case they count
+ * backwards from the end of the year and the end of the
+ * month respectively. No wraparound is performed, however,
+ * and invalid values cause an ArgumentError to be raised.
+ * A date falling in the period skipped in the Day of Calendar
+ * Reform adjustment is not valid.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ */
static VALUE
date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
{
@@ -920,18 +1609,29 @@ date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
}
static VALUE
+rtv__valid_ordinal_p(int argc, VALUE *argv)
+{
+ assert(argc == 3);
+ return rt__valid_ordinal_p(argv[0], argv[1], argv[2]);
+}
+
+static VALUE
valid_ordinal_sub(int argc, VALUE *argv, VALUE klass)
{
int y, d, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return rtv__valid_ordinal_p(argc, argv);
+#endif
+
if (!(FIXNUM_P(argv[0]) &&
FIXNUM_P(argv[1])))
- return cforwardv("_valid_ordinal_r?");
+ return rtv__valid_ordinal_p(argc, argv);
y = NUM2INT(argv[0]);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("_valid_ordinal_r?");
+ return rtv__valid_ordinal_p(argc, argv);
d = NUM2INT(argv[1]);
sg = NUM2DBL(argv[2]);
@@ -966,6 +1666,23 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
}
#endif
+/*
+ * call-seq:
+ * Date.valid_ordinal?(year, yday[, start=Date::ITALY])
+ *
+ * Do the year +y+ and day-of-year +d+ make a valid Ordinal Date?
+ * Returns true or false.
+ *
+ * +d+ can be a negative number, in which case it counts backwards
+ * from the end of the year (-1 being the last day of the year).
+ * No year wraparound is performed, however, so valid values of
+ * +d+ are -365 .. -1, 1 .. 365 on a non-leap-year,
+ * -366 .. -1, 1 .. 366 on a leap year.
+ * A date falling in the period skipped in the Day of Calendar Reform
+ * adjustment is not valid.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ */
static VALUE
date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
{
@@ -987,19 +1704,30 @@ date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
}
static VALUE
+rtv__valid_commercial_p(int argc, VALUE *argv)
+{
+ assert(argc == 4);
+ return rt__valid_commercial_p(argv[0], argv[1], argv[2], argv[3]);
+}
+
+static VALUE
valid_commercial_sub(int argc, VALUE *argv, VALUE klass)
{
int y, w, d, rw, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return rtv__valid_commercial_p(argc, argv);
+#endif
+
if (!(FIXNUM_P(argv[0]) &&
FIXNUM_P(argv[1]) &&
FIXNUM_P(argv[2])))
- return cforwardv("_valid_commercial_r?");
+ return rtv__valid_commercial_p(argc, argv);
y = NUM2INT(argv[0]);
if (!LIGHTABLE_CWYEAR(y))
- return cforwardv("_valid_commercial_r?");
+ return rtv__valid_commercial_p(argc, argv);
w = NUM2INT(argv[1]);
d = NUM2INT(argv[2]);
@@ -1036,6 +1764,24 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
}
#endif
+/*
+ * call-seq:
+ * Date.valid_commercial?(year, week, day[, start=Date::ITALY])
+ *
+ * Do year +y+, week-of-year +w+, and day-of-week +d+ make a
+ * valid Commercial Date? Returns true or false.
+ *
+ * Monday is day-of-week 1; Sunday is day-of-week 7.
+ *
+ * +w+ and +d+ can be negative, in which case they count
+ * backwards from the end of the year and the end of the
+ * week respectively. No wraparound is performed, however,
+ * and invalid values cause an ArgumentError to be raised.
+ * A date falling in the period skipped in the Day of Calendar
+ * Reform adjustment is not valid.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ */
static VALUE
date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
{
@@ -1057,25 +1803,233 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
return Qtrue;
}
+#ifndef NDEBUG
+static VALUE
+rtv__valid_weeknum_p(int argc, VALUE *argv)
+{
+ assert(argc == 5);
+ return rt__valid_weeknum_p(argv[0], argv[1], argv[2], argv[3], argv[4]);
+}
+
+static VALUE
+valid_weeknum_sub(int argc, VALUE *argv, VALUE klass)
+{
+ int y, w, d, f, rw, rd;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return rtv__valid_weeknum_p(argc, argv);
+#endif
+
+ if (!(FIXNUM_P(argv[0]) &&
+ FIXNUM_P(argv[1]) &&
+ FIXNUM_P(argv[2]) &&
+ FIXNUM_P(argv[3])))
+ return rtv__valid_weeknum_p(argc, argv);
+
+ y = NUM2INT(argv[0]);
+ if (!LIGHTABLE_YEAR(y))
+ return rtv__valid_weeknum_p(argc, argv);
+
+ w = NUM2INT(argv[1]);
+ d = NUM2INT(argv[2]);
+ f = NUM2INT(argv[3]);
+ sg = NUM2DBL(argv[4]);
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns))
+ return Qnil;
+ return LONG2NUM(jd);
+ }
+}
+
+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);
+}
+
+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(ITALY);
+ else
+ argv2[4] = vsg;
+
+ if (NIL_P(valid_weeknum_sub(5, argv2, klass)))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+rtv__valid_nth_kday_p(int argc, VALUE *argv)
+{
+ assert(argc == 5);
+ return rt__valid_nth_kday_p(argv[0], argv[1], argv[2], argv[3], argv[4]);
+}
+static VALUE
+valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass)
+{
+ int y, m, n, k, rm, rn, rk;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return rtv__valid_nth_kday_p(argc, argv);
+#endif
+
+ if (!(FIXNUM_P(argv[0]) &&
+ FIXNUM_P(argv[1]) &&
+ FIXNUM_P(argv[2]) &&
+ FIXNUM_P(argv[3])))
+ return rtv__valid_nth_kday_p(argc, argv);
+
+ y = NUM2INT(argv[0]);
+ if (!LIGHTABLE_YEAR(y))
+ return rtv__valid_nth_kday_p(argc, argv);
+
+ m = NUM2INT(argv[1]);
+ n = NUM2INT(argv[2]);
+ k = NUM2INT(argv[3]);
+ sg = NUM2DBL(argv[4]);
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns))
+ return Qnil;
+ return LONG2NUM(jd);
+ }
+}
+
+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);
+}
+
+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(ITALY);
+ else
+ argv2[4] = vsg;
+
+ if (NIL_P(valid_nth_kday_sub(5, argv2, klass)))
+ 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)
+ *
+ * Return true if the given year is a leap year on Julian calendar.
+ */
+static VALUE
+date_s_julian_leap_p(VALUE klass, VALUE y)
+{
+ if (f_zero_p(f_mod(y, INT2FIX(4))))
+ return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * Date.gregorian_leap?(year)
+ * Date.leap?(year)
+ *
+ * Return true if the given year is a leap year on Gregorian calendar.
+ */
+static VALUE
+date_s_gregorian_leap_p(VALUE klass, VALUE y)
+{
+ if (f_zero_p(f_mod(y, INT2FIX(4))) &&
+ !f_zero_p(f_mod(y, INT2FIX(100))) ||
+ f_zero_p(f_mod(y, INT2FIX(400))))
+ return Qtrue;
+ return Qfalse;
+}
+
static void
d_right_gc_mark(union DateData *dat)
{
- if (!light_mode_p(dat)) {
- rb_gc_mark(dat->r.ajd);
- rb_gc_mark(dat->r.of);
- rb_gc_mark(dat->r.sg);
- rb_gc_mark(dat->r.cache);
- }
+ assert(!light_mode_p(dat));
+ rb_gc_mark(dat->r.ajd);
+ rb_gc_mark(dat->r.of);
+ rb_gc_mark(dat->r.sg);
+ rb_gc_mark(dat->r.cache);
}
+#define d_lite_gc_mark 0
+
inline static VALUE
-d_right_s_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg,
- unsigned flags)
+d_right_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg,
+ unsigned flags)
{
union DateData *dat;
VALUE obj;
- obj = Data_Make_Struct(klass, union DateData, d_right_gc_mark, -1, dat);
+ obj = Data_Make_Struct(klass, union DateData,
+ d_right_gc_mark, -1, dat);
dat->r.ajd = ajd;
dat->r.of = of;
@@ -1087,93 +2041,199 @@ d_right_s_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg,
}
inline static VALUE
-d_lite_s_new_internal(VALUE klass, long jd, double sg,
- int y, int m, int d, unsigned flags)
+d_lite_new_internal(VALUE klass, long jd, double sg,
+ int y, int m, int d, unsigned flags)
{
union DateData *dat;
VALUE obj;
- obj = Data_Make_Struct(klass, union DateData, d_right_gc_mark, -1, dat);
+ obj = Data_Make_Struct(klass, union DateData,
+ d_lite_gc_mark, -1, dat);
dat->l.jd = jd;
dat->l.sg = sg;
dat->l.year = y;
dat->l.mon = m;
dat->l.mday = d;
- dat->l.flags = flags;
+ dat->l.flags = flags | LIGHT_MODE;
return obj;
}
static VALUE
-d_lite_s_new_internal_wo_civil(VALUE klass, long jd, double sg,
+d_lite_new_internal_wo_civil(VALUE klass, long jd, double sg,
unsigned flags)
{
- return d_lite_s_new_internal(klass, jd, sg, 0, 0, 0, flags);
+ return d_lite_new_internal(klass, jd, sg, 0, 0, 0, flags);
}
static VALUE
d_lite_s_alloc(VALUE klass)
{
- return d_lite_s_new_internal_wo_civil(klass, 0, 0, LIGHT_MODE);
+ return d_lite_new_internal_wo_civil(klass, 0, 0, 0);
+}
+
+static VALUE
+d_right_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg)
+{
+ return d_right_new_internal(klass, ajd, of, sg, 0);
}
static VALUE
-d_right_s_new_r_bang(int argc, VALUE *argv, VALUE klass)
+d_lite_new(VALUE klass, VALUE jd, VALUE sg)
{
- VALUE vajd, vof, vsg;
+ return d_lite_new_internal_wo_civil(klass,
+ NUM2LONG(jd),
+ NUM2DBL(sg),
+ HAVE_JD);
+}
- rb_scan_args(argc, argv, "03", &vajd, &vof, &vsg);
+static VALUE
+d_switch_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg)
+{
+ VALUE t, jd, df;
- if (argc < 1)
- vajd = INT2FIX(0);
- if (argc < 2)
- vof = INT2FIX(0);
- if (argc < 3)
- vsg = DBL2NUM(ITALY);
+ t = rt_ajd_to_jd(ajd, INT2FIX(0)); /* as utc */
+ jd = RARRAY_PTR(t)[0];
+ df = RARRAY_PTR(t)[1];
+
+#ifdef FORCE_RIGHT
+ if (1)
+#else
+ if (!FIXNUM_P(jd) ||
+ f_lt_p(jd, sg) || !f_zero_p(df) || !f_zero_p(of) ||
+ !LIGHTABLE_JD(NUM2LONG(jd)))
+#endif
+ return d_right_new(klass, ajd, of, sg);
+ else
+ return d_lite_new(klass, jd, sg);
+}
+
+#ifndef NDEBUG
+static VALUE
+d_right_new_m(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ajd, of, sg;
+
+ 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(ITALY);
+ }
- return d_right_s_new_internal(klass, vajd, vof, vsg, 0);
+ return d_right_new(klass, ajd, of, sg);
}
static VALUE
-d_lite_s_new_l_bang(int argc, VALUE *argv, VALUE klass)
+d_lite_new_m(int argc, VALUE *argv, VALUE klass)
{
- VALUE vjd, vsg;
- long jd;
- double sg;
+ VALUE jd, sg;
- rb_scan_args(argc, argv, "02", &vjd, &vsg);
+ rb_scan_args(argc, argv, "02", &jd, &sg);
- if (argc < 1)
- jd = 0;
- else {
- if (!FIXNUM_P(vjd))
- rb_raise(rb_eArgError, "cannot create");
- jd = NUM2LONG(vjd);
- if (!LIGHTABLE_JD(jd))
- rb_raise(rb_eArgError, "cannot create");
+ switch (argc) {
+ case 0:
+ jd = INT2FIX(0);
+ case 1:
+ sg = INT2FIX(ITALY);
+ }
+
+ return d_lite_new(klass, jd, sg);
+}
+
+static VALUE
+d_switch_new_m(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ajd, of, sg;
+
+ 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(ITALY);
}
- if (argc < 2)
- sg = 0;
- else
- sg = NUM2DBL(vsg);
- return d_lite_s_new_internal_wo_civil(klass,
- jd,
- sg,
- LIGHT_MODE | HAVE_JD);
+ return d_switch_new(klass, ajd, of, sg);
}
+#endif
static VALUE
+d_right_new_jd(VALUE klass, VALUE jd, VALUE sg)
+{
+ return d_right_new(klass,
+ rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)),
+ INT2FIX(0),
+ sg);
+}
+
+#ifndef NDEBUG
+static VALUE
+d_lite_new_jd(VALUE klass, VALUE jd, VALUE sg)
+{
+ return d_lite_new(klass, jd, sg);
+}
+#endif
+
+static VALUE
+d_switch_new_jd(VALUE klass, VALUE jd, VALUE sg)
+{
+ return d_switch_new(klass,
+ rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0)),
+ INT2FIX(0),
+ sg);
+}
+
+#ifndef NDEBUG
+static VALUE
date_s_new_r_bang(int argc, VALUE *argv, VALUE klass)
{
- return d_right_s_new_r_bang(argc, argv, klass);
+ return d_right_new_m(argc, argv, klass);
}
static VALUE
date_s_new_l_bang(int argc, VALUE *argv, VALUE klass)
{
- return d_lite_s_new_l_bang(argc, argv, klass);
+ return d_lite_new_m(argc, argv, klass);
+}
+
+static VALUE
+date_s_new_bang(int argc, VALUE *argv, VALUE klass)
+{
+ return d_switch_new_m(argc, argv, klass);
+}
+#endif
+
+#define c_cforwardv(m) rt_date_s_##m(argc, argv, klass)
+
+static VALUE
+rt_date_s_jd(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE jd, sg;
+
+ rb_scan_args(argc, argv, "02", &jd, &sg);
+
+ switch (argc) {
+ case 0:
+ jd = INT2FIX(0);
+ case 1:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_jd_p(jd, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
}
/*
@@ -1192,28 +2252,55 @@ date_s_jd(int argc, VALUE *argv, VALUE klass)
long jd;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(jd);
+#endif
+
rb_scan_args(argc, argv, "02", &vjd, &vsg);
if (!FIXNUM_P(vjd))
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ jd = 0;
+ sg = ITALY;
- if (argc >= 1) {
+ switch (argc) {
+ case 2:
+ sg = NUM2DBL(vsg);
+ case 1:
jd = NUM2LONG(vjd);
if (!LIGHTABLE_JD(jd))
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
}
- else
- jd = 0;
if (jd < sg)
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
+
+ return d_lite_new_internal_wo_civil(klass, jd, sg, HAVE_JD);
+}
+
+static VALUE
+rt_date_s_ordinal(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, d, sg, jd;
+
+ rb_scan_args(argc, argv, "03", &y, &d, &sg);
- return d_lite_s_new_internal_wo_civil(klass, jd, sg, LIGHT_MODE | HAVE_JD);
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ d = INT2FIX(1);
+ case 2:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_ordinal_p(y, d, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
}
/*
@@ -1238,28 +2325,29 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
int y, d, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(ordinal);
+#endif
+
rb_scan_args(argc, argv, "03", &vy, &vd, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
(NIL_P(vd) || FIXNUM_P(vd))))
- return cforwardv("ordinal_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(ordinal);
y = -4712;
d = 1;
+ sg = ITALY;
switch (argc) {
case 3:
+ sg = NUM2DBL(vsg);
case 2:
d = NUM2INT(vd);
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("ordinal_r");
+ return c_cforwardv(ordinal);
}
{
@@ -1270,11 +2358,37 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("ordinal_r");
+ return c_cforwardv(ordinal);
+
+ return d_lite_new_internal_wo_civil(klass, jd, sg,
+ HAVE_JD);
+ }
+}
+
+static VALUE
+rt_date_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, m, d, sg, jd;
+
+ rb_scan_args(argc, argv, "04", &y, &m, &d, &sg);
- return d_lite_s_new_internal_wo_civil(klass, jd, sg,
- LIGHT_MODE | HAVE_JD);
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ m = INT2FIX(1);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ sg = INT2FIX(ITALY);
}
+
+ jd = rt__valid_civil_p(y, m, d, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
}
/*
@@ -1303,24 +2417,25 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
int y, m, d, rm, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(civil);
+#endif
+
rb_scan_args(argc, argv, "04", &vy, &vm, &vd, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
(NIL_P(vm) || FIXNUM_P(vm)) &&
(NIL_P(vd) || FIXNUM_P(vd))))
- return cforwardv("civil_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(civil);
y = -4712;
m = 1;
d = 1;
+ sg = ITALY;
switch (argc) {
case 4:
+ sg = NUM2DBL(vsg);
case 3:
d = NUM2INT(vd);
case 2:
@@ -1328,15 +2443,15 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("civil_r");
+ return c_cforwardv(civil);
}
if (isinf(sg) && sg < 0) {
if (!valid_gregorian_p(y, m, d, &rm, &rd))
rb_raise(rb_eArgError, "invalid date");
- return d_lite_s_new_internal(klass, 0, sg, y, rm, rd,
- LIGHT_MODE | HAVE_CIVIL);
+ return d_lite_new_internal(klass, 0, sg, y, rm, rd,
+ HAVE_CIVIL);
}
else {
long jd;
@@ -1346,11 +2461,37 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("civil_r");
+ return c_cforwardv(civil);
+
+ return d_lite_new_internal(klass, jd, sg, y, rm, rd,
+ HAVE_JD | HAVE_CIVIL);
+ }
+}
+
+static VALUE
+rt_date_s_commercial(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, w, d, sg, jd;
+
+ rb_scan_args(argc, argv, "04", &y, &w, &d, &sg);
- return d_lite_s_new_internal(klass, jd, sg, y, rm, rd,
- LIGHT_MODE | HAVE_JD | HAVE_CIVIL);
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ w = INT2FIX(1);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ sg = INT2FIX(ITALY);
}
+
+ jd = rt__valid_commercial_p(y, w, d, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
}
/*
@@ -1379,24 +2520,25 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
int y, w, d, rw, rd;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(commercial);
+#endif
+
rb_scan_args(argc, argv, "04", &vy, &vw, &vd, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
(NIL_P(vw) || FIXNUM_P(vw)) &&
(NIL_P(vd) || FIXNUM_P(vd))))
- return cforwardv("commercial_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(commercial);
y = -4712;
w = 1;
d = 1;
+ sg = ITALY;
switch (argc) {
case 4:
+ sg = NUM2DBL(vsg);
case 3:
d = NUM2INT(vd);
case 2:
@@ -1404,7 +2546,7 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_CWYEAR(y))
- return cforwardv("commercial_r");
+ return c_cforwardv(commercial);
}
{
@@ -1415,12 +2557,180 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("commercial_r");
+ return c_cforwardv(commercial);
+
+ return d_lite_new_internal_wo_civil(klass, jd, sg,
+ HAVE_JD);
+ }
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_date_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, w, d, f, sg, jd;
+
+ rb_scan_args(argc, argv, "05", &y, &w, &d, &f, &sg);
+
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ w = INT2FIX(0);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ f = INT2FIX(0);
+ case 4:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_weeknum_p(y, w, d, f, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
+}
+
+static VALUE
+date_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vsg;
+ int y, w, d, f, rw, rd;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return c_cforwardv(weeknum);
+#endif
+
+ rb_scan_args(argc, argv, "05", &vy, &vw, &vd, &vf, &vsg);
+
+ if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
+ (NIL_P(vw) || FIXNUM_P(vw)) &&
+ (NIL_P(vd) || FIXNUM_P(vd)) &&
+ (NIL_P(vf) || FIXNUM_P(vf))))
+ return c_cforwardv(weeknum);
+
+ y = -4712;
+ w = 0;
+ d = 1;
+ f = 0;
+ sg = ITALY;
+
+ switch (argc) {
+ case 5:
+ sg = NUM2DBL(vsg);
+ case 4:
+ f = NUM2INT(vf);
+ case 3:
+ d = NUM2INT(vd);
+ case 2:
+ w = NUM2INT(vw);
+ case 1:
+ y = NUM2INT(vy);
+ if (!LIGHTABLE_YEAR(y))
+ return c_cforwardv(weeknum);
+ }
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns))
+ rb_raise(rb_eArgError, "invalid date");
+
+ if (!LIGHTABLE_JD(jd) || !ns)
+ return c_cforwardv(weeknum);
+
+ return d_lite_new_internal_wo_civil(klass, jd, sg,
+ HAVE_JD);
+ }
+}
+
+static VALUE
+rt_date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, m, n, k, sg, jd;
+
+ rb_scan_args(argc, argv, "05", &y, &m, &n, &k, &sg);
+
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ m = INT2FIX(1);
+ case 2:
+ n = INT2FIX(1);
+ case 3:
+ k = INT2FIX(1);
+ case 4:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_nth_kday_p(y, m, n, k, sg);
+
+ if (NIL_P(jd))
+ rb_raise(rb_eArgError, "invalid date");
+
+ return d_right_new_jd(klass, jd, sg);
+}
+
+static VALUE
+date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vsg;
+ int y, m, n, k, rm, rn, rk;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return c_cforwardv(nth_kday);
+#endif
+
+ rb_scan_args(argc, argv, "05", &vy, &vm, &vn, &vk, &vsg);
+
+ if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
+ (NIL_P(vm) || FIXNUM_P(vm)) &&
+ (NIL_P(vn) || FIXNUM_P(vn)) &&
+ (NIL_P(vk) || FIXNUM_P(vk))))
+ return c_cforwardv(nth_kday);
+
+ y = -4712;
+ m = 1;
+ n = 1;
+ k = 1;
+ sg = ITALY;
+
+ switch (argc) {
+ case 5:
+ sg = NUM2DBL(vsg);
+ case 4:
+ k = NUM2INT(vk);
+ case 3:
+ n = NUM2INT(vn);
+ case 2:
+ m = NUM2INT(vm);
+ case 1:
+ y = NUM2INT(vy);
+ if (!LIGHTABLE_YEAR(y))
+ return c_cforwardv(nth_kday);
+ }
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns))
+ rb_raise(rb_eArgError, "invalid date");
+
+ if (!LIGHTABLE_JD(jd) || !ns)
+ return c_cforwardv(nth_kday);
- return d_lite_s_new_internal_wo_civil(klass, jd, sg,
- LIGHT_MODE | HAVE_JD);
+ return d_lite_new_internal_wo_civil(klass, jd, sg,
+ HAVE_JD);
}
}
+#endif
#if !defined(HAVE_GMTIME_R)
static struct tm*
@@ -1453,10 +2763,10 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
rb_scan_args(argc, argv, "01", &vsg);
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
+ if (argc < 1)
sg = ITALY;
+ else
+ sg = NUM2DBL(vsg);
if (time(&t) == -1)
rb_sys_fail("time");
@@ -1466,23 +2776,441 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
m = tm.tm_mon + 1;
d = tm.tm_mday;
+#ifdef FORCE_RIGHT
+ goto right;
+#endif
+
if (!LIGHTABLE_YEAR(y))
- rb_raise(rb_eArgError, "cannot create");
+ goto right;
if (isinf(sg) && sg < 0)
- return d_lite_s_new_internal(klass, 0, sg, y, m, d,
- LIGHT_MODE | HAVE_CIVIL);
+ return d_lite_new_internal(klass, 0, sg, y, m, d,
+ HAVE_CIVIL);
else {
long jd;
int ns;
civil_to_jd(y, m, d, sg, &jd, &ns);
- return d_lite_s_new_internal(klass, jd, sg, y, m, d,
- LIGHT_MODE | HAVE_JD | HAVE_CIVIL);
+ return d_lite_new_internal(klass, jd, sg, y, m, d,
+ HAVE_JD | HAVE_CIVIL);
+ }
+ right:
+ {
+ VALUE jd, ajd;
+
+ jd = rt_civil_to_jd(INT2FIX(y), INT2FIX(m), INT2FIX(d), DBL2NUM(sg));
+ ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
+ return d_right_new(klass, ajd, INT2FIX(0), DBL2NUM(sg));
}
}
+#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;
+
+ if (NIL_P(hash))
+ hash = rb_hash_new();
+
+ 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
+fv_values_at(VALUE h, VALUE a)
+{
+ return rb_funcall2(h, rb_intern("values_at"),
+ RARRAY_LENINT(a), RARRAY_PTR(a));
+}
+
+static VALUE
+rt_complete_frags(VALUE klass, VALUE hash)
+{
+ static VALUE tab = Qnil;
+ VALUE t, l, g, 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;
+
+ t = rb_ary_new2(RARRAY_LEN(tab));
+
+ for (i = 0; i < RARRAY_LENINT(tab); i++) {
+ VALUE x, k, a, e;
+
+ x = RARRAY_PTR(tab)[i];
+ k = RARRAY_PTR(x)[0];
+ a = RARRAY_PTR(x)[1];
+ e = f_compact(fv_values_at(hash, a));
+
+ if (RARRAY_LEN(e) > 0)
+ rb_ary_push(t, rb_ary_new3(5,
+ INT2FIX(RARRAY_LENINT(e)),
+ INT2FIX(-i),
+ k, a, e));
+ }
+
+ if (RARRAY_LEN(t) == 0)
+ g = Qnil;
+ else {
+ rb_ary_sort_bang(t);
+ l = RARRAY_PTR(t)[RARRAY_LENINT(t) - 1];
+ g = rb_ary_new3(3,
+ RARRAY_PTR(l)[2],
+ RARRAY_PTR(l)[3],
+ RARRAY_PTR(l)[4]);
+ }
+ }
+
+ d = Qnil;
+
+ if (!NIL_P(g) && !NIL_P(RARRAY_PTR(g)[0]) &&
+ (RARRAY_LEN(RARRAY_PTR(g)[1]) -
+ RARRAY_LEN(RARRAY_PTR(g)[2]))) {
+ VALUE k, a;
+
+ if (NIL_P(d))
+ d = date_s_today(0, (VALUE *)0, cDate);
+
+ k = RARRAY_PTR(g)[0];
+ a = RARRAY_PTR(g)[1];
+
+ if (k == sym("ordinal")) {
+ if (NIL_P(ref_hash("year")))
+ set_hash("year", f_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;
+ 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;
+ 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")) {
+ set_hash("jd", f_jd(f_add(f_sub(d, f_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;
+ 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;
+ 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 (!NIL_P(g) && RARRAY_PTR(g)[0] == 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", f_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;
+}
+
+#define f_values_at1(o,k1) rb_funcall(o, rb_intern("values_at"), 1, k1)
+#define f_values_at2(o,k1,k2) rb_funcall(o, rb_intern("values_at"), 2, k1, k2)
+#define f_values_at3(o,k1,k2,k3) rb_funcall(o, rb_intern("values_at"), 3, k1, k2, k3)
+
+static VALUE
+f_all_p(VALUE a)
+{
+ int i;
+
+ for (i = 0; i < RARRAY_LENINT(a); i++)
+ if (NIL_P(RARRAY_PTR(a)[i]))
+ return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+rt__valid_date_frags_p(VALUE hash, VALUE sg)
+{
+ VALUE a;
+
+ a = f_values_at1(hash, sym("jd"));
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_jd_p(RARRAY_PTR(a)[0],
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+
+ a = f_values_at2(hash, sym("year"), sym("yday"));
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_ordinal_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+
+ a = f_values_at3(hash, sym("year"), sym("mon"), sym("mday"));
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_civil_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ RARRAY_PTR(a)[2],
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+
+ a = f_values_at3(hash, sym("cwyear"), sym("cweek"), sym("cwday"));
+ if (NIL_P(RARRAY_PTR(a)[2]) && !NIL_P(ref_hash("wday")))
+ if (f_zero_p(ref_hash("wday")))
+ RARRAY_PTR(a)[2] = INT2FIX(7);
+ else
+ RARRAY_PTR(a)[2] = ref_hash("wday");
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_commercial_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ RARRAY_PTR(a)[2],
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+
+ a = f_values_at3(hash, sym("year"), sym("wnum0"), sym("wday"));
+ if (NIL_P(RARRAY_PTR(a)[2]) && !NIL_P(ref_hash("cwday")))
+ RARRAY_PTR(a)[2] = f_mod(ref_hash("cwday"), INT2FIX(7));
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_weeknum_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ RARRAY_PTR(a)[2],
+ INT2FIX(0),
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+
+ a = f_values_at3(hash, sym("year"), sym("wnum1"), sym("wday"));
+ if (!NIL_P(RARRAY_PTR(a)[2]))
+ RARRAY_PTR(a)[2] = f_mod(f_sub(RARRAY_PTR(a)[2], INT2FIX(1)),
+ INT2FIX(7));
+ if (NIL_P(RARRAY_PTR(a)[2]) && !NIL_P(ref_hash("cwday")))
+ RARRAY_PTR(a)[2] = f_mod(f_sub(ref_hash("cwday"), INT2FIX(1)),
+ INT2FIX(7));
+ if (f_all_p(a)) {
+ VALUE jd = rt__valid_weeknum_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ RARRAY_PTR(a)[2],
+ INT2FIX(1),
+ sg);
+ if (!NIL_P(jd))
+ return jd;
+ }
+ return Qnil;
+}
+
+static VALUE
+rt__valid_time_frags_p(VALUE hash)
+{
+ VALUE a;
+
+ a = f_values_at3(hash, sym("hour"), sym("min"), sym("sec"));
+ return rt__valid_time_p(RARRAY_PTR(a)[0],
+ RARRAY_PTR(a)[1],
+ RARRAY_PTR(a)[2]);
+}
+
+static VALUE
+d_switch_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
+{
+ VALUE jd;
+
+ 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");
+ return d_switch_new_jd(klass, jd, sg);
+}
+
VALUE
date__strptime(const char *str, size_t slen,
const char *fmt, size_t flen, VALUE hash);
@@ -1525,10 +3253,12 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
if (!NIL_P(zone)) {
rb_enc_copy(zone, vstr);
+ OBJ_INFECT(zone, vstr);
rb_hash_aset(hash, ID2SYM(rb_intern("zone")), zone);
}
if (!NIL_P(left)) {
rb_enc_copy(left, vstr);
+ OBJ_INFECT(left, vstr);
rb_hash_aset(hash, ID2SYM(rb_intern("leftover")), left);
}
}
@@ -1548,6 +3278,52 @@ 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]]])
+ *
+ * Create a new Date object by parsing from a String
+ * according to a specified format.
+ *
+ * +str+ is a String holding a date representation.
+ * +fmt+ is the format that the date is in. See
+ * date/format.rb for details on supported formats.
+ *
+ * The default +str+ is '-4712-01-01', and the default
+ * +fmt+ is '%F', which means Year-Month-Day_of_Month.
+ * This gives Julian Day Number day 0.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ *
+ * An ArgumentError will be raised if +str+ cannot be
+ * parsed.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = fmt;
+ hash = date_s__strptime(2, argv2, klass);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
VALUE
date__parse(VALUE str, VALUE comp);
@@ -1571,6 +3347,7 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
if (!NIL_P(zone)) {
rb_enc_copy(zone, vstr);
+ OBJ_INFECT(zone, vstr);
rb_hash_aset(hash, ID2SYM(rb_intern("zone")), zone);
}
}
@@ -1592,6 +3369,295 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
+ * Date.parse(string="-4712-01-01"[, comp=true[,start=ITALY]])
+ *
+ * Create a new Date object by parsing from a String,
+ * without specifying the format.
+ *
+ * +str+ is a String holding a date representation.
+ * +comp+ specifies whether to interpret 2-digit years
+ * as 19XX (>= 69) or 20XX (< 69); the default is to.
+ * The method will attempt to parse a date from the String
+ * using various heuristics; see #_parse in date/format.rb
+ * for more details. If parsing fails, an ArgumentError
+ * will be raised.
+ *
+ * The default +str+ is '-4712-01-01'; this is Julian
+ * Day Number day 0.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = comp;
+ hash = date_s__parse(2, argv2, klass);
+ return d_switch_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)
+ *
+ * Return 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])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical ISO 8601 format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__iso8601(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._rfc3339(string)
+ *
+ * Return 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])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical RFC 3339 format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__rfc3339(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._xmlschema(string)
+ *
+ * Return 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])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical XML Schema format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__xmlschema(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._rfc2822(string)
+ * Date._rfc822(string)
+ *
+ * Return 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.rfc822(string="Mon, 1 Jan -4712 00:00:00 +0000"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical RFC 2822 format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__rfc2822(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._httpdate(string)
+ *
+ * Return 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])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some RFC 2616 format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__httpdate(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date._jisx0301(string)
+ *
+ * Return 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])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical JIS X 0301 format.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__jisx0301(klass, str);
+ return d_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
* d.ajd
*
* Get the date as an Astronomical Julian Day Number.
@@ -1608,6 +3674,18 @@ d_lite_ajd(VALUE self)
}
}
+#define c_iforward0(m) d_right_##m(self)
+#define c_iforwardv(m) d_right_##m(argc, argv, self)
+#define c_iforwardop(m) d_right_##m(self, other)
+
+static VALUE
+d_right_amjd(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return rt_ajd_to_amjd(dat->r.ajd);
+}
+
/*
* call-seq:
* d.amjd
@@ -1619,13 +3697,40 @@ d_lite_amjd(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("amjd_r");
+ return c_iforward0(amjd);
{
get_d_jd(dat);
return rb_rational_new1(LONG2NUM(dat->l.jd - 2400001L));
}
}
+#define return_once(k, expr)\
+{\
+ VALUE id, val;\
+ get_d1(self);\
+ id = ID2SYM(rb_intern(#k));\
+ val = rb_hash_aref(dat->r.cache, id);\
+ if (!NIL_P(val))\
+ return val;\
+ val = expr;\
+ rb_hash_aset(dat->r.cache, id, val);\
+ return val;\
+}
+
+static VALUE
+d_right_daynum(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(daynum, rt_ajd_to_jd(dat->r.ajd, dat->r.of));
+}
+
+static VALUE
+d_right_jd(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(daynum))[0];
+}
+
/*
* call-seq:
* d.jd
@@ -1637,13 +3742,21 @@ d_lite_jd(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("jd_r");
+ return c_iforward0(jd);
{
get_d_jd(dat);
return INT2FIX(dat->l.jd);
}
}
+static VALUE
+d_right_mjd(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return rt_jd_to_mjd(d_right_jd(self));
+}
+
/*
* call-seq:
* d.mjd
@@ -1655,13 +3768,21 @@ d_lite_mjd(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("mjd_r");
+ return c_iforward0(mjd);
{
get_d_jd(dat);
return LONG2NUM(dat->l.jd - 2400001L);
}
}
+static VALUE
+d_right_ld(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return rt_jd_to_ld(d_right_jd(self));
+}
+
/*
* call-seq:
* d.ld
@@ -1673,13 +3794,27 @@ d_lite_ld(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("ld_r");
+ return c_iforward0(ld);
{
get_d_jd(dat);
return LONG2NUM(dat->l.jd - 2299160L);
}
}
+static VALUE
+d_right_civil(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(civil, rt_jd_to_civil(d_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+d_right_year(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[0];
+}
+
/*
* call-seq:
* d.year
@@ -1691,13 +3826,27 @@ d_lite_year(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("year_r");
+ return c_iforward0(year);
{
get_d_civil(dat);
return INT2FIX(dat->l.year);
}
}
+static VALUE
+d_right_ordinal(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(ordinal, rt_jd_to_ordinal(d_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+d_right_yday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(ordinal))[1];
+}
+
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 }
@@ -1722,13 +3871,19 @@ d_lite_yday(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("yday_r");
+ return c_iforward0(yday);
{
get_d_civil(dat);
return INT2FIX(civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday));
}
}
+static VALUE
+d_right_mon(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[1];
+}
+
/*
* call-seq:
* d.mon
@@ -1742,13 +3897,19 @@ d_lite_mon(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("mon_r");
+ return c_iforward0(mon);
{
get_d_civil(dat);
return INT2FIX(dat->l.mon);
}
}
+static VALUE
+d_right_mday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[2];
+}
+
/*
* call-seq:
* d.mday
@@ -1760,13 +3921,19 @@ d_lite_mday(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("mday_r");
+ return c_iforward0(mday);
{
get_d_civil(dat);
return INT2FIX(dat->l.mday);
}
}
+static VALUE
+d_right_day_fraction(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(daynum))[1];
+}
+
/*
* call-seq:
* d.day_fraction
@@ -1778,18 +3945,33 @@ d_lite_day_fraction(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("day_fraction_r");
+ return c_iforward0(day_fraction);
return INT2FIX(0);
}
static VALUE
+d_right_weeknum0(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(weeknum0, rt_jd_to_weeknum(d_right_jd(self),
+ INT2FIX(0), dat->r.sg));
+}
+
+static VALUE
+d_right_wnum0(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(weeknum0))[1];
+}
+
+static VALUE
d_lite_wnum0(VALUE self)
{
int ry, rw, rd;
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("wnum0_r");
+ return c_iforward0(wnum0);
{
get_d_jd(dat);
jd_to_weeknum(dat->l.jd, 0, dat->l.sg, &ry, &rw, &rd);
@@ -1798,13 +3980,28 @@ d_lite_wnum0(VALUE self)
}
static VALUE
+d_right_weeknum1(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(weeknum1, rt_jd_to_weeknum(d_right_jd(self),
+ INT2FIX(1), dat->r.sg));
+}
+
+static VALUE
+d_right_wnum1(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(weeknum1))[1];
+}
+
+static VALUE
d_lite_wnum1(VALUE self)
{
int ry, rw, rd;
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("wnum1_r");
+ return c_iforward0(wnum1);
{
get_d_jd(dat);
jd_to_weeknum(dat->l.jd, 1, dat->l.sg, &ry, &rw, &rd);
@@ -1812,6 +4009,45 @@ d_lite_wnum1(VALUE self)
}
}
+#ifndef NDEBUG
+static VALUE
+d_right_time(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(time, rt_day_fraction_to_time(d_right_day_fraction(self)));
+}
+#endif
+
+static VALUE
+d_right_time_wo_sf(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(time_wo_sf,
+ rt_day_fraction_to_time_wo_sf(d_right_day_fraction(self)));
+}
+
+static VALUE
+d_right_time_sf(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(time_sf, f_mul(f_mod(d_right_day_fraction(self),
+ SECONDS_IN_DAY),
+ INT2FIX(DAY_IN_SECONDS)));
+}
+
+static VALUE
+d_right_hour(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[0];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[0];
+#endif
+}
+
/*
* call-seq:
* d.hour
@@ -1823,10 +4059,20 @@ d_lite_hour(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("hour_r");
+ return c_iforward0(hour);
return INT2FIX(0);
}
+static VALUE
+d_right_min(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[1];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[1];
+#endif
+}
+
/*
* call-seq:
* d.min
@@ -1839,10 +4085,20 @@ d_lite_min(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("min_r");
+ return c_iforward0(min);
return INT2FIX(0);
}
+static VALUE
+d_right_sec(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[2];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[2];
+#endif
+}
+
/*
* call-seq:
* d.sec
@@ -1855,10 +4111,20 @@ d_lite_sec(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("sec_r");
+ return c_iforward0(sec);
return INT2FIX(0);
}
+static VALUE
+d_right_sec_fraction(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[3];
+#else
+ return c_iforward0(time_sf);
+#endif
+}
+
/*
* call-seq:
* d.sec_fraction
@@ -1871,7 +4137,7 @@ d_lite_sec_fraction(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("sec_fraction_r");
+ return c_iforward0(sec_fraction);
return INT2FIX(0);
}
@@ -1890,6 +4156,36 @@ d_lite_offset(VALUE self)
return INT2FIX(0);
}
+static VALUE
+d_right_zone(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ {
+ int sign;
+ VALUE hh, mm, ss, fr;
+
+ if (f_negative_p(dat->r.of)) {
+ sign = '-';
+ fr = f_abs(dat->r.of);
+ }
+ else {
+ sign = '+';
+ fr = dat->r.of;
+ }
+ ss = f_div(fr, SECONDS_IN_DAY);
+
+ hh = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS));
+ ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS));
+
+ mm = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS));
+
+ return rb_enc_sprintf(rb_usascii_encoding(),
+ "%c%02d:%02d",
+ sign, NUM2INT(hh), NUM2INT(mm));
+ }
+}
+
/*
* call-seq:
* d.zone
@@ -1901,10 +4197,24 @@ d_lite_zone(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("zone_r");
+ return c_iforward0(zone);
return rb_usascii_str_new2("+00:00");
}
+static VALUE
+d_right_commercial(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return_once(commercial, rt_jd_to_commercial(d_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+d_right_cwyear(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[0];
+}
+
/*
* call-seq:
* d.cwyear
@@ -1919,7 +4229,7 @@ d_lite_cwyear(VALUE self)
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("cwyear_r");
+ return c_iforward0(cwyear);
{
get_d_jd(dat);
jd_to_commercial(dat->l.jd, dat->l.sg, &ry, &rw, &rd);
@@ -1927,6 +4237,12 @@ d_lite_cwyear(VALUE self)
}
}
+static VALUE
+d_right_cweek(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[1];
+}
+
/*
* call-seq:
* d.cweek
@@ -1940,7 +4256,7 @@ d_lite_cweek(VALUE self)
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("cweek_r");
+ return c_iforward0(cweek);
{
get_d_jd(dat);
jd_to_commercial(dat->l.jd, dat->l.sg, &ry, &rw, &rd);
@@ -1948,6 +4264,12 @@ d_lite_cweek(VALUE self)
}
}
+static VALUE
+d_right_cwday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[2];
+}
+
/*
* call-seq:
* d.cwday
@@ -1962,7 +4284,7 @@ d_lite_cwday(VALUE self)
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("cwday_r");
+ return c_iforward0(cwday);
{
get_d_jd(dat);
w = jd_to_wday(dat->l.jd);
@@ -1972,6 +4294,12 @@ d_lite_cwday(VALUE self)
}
}
+static VALUE
+d_right_wday(VALUE self)
+{
+ return rt_jd_to_wday(d_right_jd(self));
+}
+
/*
* call-seq:
* d.wday
@@ -1984,7 +4312,7 @@ d_lite_wday(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("wday_r");
+ return c_iforward0(wday);
{
get_d_jd(dat);
return INT2FIX(jd_to_wday(dat->l.jd));
@@ -1993,6 +4321,112 @@ d_lite_wday(VALUE self)
/*
* call-seq:
+ * d.sunday?
+ *
+ * Is the current date Sunday?
+ */
+static VALUE
+d_lite_sunday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(0));
+}
+
+/*
+ * call-seq:
+ * d.monday?
+ *
+ * Is the current date Monday?
+ */
+static VALUE
+d_lite_monday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(1));
+}
+
+/*
+ * call-seq:
+ * d.tuesday?
+ *
+ * Is the current date Tuesday?
+ */
+static VALUE
+d_lite_tuesday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(2));
+}
+
+/*
+ * call-seq:
+ * d.wednesday?
+ *
+ * Is the current date Wednesday?
+ */
+static VALUE
+d_lite_wednesday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(3));
+}
+
+/*
+ * call-seq:
+ * d.thursday?
+ *
+ * Is the current date Thursday?
+ */
+static VALUE
+d_lite_thursday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(4));
+}
+
+/*
+ * call-seq:
+ * d.friday?
+ *
+ * Is the current date Friday?
+ */
+static VALUE
+d_lite_friday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(5));
+}
+
+/*
+ * call-seq:
+ * d.saturday?
+ *
+ * Is the current date Saturday?
+ */
+static VALUE
+d_lite_saturday_p(VALUE self)
+{
+ return f_eqeq_p(d_lite_wday(self), INT2FIX(6));
+}
+
+#ifndef NDEBUG
+static VALUE
+generic_nth_kday_p(VALUE self, VALUE n, VALUE k)
+{
+ if (f_eqeq_p(k, f_wday(self)) &&
+ f_equal_p(f_jd(self), rt_nth_kday_to_jd(f_year(self),
+ f_mon(self),
+ n, k,
+ f_start(self))))
+ return Qtrue;
+ return Qfalse;
+}
+#endif
+
+static VALUE
+d_right_julian_p(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return f_lt_p(d_right_jd(self), dat->r.sg);
+}
+
+/*
+ * call-seq:
* d.julian?
*
* Is the current date old-style (Julian Calendar)?
@@ -2002,10 +4436,18 @@ d_lite_julian_p(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("julian_r?");
+ return c_iforward0(julian_p);
return Qfalse;
}
+static VALUE
+d_right_gregorian_p(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return d_right_julian_p(self) ? Qfalse : Qtrue;
+}
+
/*
* call-seq:
* d.gregorian?
@@ -2017,10 +4459,33 @@ d_lite_gregorian_p(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("gregorian_r?");
+ return c_iforward0(gregorian_p);
return Qtrue;
}
+static VALUE
+d_right_fix_style(VALUE self)
+{
+ if (d_right_julian_p(self))
+ return DBL2NUM(JULIAN);
+ return DBL2NUM(GREGORIAN);
+}
+
+static VALUE
+d_right_leap_p(VALUE self)
+{
+ VALUE style, a;
+
+ style = d_right_fix_style(self);
+ a = rt_jd_to_civil(f_sub(rt_civil_to_jd(d_right_year(self),
+ INT2FIX(3), INT2FIX(1), style),
+ INT2FIX(1)),
+ style);
+ if (f_eqeq_p(RARRAY_PTR(a)[2], INT2FIX(29)))
+ return Qtrue;
+ return Qfalse;
+}
+
/*
* call-seq:
* d.leap?
@@ -2032,7 +4497,7 @@ d_lite_leap_p(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("leap_r?");
+ return c_iforward0(leap_p);
{
get_d_civil(dat);
return leap_p(dat->l.year) ? Qtrue : Qfalse;
@@ -2054,6 +4519,16 @@ d_lite_start(VALUE self)
return DBL2NUM(dat->l.sg);
}
+static VALUE
+d_right_new_start(int argc, VALUE *argv, VALUE self)
+{
+ get_d1(self);
+ return d_right_new(CLASS_OF(self),
+ d_lite_ajd(self),
+ d_lite_offset(self),
+ (argc >= 1) ? argv[0] : INT2FIX(ITALY));
+}
+
/*
* call-seq:
* d.new_start([start=Date::ITALY])
@@ -2069,26 +4544,112 @@ d_lite_new_start(int argc, VALUE *argv, VALUE self)
get_d1(self);
if (!light_mode_p(dat))
- return iforwardv("new_start_r");
+ return c_iforwardv(new_start);
rb_scan_args(argc, argv, "01", &vsg);
- if (!NIL_P(vsg))
+ sg = ITALY;
+ if (argc >= 1)
sg = NUM2DBL(vsg);
- else
- sg = ITALY;
{
get_d_jd(dat);
if (dat->l.jd < sg)
- return iforwardv("new_start_r");
+ return c_iforwardv(new_start);
+
+ return d_lite_new_internal_wo_civil(CLASS_OF(self),
+ dat->l.jd,
+ sg,
+ HAVE_JD);
+ }
+}
+
+/*
+ * call-seq:
+ * d.italy
+ *
+ * Create a copy of this Date object that uses the Italian/Catholic
+ * Day of Calendar Reform.
+ */
+static VALUE
+d_lite_italy(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = INT2FIX(ITALY);
+ return d_lite_new_start(1, argv, self);
+}
+
+/*
+ * call-seq:
+ * d.england
+ *
+ * Create a copy of this Date object that uses the English/Colonial
+ * Day of Calendar Reform.
+ */
+static VALUE
+d_lite_england(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = INT2FIX(ENGLAND);
+ return d_lite_new_start(1, argv, self);
+}
+
+/*
+ * call-seq:
+ * d.julian
+ *
+ * Create a copy of this Date object that always uses the Julian
+ * Calendar.
+ */
+static VALUE
+d_lite_julian(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = DBL2NUM(JULIAN);
+ return d_lite_new_start(1, argv, self);
+}
- return d_lite_s_new_internal_wo_civil(CLASS_OF(self),
- dat->l.jd,
- sg,
- LIGHT_MODE | HAVE_JD);
+/*
+ * call-seq:
+ * d.gregorian
+ *
+ * Create a copy of this Date object that always uses the Gregorian
+ * Calendar.
+ */
+static VALUE
+d_lite_gregorian(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = DBL2NUM(GREGORIAN);
+ return d_lite_new_start(1, argv, self);
+}
+
+static VALUE
+sof2nof(VALUE of)
+{
+ if (TYPE(of) == T_STRING) {
+ VALUE n = date_zone_to_diff(of);
+ if (NIL_P(n))
+ of = INT2FIX(0);
+ else
+ of = rb_rational_new2(n, INT2FIX(DAY_IN_SECONDS));
}
+ else if (TYPE(of) == T_FLOAT) {
+ of = rb_rational_new2(f_truncate(f_mul(of, INT2FIX(DAY_IN_SECONDS))),
+ INT2FIX(DAY_IN_SECONDS));
+ }
+ return of;
+}
+
+static VALUE
+d_right_new_offset(int argc, VALUE *argv, VALUE self)
+{
+ get_d1(self);
+ return d_right_new(CLASS_OF(self),
+ d_lite_ajd(self),
+ (argc >= 1) ? sof2nof(argv[0]) : INT2FIX(0),
+ d_lite_start(self));
}
/*
@@ -2106,25 +4667,42 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self)
get_d1(self);
if (!light_mode_p(dat))
- return iforwardv("new_offset_r");
+ return c_iforwardv(new_offset);
rb_scan_args(argc, argv, "01", &vof);
if (NIL_P(vof))
rof = 0;
else {
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof) || rof != 0)
- return iforwardv("new_offset_r");
+ return c_iforwardv(new_offset);
}
{
get_d_jd(dat);
- return d_lite_s_new_internal_wo_civil(CLASS_OF(self),
- dat->l.jd,
- dat->l.sg,
- LIGHT_MODE | HAVE_JD);
+ return d_lite_new_internal_wo_civil(CLASS_OF(self),
+ dat->l.jd,
+ dat->l.sg,
+ HAVE_JD);
+ }
+}
+
+static VALUE
+d_right_plus(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_d1(self);
+ if (TYPE(other) == T_FLOAT)
+ other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)),
+ day_in_nanoseconds);
+ return d_right_new(CLASS_OF(self),
+ f_add(d_lite_ajd(self), other),
+ d_lite_offset(self),
+ d_lite_start(self));
}
+ rb_raise(rb_eTypeError, "expected numeric");
}
/*
@@ -2147,7 +4725,7 @@ d_lite_plus(VALUE self, VALUE other)
get_d1(self);
if (!light_mode_p(dat))
- return iforwardop("plus_r");
+ return c_iforwardop(plus);
switch (TYPE(other)) {
case T_FIXNUM:
@@ -2159,10 +4737,11 @@ d_lite_plus(VALUE self, VALUE other)
jd = dat->l.jd + FIX2LONG(other);
if (LIGHTABLE_JD(jd) && jd >= dat->l.sg)
- return d_lite_s_new_internal(CLASS_OF(self),
- jd, dat->l.sg,
- 0, 0, 0,
- dat->l.flags & ~HAVE_CIVIL);
+ return d_lite_new_internal(CLASS_OF(self),
+ jd, dat->l.sg,
+ 0, 0, 0,
+ (dat->l.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
}
break;
case T_FLOAT:
@@ -2174,10 +4753,32 @@ d_lite_plus(VALUE self, VALUE other)
}
break;
}
- return iforwardop("plus_r");
+ return c_iforwardop(plus);
}
static VALUE
+d_right_minus(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_d1(self);
+ if (TYPE(other) == T_FLOAT)
+ other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)),
+ day_in_nanoseconds);
+ return d_right_new(CLASS_OF(self),
+ f_sub(d_lite_ajd(self), other),
+ d_lite_offset(self),
+ d_lite_start(self));
+
+ }
+ else if (k_date_p(other)) {
+ return f_sub(d_lite_ajd(self), f_ajd(other));
+ }
+ rb_raise(rb_eTypeError, "expected numeric");
+}
+
+static VALUE dt_right_minus(VALUE, VALUE);
+
+static VALUE
minus_dd(VALUE self, VALUE other)
{
get_dt2_cast(self, other);
@@ -2217,10 +4818,12 @@ minus_dd(VALUE self, VALUE other)
r = f_add(r, rb_rational_new2(INT2FIX(df),
INT2FIX(DAY_IN_SECONDS)));
if (sf)
- r = f_add(r, rb_rational_new2(INT2FIX(sf), day_in_nanoseconds));
+ r = f_add(r, rb_rational_new2(LONG2NUM(sf), day_in_nanoseconds));
return r;
}
- return iforwardop("minus_r");
+ if (!k_datetime_p(self))
+ return d_right_minus(self, other);
+ return dt_right_minus(self, other);
}
/*
@@ -2265,10 +4868,286 @@ d_lite_minus(VALUE self, VALUE other)
case T_FLOAT:
return d_lite_plus(self, DBL2NUM(-NUM2DBL(other)));
}
- return iforwardop("minus_r");
+ return c_iforwardop(minus);
+}
+
+/*
+ * call-seq:
+ * d.next_day([n=1])
+ *
+ * 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])
+ *
+ * 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
+ *
+ * Return a new Date one day after this one.
+ */
+static VALUE
+d_lite_next(VALUE self)
+{
+ return d_lite_next_day(0, (VALUE *)NULL, self);
+}
+
+/*
+ * call-seq:
+ * d >> n
+ *
+ * Return a new Date object that is +n+ months later than
+ * the current one.
+ *
+ * If the day-of-the-month of the current Date is greater
+ * than the last day of the target month, the day-of-the-month
+ * of the returned Date will be the last day of the target month.
+ */
+static VALUE
+d_lite_rshift(VALUE self, VALUE other)
+{
+ VALUE t, y, m, d, sg, j;
+
+ t = f_add3(f_mul(d_lite_year(self), INT2FIX(12)),
+ f_sub(d_lite_mon(self), INT2FIX(1)),
+ other);
+ y = f_idiv(t, INT2FIX(12));
+ m = f_mod(t, INT2FIX(12));
+ m = f_add(m, INT2FIX(1));
+ d = d_lite_mday(self);
+ sg = d_lite_start(self);
+
+ while (NIL_P(j = rt__valid_civil_p(y, m, d, sg))) {
+ d = f_sub(d, INT2FIX(1));
+ if (f_lt_p(d, INT2FIX(1)))
+ rb_raise(rb_eArgError, "invalid date");
+ }
+ return f_add(self, f_sub(j, d_lite_jd(self)));
+}
+
+/*
+ * call-seq:
+ * d << n
+ *
+ * Return a new Date object that is +n+ months earlier than
+ * the current one.
+ *
+ * If the day-of-the-month of the current Date is greater
+ * than the last day of the target month, the day-of-the-month
+ * of the returned Date will be the last day of the target month.
+ */
+static VALUE
+d_lite_lshift(VALUE self, VALUE other)
+{
+ return d_lite_rshift(self, f_negate(other));
+}
+
+/*
+ * call-seq:
+ * d.next_month([n=1])
+ *
+ * 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])
+ *
+ * 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])
+ *
+ * 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])
+ *
+ * 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)));
+}
+
+/*
+ * call-seq:
+ * d.step(limit[, step=1])
+ * d.step(limit[, step=1]){|date| ...}
+ *
+ * Step the current date forward +step+ days at a
+ * time (or backward, if +step+ is negative) until
+ * we reach +limit+ (inclusive), yielding the resultant
+ * date at each step.
+ */
+static VALUE
+generic_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 (f_ge_p(date, limit)) {
+ rb_yield(date);
+ date = f_add(date, step);
+ }
+ break;
+ case 0:
+ while (1)
+ rb_yield(date);
+ break;
+ case 1:
+ while (f_le_p(date, limit)) {
+ rb_yield(date);
+ date = f_add(date, step);
+ }
+ break;
+ default:
+ abort();
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * d.upto(max)
+ * d.upto(max){|date| ...}
+ *
+ * Step forward one day at a time until we reach +max+
+ * (inclusive), yielding each date as we go.
+ */
+static VALUE
+generic_upto(VALUE self, VALUE max)
+{
+ VALUE date;
+
+ RETURN_ENUMERATOR(self, 1, &max);
+
+ date = self;
+ while (f_le_p(date, max)) {
+ rb_yield(date);
+ date = f_add(date, INT2FIX(1));
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * d.downto(min)
+ * d.downto(min){|date| ...}
+ *
+ * Step backward one day at a time until we reach +min+
+ * (inclusive), yielding each date as we go.
+ */
+static VALUE
+generic_downto(VALUE self, VALUE min)
+{
+ VALUE date;
+
+ RETURN_ENUMERATOR(self, 1, &min);
+
+ date = self;
+ while (f_ge_p(date, min)) {
+ rb_yield(date);
+ date = f_add(date, INT2FIX(-1));
+ }
+ return self;
}
static VALUE
+d_right_cmp(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_d1(self);
+ return f_cmp(d_lite_ajd(self), other);
+ }
+ else if (k_date_p(other)) {
+ return f_cmp(d_lite_ajd(self), f_ajd(other));
+ }
+ return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
+}
+
+static VALUE dt_right_cmp(VALUE, VALUE);
+
+static VALUE
cmp_dd(VALUE self, VALUE other)
{
get_dt2_cast(self, other);
@@ -2306,7 +5185,9 @@ cmp_dd(VALUE self, VALUE other)
return INT2FIX(1);
}
}
- return iforwardop("cmp_r");
+ if (!k_datetime_p(self))
+ return d_right_cmp(self, other);
+ return dt_right_cmp(self, other);
}
/*
@@ -2378,9 +5259,24 @@ d_lite_cmp(VALUE self, VALUE other)
}
}
}
- return iforwardop("cmp_r");
+ return c_iforwardop(cmp);
+}
+
+static VALUE
+d_right_equal(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_d1(self);
+ return f_eqeq_p(d_lite_jd(self), other);
+ }
+ else if (k_date_p(other)) {
+ return f_eqeq_p(d_lite_jd(self), f_jd(other));
+ }
+ return rb_num_coerce_cmp(self, other, rb_intern("=="));
}
+static VALUE dt_right_equal(VALUE, VALUE);
+
static VALUE
equal_dd(VALUE self, VALUE other)
{
@@ -2397,7 +5293,9 @@ equal_dd(VALUE self, VALUE other)
return Qtrue;
return Qfalse;
}
- return iforwardop("equal_r");
+ if (!k_datetime_p(self))
+ return d_right_equal(self, other);
+ return dt_right_equal(self, other);
}
/*
@@ -2441,7 +5339,15 @@ d_lite_equal(VALUE self, VALUE other)
}
}
}
- return iforwardop("equal_r");
+ return c_iforwardop(equal);
+}
+
+static VALUE
+d_right_eql_p(VALUE self, VALUE other)
+{
+ if (k_date_p(other) && f_eqeq_p(self, other))
+ return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -2462,7 +5368,7 @@ eql_p_dd(VALUE self, VALUE other)
return Qtrue;
return Qfalse;
}
- return iforwardop("eql_r?");
+ return c_iforwardop(eql_p);
}
/*
@@ -2503,7 +5409,15 @@ d_lite_eql_p(VALUE self, VALUE other)
}
}
}
- return iforwardop("eql_r?");
+ return c_iforwardop(eql_p);
+}
+
+static VALUE
+d_right_hash(VALUE self)
+{
+ get_d1(self);
+ assert(!light_mode_p(dat));
+ return rb_hash(dat->r.ajd);
}
/*
@@ -2517,10 +5431,26 @@ d_lite_hash(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("hash_r");
+ return c_iforward0(hash);
return rb_hash(d_lite_ajd(self));
}
+static VALUE
+d_right_to_s(VALUE self)
+{
+ VALUE a, argv[4];
+
+ get_d1(self);
+ assert(!light_mode_p(dat));
+
+ argv[0] = rb_usascii_str_new2("%.4d-%02d-%02d");
+ a = d_right_civil(self);
+ argv[1] = RARRAY_PTR(a)[0];
+ argv[2] = RARRAY_PTR(a)[1];
+ argv[3] = RARRAY_PTR(a)[2];
+ return rb_f_sprintf(4, argv);
+}
+
/*
* call-seq:
* d.to_s
@@ -2532,7 +5462,7 @@ d_lite_to_s(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("to_s_r");
+ return c_iforward0(to_s);
{
get_d_civil(dat);
return rb_enc_sprintf(rb_usascii_encoding(),
@@ -2541,6 +5471,23 @@ d_lite_to_s(VALUE self)
}
}
+static VALUE
+d_right_inspect(VALUE self)
+{
+ VALUE argv[6];
+
+ get_d1(self);
+ assert(!light_mode_p(dat));
+
+ argv[0] = rb_usascii_str_new2("#<%s[R]: %s (%s,%s,%s)>");
+ argv[1] = rb_class_name(CLASS_OF(self));
+ argv[2] = d_right_to_s(self);
+ argv[3] = dat->r.ajd;
+ argv[4] = dat->r.of;
+ argv[5] = dat->r.sg;
+ return rb_f_sprintf(6, argv);
+}
+
/*
* call-seq:
* d.inspect
@@ -2552,7 +5499,7 @@ d_lite_inspect(VALUE self)
{
get_d1(self);
if (!light_mode_p(dat))
- return iforward0("inspect_r");
+ return c_iforward0(inspect);
{
get_d_civil(dat);
get_d_jd(dat);
@@ -2609,20 +5556,18 @@ d_lite_set_tmx(VALUE self, struct tmx *tmx)
get_d1(self);
if (!light_mode_p(dat)) {
- tmx->year = iforward0("year_r");
- tmx->yday = FIX2INT(iforward0("yday_r"));
- tmx->mon = FIX2INT(iforward0("mon_r"));
- tmx->mday = FIX2INT(iforward0("mday_r"));
- tmx->hour = FIX2INT(iforward0("hour_r"));
- tmx->min = FIX2INT(iforward0("min_r"));
- tmx->sec = FIX2INT(iforward0("sec_r"));
- tmx->wday = FIX2INT(iforward0("wday_r"));
- tmx->offset = INT2FIX(0);
- tmx->zone = RSTRING_PTR(iforward0("zone_r"));
- tmx->timev = f_mul(f_sub(dat->r.ajd,
- rb_rational_new2(INT2FIX(4881175),
- INT2FIX(2))),
- INT2FIX(86400));
+ tmx->year = d_right_year(self);
+ tmx->yday = FIX2INT(d_right_yday(self));
+ tmx->mon = FIX2INT(d_right_mon(self));
+ tmx->mday = FIX2INT(d_right_mday(self));
+ tmx->hour = FIX2INT(d_right_hour(self));
+ tmx->min = FIX2INT(d_right_min(self));
+ tmx->sec = FIX2INT(d_right_sec(self));
+ tmx->wday = FIX2INT(d_right_wday(self));
+ tmx->offset = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS));
+ tmx->zone = RSTRING_PTR(d_right_zone(self));
+ tmx->timev = f_mul(f_sub(dat->r.ajd, UNIX_EPOCH_IN_AJD),
+ INT2FIX(DAY_IN_SECONDS));
}
else {
get_d_jd(dat);
@@ -2639,7 +5584,7 @@ d_lite_set_tmx(VALUE self, struct tmx *tmx)
tmx->offset = INT2FIX(0);
tmx->zone = "+00:00";
tmx->timev = f_mul(INT2FIX(dat->l.jd - 2440588),
- INT2FIX(86400));
+ INT2FIX(DAY_IN_SECONDS));
}
}
@@ -2648,7 +5593,6 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
const char *default_fmt,
void (*func)(VALUE, struct tmx *))
{
- get_d1(self);
{
VALUE vfmt;
const char *fmt;
@@ -2695,6 +5639,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
str = rb_str_new(buf, len);
if (buf != buffer) xfree(buf);
rb_enc_copy(str, vfmt);
+ OBJ_INFECT(str, vfmt);
return str;
}
}
@@ -2712,6 +5657,134 @@ d_lite_strftime(int argc, VALUE *argv, VALUE self)
"%F", d_lite_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
+ * d.ctime
+ *
+ * Equivalent to strftime('%c').
+ * See also asctime(3) or ctime(3).
+ */
+static VALUE
+d_lite_asctime(VALUE self)
+{
+ return strftimev("%c", self, d_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * d.iso8601
+ * d.xmlschema
+ *
+ * Equivalent to strftime('%F').
+ */
+static VALUE
+d_lite_iso8601(VALUE self)
+{
+ return strftimev("%F", self, d_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * d.rfc3339
+ *
+ * Equivalent to strftime('%FT%T%:z').
+ */
+static VALUE
+d_lite_rfc3339(VALUE self)
+{
+ return strftimev("%FT%T%:z", self, d_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * d.rfc2822
+ * d.rfc822
+ *
+ * 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, d_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * d.httpdate
+ *
+ * Equivalent to strftime('%a, %d %b %Y %T GMT').
+ * See also RFC 2616.
+ */
+static VALUE
+d_lite_httpdate(VALUE self)
+{
+ VALUE argv[1], d;
+
+ argv[0] = INT2FIX(0);
+ d = d_lite_new_offset(1, argv, self);
+ return strftimev("%a, %d %b %Y %T GMT", d, d_lite_set_tmx);
+}
+
+static VALUE
+gengo(VALUE jd, VALUE y, VALUE *a)
+{
+ if (f_lt_p(jd, INT2FIX(2405160)))
+ return 0;
+ if (f_lt_p(jd, INT2FIX(2419614))) {
+ a[0] = rb_usascii_str_new2("M%02d");
+ a[1] = f_sub(y, INT2FIX(1867));
+ }
+ else if (f_lt_p(jd, INT2FIX(2424875))) {
+ a[0] = rb_usascii_str_new2("T%02d");
+ a[1] = f_sub(y, INT2FIX(1911));
+ }
+ else if (f_lt_p(jd, INT2FIX(2447535))) {
+ a[0] = rb_usascii_str_new2("S%02d");
+ a[1] = f_sub(y, INT2FIX(1925));
+ }
+ else {
+ a[0] = rb_usascii_str_new2("H%02d");
+ a[1] = f_sub(y, INT2FIX(1988));
+ }
+ return 1;
+}
+
+/*
+ * call-seq:
+ * d.jisx0301
+ *
+ * Return a string as a JIS X 0301 format.
+ */
+static VALUE
+d_lite_jisx0301(VALUE self)
+{
+ VALUE argv[2];
+
+ if (!gengo(d_lite_jd(self),
+ d_lite_year(self),
+ argv))
+ return strftimev("%F", self, d_lite_set_tmx);
+ return f_add(rb_f_sprintf(2, argv),
+ strftimev(".%m.%d", self, d_lite_set_tmx));
+}
+
/*
* call-seq:
* d.marshal_dump
@@ -2783,28 +5856,51 @@ d_lite_marshal_load(VALUE self, VALUE a)
return self;
}
-static VALUE
-d_right_cache(VALUE self)
+/* datetime light */
+
+static void
+dt_right_gc_mark(union DateTimeData *dat)
{
- get_d1(self);
- if (light_mode_p(dat))
- return Qnil;
- return dat->r.cache;
+ assert(!light_mode_p(dat));
+ rb_gc_mark(dat->r.ajd);
+ rb_gc_mark(dat->r.of);
+ rb_gc_mark(dat->r.sg);
+ rb_gc_mark(dat->r.cache);
}
-/* datetime light */
+#define dt_lite_gc_mark 0
+
+inline static VALUE
+dt_right_new_internal(VALUE klass, VALUE ajd, VALUE of, VALUE sg,
+ unsigned flags)
+{
+ union DateTimeData *dat;
+ VALUE obj;
+
+ obj = Data_Make_Struct(klass, union DateTimeData,
+ dt_right_gc_mark, -1, dat);
+
+ dat->r.ajd = ajd;
+ dat->r.of = of;
+ dat->r.sg = sg;
+ dat->r.cache = rb_hash_new();
+ dat->r.flags = flags | DATETIME_OBJ;
+
+ return obj;
+}
inline static VALUE
-dt_lite_s_new_internal(VALUE klass, long jd, int df,
- long sf, int of, double sg,
- int y, int m, int d,
- int h, int min, int s,
- unsigned flags)
+dt_lite_new_internal(VALUE klass, long jd, int df,
+ long sf, int of, double sg,
+ int y, int m, int d,
+ int h, int min, int s,
+ unsigned flags)
{
union DateTimeData *dat;
VALUE obj;
- obj = Data_Make_Struct(klass, union DateTimeData, 0, -1, dat);
+ obj = Data_Make_Struct(klass, union DateTimeData,
+ dt_lite_gc_mark, -1, dat);
dat->l.jd = jd;
dat->l.df = df;
@@ -2817,67 +5913,227 @@ dt_lite_s_new_internal(VALUE klass, long jd, int df,
dat->l.hour = h;
dat->l.min = min;
dat->l.sec = s;
- dat->l.flags = flags;
+ dat->l.flags = flags | LIGHT_MODE | DATETIME_OBJ;
return obj;
}
static VALUE
-dt_lite_s_new_internal_wo_civil(VALUE klass, long jd, int df,
- long sf, int of, double sg,
- unsigned flags)
+dt_lite_new_internal_wo_civil(VALUE klass, long jd, int df,
+ long sf, int of, double sg,
+ unsigned flags)
{
- return dt_lite_s_new_internal(klass, jd, df, sf, of, sg,
+ return dt_lite_new_internal(klass, jd, df, sf, of, sg,
0, 0, 0, 0, 0, 0, flags);
}
static VALUE
dt_lite_s_alloc(VALUE klass)
{
- return dt_lite_s_new_internal_wo_civil(klass, 0, 0, 0, 0, 0, LIGHT_MODE);
+ return dt_lite_new_internal_wo_civil(klass, 0, 0, 0, 0, 0, 0);
}
static VALUE
-dt_lite_s_new_l_bang(int argc, VALUE *argv, VALUE klass)
+dt_right_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg)
{
- VALUE vjd, vdf, vsf, vof, vsg;
- long jd;
+ return dt_right_new_internal(klass, ajd, of, sg, 0);
+}
+
+static VALUE
+dt_lite_new(VALUE klass, VALUE jd, VALUE df, VALUE sf, VALUE of, VALUE sg)
+{
+ return dt_lite_new_internal_wo_civil(klass,
+ NUM2LONG(jd),
+ FIX2INT(df),
+ NUM2LONG(sf),
+ FIX2INT(of),
+ NUM2DBL(sg),
+ HAVE_JD | HAVE_DF);
+}
- rb_scan_args(argc, argv, "05", &vjd, &vdf, &vsf, &vof, &vsg);
+static VALUE
+dt_switch_new(VALUE klass, VALUE ajd, VALUE of, VALUE sg)
+{
+ VALUE t, jd, df, sf, ssf, odf, osf;
- if (argc < 1)
- vjd = INT2FIX(0);
- if (argc < 2)
- vdf = INT2FIX(0);
- if (argc < 3)
- vsf = INT2FIX(0);
- if (argc < 4)
- vof = INT2FIX(0);
- if (argc < 5)
- vsg = INT2FIX(0);
+ t = rt_ajd_to_jd(ajd, INT2FIX(0)); /* as utc */
+ jd = RARRAY_PTR(t)[0];
+ df = RARRAY_PTR(t)[1];
+
+ t = f_mul(df, INT2FIX(DAY_IN_SECONDS));
+ df = f_idiv(t, INT2FIX(1));
+ sf = f_mod(t, INT2FIX(1));
+
+ t = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ sf = f_idiv(t, INT2FIX(1));
+ ssf = f_mod(t, INT2FIX(1));
+
+ t = f_mul(of, INT2FIX(DAY_IN_SECONDS));
+ odf = f_truncate(t);
+ osf = f_remainder(t, INT2FIX(1));
+
+#ifdef FORCE_RIGHT
+ if (1)
+#else
+ if (!FIXNUM_P(jd) ||
+ f_lt_p(jd, sg) || !f_zero_p(ssf) || !f_zero_p(osf) ||
+ !LIGHTABLE_JD(NUM2LONG(jd)))
+#endif
+ return dt_right_new(klass, ajd, of, sg);
+ else
+ return dt_lite_new(klass, jd, df, sf, odf, sg);
+}
+
+#ifndef NDEBUG
+static VALUE
+dt_right_new_m(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ajd, of, sg;
+
+ 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(ITALY);
+ }
+
+ return dt_right_new(klass, ajd, of, sg);
+}
+
+static VALUE
+dt_lite_new_m(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE jd, df, sf, of, sg;
+
+ rb_scan_args(argc, argv, "05", &jd, &df, &sf, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ jd = INT2FIX(0);
+ case 1:
+ df = INT2FIX(0);
+ case 2:
+ sf = INT2FIX(0);
+ case 3:
+ of = INT2FIX(0);
+ case 4:
+ sg = INT2FIX(ITALY);
+ }
+
+ return dt_lite_new(klass, jd, df, sf, of, sg);
+}
+
+static VALUE
+dt_switch_new_m(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ajd, of, sg;
+
+ 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(ITALY);
+ }
+
+ return dt_switch_new(klass, ajd, of, sg);
+}
+#endif
+
+static VALUE
+dt_right_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg)
+{
+ return dt_right_new(klass,
+ rt_jd_to_ajd(jd, fr, of),
+ of,
+ sg);
+}
+
+#ifndef NDEBUG
+static VALUE
+dt_lite_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg)
+{
+ VALUE n, df, sf;
+
+ n = f_mul(fr, INT2FIX(DAY_IN_SECONDS));
+ df = f_idiv(n, INT2FIX(1));
+ sf = f_mod(n, INT2FIX(1));
+ n = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ sf = f_idiv(n, INT2FIX(1));
+ return dt_lite_new(klass, jd, df, sf, of, sg);
+}
+#endif
- if (!FIXNUM_P(vjd) ||
- !FIXNUM_P(vdf) ||
- !FIXNUM_P(vsf) ||
- !FIXNUM_P(vof))
- rb_raise(rb_eArgError, "cannot create");
- jd = NUM2LONG(vjd);
- if (!LIGHTABLE_JD(jd))
- rb_raise(rb_eArgError, "cannot create");
+static VALUE
+dt_switch_new_jd(VALUE klass, VALUE jd, VALUE fr, VALUE of, VALUE sg)
+{
+ return dt_switch_new(klass,
+ rt_jd_to_ajd(jd, fr, of),
+ of,
+ sg);
+}
- return dt_lite_s_new_internal_wo_civil(klass,
- jd,
- FIX2INT(vdf),
- FIX2INT(vsf),
- FIX2INT(vof),
- NUM2DBL(vsg),
- LIGHT_MODE | HAVE_JD | HAVE_DF);
+#ifndef NDEBUG
+static VALUE
+datetime_s_new_r_bang(int argc, VALUE *argv, VALUE klass)
+{
+ return dt_right_new_m(argc, argv, klass);
}
static VALUE
datetime_s_new_l_bang(int argc, VALUE *argv, VALUE klass)
{
- return dt_lite_s_new_l_bang(argc, argv, klass);
+ return dt_lite_new_m(argc, argv, klass);
+}
+
+static VALUE
+datetime_s_new_bang(int argc, VALUE *argv, VALUE klass)
+{
+ return dt_switch_new_m(argc, argv, klass);
+}
+#endif
+
+#undef c_cforwardv
+#define c_cforwardv(m) rt_datetime_s_##m(argc, argv, klass)
+
+static VALUE
+rt_datetime_s_jd(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE jd, h, min, s, of, sg, fr;
+
+ rb_scan_args(argc, argv, "06", &jd, &h, &min, &s, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ jd = INT2FIX(0);
+ case 1:
+ h = INT2FIX(0);
+ case 2:
+ min = INT2FIX(0);
+ case 3:
+ s = INT2FIX(0);
+ case 4:
+ of = INT2FIX(0);
+ case 5:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_jd_p(jd, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
}
/*
@@ -2906,24 +6162,26 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
int h, min, s, rh, rmin, rs, rof;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(jd);
+#endif
+
rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
if (!FIXNUM_P(vjd))
- return cforwardv("jd_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(jd);
jd = h = min = s = 0;
rof = 0;
+ sg = ITALY;
switch (argc) {
case 6:
+ sg = NUM2DBL(vsg);
case 5:
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof))
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
case 4:
s = NUM2INT(vs);
case 3:
@@ -2933,21 +6191,56 @@ datetime_s_jd(int argc, VALUE *argv, VALUE klass)
case 1:
jd = NUM2LONG(vjd);
if (!LIGHTABLE_JD(jd))
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
}
if (jd < sg)
- return cforwardv("jd_r");
+ return c_cforwardv(jd);
if (!valid_time_p(h, min, s, &rh, &rmin, &rs))
rb_raise(rb_eArgError, "invalid date");
- return dt_lite_s_new_internal(klass,
- jd_local_to_utc(jd,
- time_to_df(rh, rmin, rs),
- rof),
- 0, 0, rof, sg, 0, 0, 0, rh, rmin, rs,
- LIGHT_MODE | HAVE_JD | HAVE_TIME);
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg, 0, 0, 0, rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+}
+
+static VALUE
+rt_datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, d, h, min, s, of, sg, jd, fr;
+
+ rb_scan_args(argc, argv, "07", &y, &d, &h, &min, &s, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ d = INT2FIX(1);
+ case 2:
+ h = INT2FIX(0);
+ case 3:
+ min = INT2FIX(0);
+ case 4:
+ s = INT2FIX(0);
+ case 5:
+ of = INT2FIX(0);
+ case 6:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_ordinal_p(y, d, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
}
/*
@@ -2976,6 +6269,10 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
int y, d, rd, h, min, s, rh, rmin, rs, rof;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(ordinal);
+#endif
+
rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
@@ -2983,24 +6280,22 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
(NIL_P(vh) || FIXNUM_P(vh)) &&
(NIL_P(vmin) || FIXNUM_P(vmin)) &&
(NIL_P(vs) || FIXNUM_P(vs))))
- return cforwardv("ordinal_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(ordinal);
y = -4712;
d = 1;
h = min = s = 0;
rof = 0;
+ sg = ITALY;
switch (argc) {
case 7:
+ sg = NUM2DBL(vsg);
case 6:
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof))
- return cforwardv("ordinal_r");
+ return c_cforwardv(ordinal);
case 5:
s = NUM2INT(vs);
case 4:
@@ -3012,7 +6307,7 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("ordinal_r");
+ return c_cforwardv(ordinal);
}
{
@@ -3025,16 +6320,53 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("ordinal_r");
+ return c_cforwardv(ordinal);
+
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg,
+ 0, 0, 0, rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+}
+
+static VALUE
+rt_datetime_s_civil(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, m, d, h, min, s, of, sg, jd, fr;
+
+ rb_scan_args(argc, argv, "08", &y, &m, &d, &h, &min, &s, &of, &sg);
- return dt_lite_s_new_internal(klass,
- jd_local_to_utc(jd,
- time_to_df(rh, rmin, rs),
- rof),
- 0, 0, rof, sg,
- 0, 0, 0, rh, rmin, rs,
- LIGHT_MODE | HAVE_JD | HAVE_TIME);
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ m = INT2FIX(1);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ h = INT2FIX(0);
+ case 4:
+ min = INT2FIX(0);
+ case 5:
+ s = INT2FIX(0);
+ case 6:
+ of = INT2FIX(0);
+ case 7:
+ sg = INT2FIX(ITALY);
}
+
+ jd = rt__valid_civil_p(y, m, d, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
}
/*
@@ -3064,6 +6396,10 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
int y, m, d, rm, rd, h, min, s, rh, rmin, rs, rof;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(civil);
+#endif
+
rb_scan_args(argc, argv, "08", &vy, &vm, &vd, &vh, &vmin, &vs, &vof, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
@@ -3072,12 +6408,7 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
(NIL_P(vh) || FIXNUM_P(vh)) &&
(NIL_P(vmin) || FIXNUM_P(vmin)) &&
(NIL_P(vs) || FIXNUM_P(vs))))
- return cforwardv("civil_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(civil);
y = -4712;
m = 1;
@@ -3085,12 +6416,15 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
h = min = s = 0;
rof = 0;
+ sg = ITALY;
switch (argc) {
case 8:
+ sg = NUM2DBL(vsg);
case 7:
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof))
- return cforwardv("civil_r");
+ return c_cforwardv(civil);
case 6:
s = NUM2INT(vs);
case 5:
@@ -3104,7 +6438,7 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_YEAR(y))
- return cforwardv("civil_r");
+ return c_cforwardv(civil);
}
if (isinf(sg) && sg < 0) {
@@ -3113,9 +6447,9 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
if (!valid_time_p(h, min, s, &rh, &rmin, &rs))
rb_raise(rb_eArgError, "invalid date");
- return dt_lite_s_new_internal(klass, 0, 0, 0, rof, sg,
- y, rm, rd, rh, rmin, rs,
- LIGHT_MODE | HAVE_CIVIL | HAVE_TIME);
+ return dt_lite_new_internal(klass, 0, 0, 0, rof, sg,
+ y, rm, rd, rh, rmin, rs,
+ HAVE_CIVIL | HAVE_TIME);
}
else {
long jd;
@@ -3127,17 +6461,53 @@ datetime_s_civil(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("civil_r");
+ return c_cforwardv(civil);
+
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg,
+ y, rm, rd, rh, rmin, rs,
+ HAVE_JD | HAVE_CIVIL | HAVE_TIME);
+ }
+}
+
+static VALUE
+rt_datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, w, d, h, min, s, of, sg, jd, fr;
- return dt_lite_s_new_internal(klass,
- jd_local_to_utc(jd,
- time_to_df(rh, rmin, rs),
- rof),
- 0, 0, rof, sg,
- y, rm, rd, rh, rmin, rs,
- LIGHT_MODE | HAVE_JD |
- HAVE_CIVIL | HAVE_TIME);
+ rb_scan_args(argc, argv, "08", &y, &w, &d, &h, &min, &s, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ w = INT2FIX(1);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ h = INT2FIX(0);
+ case 4:
+ min = INT2FIX(0);
+ case 5:
+ s = INT2FIX(0);
+ case 6:
+ of = INT2FIX(0);
+ case 7:
+ sg = INT2FIX(ITALY);
}
+
+ jd = rt__valid_commercial_p(y, w, d, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
}
/*
@@ -3167,6 +6537,10 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
int y, w, d, rw, rd, h, min, s, rh, rmin, rs, rof;
double sg;
+#ifdef FORCE_RIGHT
+ return c_cforwardv(commercial);
+#endif
+
rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
@@ -3175,12 +6549,7 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
(NIL_P(vh) || FIXNUM_P(vh)) &&
(NIL_P(vmin) || FIXNUM_P(vmin)) &&
(NIL_P(vs) || FIXNUM_P(vs))))
- return cforwardv("commercial_r");
-
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
- sg = ITALY;
+ return c_cforwardv(commercial);
y = -4712;
w = 1;
@@ -3188,12 +6557,15 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
h = min = s = 0;
rof = 0;
+ sg = ITALY;
switch (argc) {
case 8:
+ sg = NUM2DBL(vsg);
case 7:
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof))
- return cforwardv("commercial_r");
+ return c_cforwardv(commercial);
case 6:
s = NUM2INT(vs);
case 5:
@@ -3207,7 +6579,7 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
case 1:
y = NUM2INT(vy);
if (!LIGHTABLE_CWYEAR(y))
- return cforwardv("commercial_r");
+ return c_cforwardv(commercial);
}
{
@@ -3220,18 +6592,256 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eArgError, "invalid date");
if (!LIGHTABLE_JD(jd) || !ns)
- return cforwardv("commercial_r");
+ return c_cforwardv(commercial);
+
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg,
+ 0, 0, 0, rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+}
+
+#ifndef NDEBUG
+static VALUE
+rt_datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, w, d, f, h, min, s, of, sg, jd, fr;
+
+ rb_scan_args(argc, argv, "09", &y, &w, &d, &f, &h, &min, &s, &of, &sg);
- return dt_lite_s_new_internal(klass,
- jd_local_to_utc(jd,
- time_to_df(rh, rmin, rs),
- rof),
- 0, 0, rof, sg,
- 0, 0, 0, rh, rmin, rs,
- LIGHT_MODE | HAVE_JD | HAVE_TIME);
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ w = INT2FIX(0);
+ case 2:
+ d = INT2FIX(1);
+ case 3:
+ f = INT2FIX(0);
+ case 4:
+ h = INT2FIX(0);
+ case 5:
+ min = INT2FIX(0);
+ case 6:
+ s = INT2FIX(0);
+ case 7:
+ of = INT2FIX(0);
+ case 8:
+ sg = INT2FIX(ITALY);
}
+
+ jd = rt__valid_weeknum_p(y, w, d, f, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
}
+static VALUE
+datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vw, vd, vf, vh, vmin, vs, vof, vsg;
+ int y, w, d, f, rw, rd, h, min, s, rh, rmin, rs, rof;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return c_cforwardv(weeknum);
+#endif
+
+ rb_scan_args(argc, argv, "09", &vy, &vw, &vd, &vf,
+ &vh, &vmin, &vs, &vof, &vsg);
+
+ if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
+ (NIL_P(vw) || FIXNUM_P(vw)) &&
+ (NIL_P(vd) || FIXNUM_P(vd)) &&
+ (NIL_P(vf) || FIXNUM_P(vf)) &&
+ (NIL_P(vh) || FIXNUM_P(vh)) &&
+ (NIL_P(vmin) || FIXNUM_P(vmin)) &&
+ (NIL_P(vs) || FIXNUM_P(vs))))
+ return c_cforwardv(weeknum);
+
+ y = -4712;
+ w = 0;
+ d = 1;
+ f = 0;
+
+ h = min = s = 0;
+ rof = 0;
+ sg = ITALY;
+
+ switch (argc) {
+ case 9:
+ sg = NUM2DBL(vsg);
+ case 8:
+ vof = sof2nof(vof);
+ if (!daydiff_to_sec(vof, &rof))
+ return c_cforwardv(weeknum);
+ case 7:
+ s = NUM2INT(vs);
+ case 6:
+ min = NUM2INT(vmin);
+ case 5:
+ h = NUM2INT(vh);
+ case 4:
+ f = NUM2INT(vf);
+ case 3:
+ d = NUM2INT(vd);
+ case 2:
+ w = NUM2INT(vw);
+ case 1:
+ y = NUM2INT(vy);
+ if (!LIGHTABLE_YEAR(y))
+ return c_cforwardv(weeknum);
+ }
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_weeknum_p(y, w, d, f, sg, &rw, &rd, &jd, &ns))
+ rb_raise(rb_eArgError, "invalid date");
+ if (!valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(rb_eArgError, "invalid date");
+
+ if (!LIGHTABLE_JD(jd) || !ns)
+ return c_cforwardv(weeknum);
+
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg,
+ 0, 0, 0, rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+}
+
+static VALUE
+rt_datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE y, m, n, k, h, min, s, of, sg, jd, fr;
+
+ rb_scan_args(argc, argv, "09", &y, &m, &n, &k, &h, &min, &s, &of, &sg);
+
+ switch (argc) {
+ case 0:
+ y = INT2FIX(-4712);
+ case 1:
+ m = INT2FIX(1);
+ case 2:
+ n = INT2FIX(1);
+ case 3:
+ k = INT2FIX(1);
+ case 4:
+ h = INT2FIX(0);
+ case 5:
+ min = INT2FIX(0);
+ case 6:
+ s = INT2FIX(0);
+ case 7:
+ of = INT2FIX(0);
+ case 8:
+ sg = INT2FIX(ITALY);
+ }
+
+ jd = rt__valid_nth_kday_p(y, m, n, k, sg);
+ fr = rt__valid_time_p(h, min, s);
+
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+
+ of = sof2nof(of);
+
+ return dt_right_new_jd(klass, jd, fr, of, sg);
+}
+
+static VALUE
+datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE vy, vm, vn, vk, vh, vmin, vs, vof, vsg;
+ int y, m, n, k, rm, rn, rk, h, min, s, rh, rmin, rs, rof;
+ double sg;
+
+#ifdef FORCE_RIGHT
+ return c_cforwardv(nth_kday);
+#endif
+
+ rb_scan_args(argc, argv, "09", &vy, &vm, &vn, &vk,
+ &vh, &vmin, &vs, &vof, &vsg);
+
+ if (!((NIL_P(vy) || FIXNUM_P(vy)) &&
+ (NIL_P(vm) || FIXNUM_P(vm)) &&
+ (NIL_P(vn) || FIXNUM_P(vn)) &&
+ (NIL_P(vk) || FIXNUM_P(vk)) &&
+ (NIL_P(vh) || FIXNUM_P(vh)) &&
+ (NIL_P(vmin) || FIXNUM_P(vmin)) &&
+ (NIL_P(vs) || FIXNUM_P(vs))))
+ return c_cforwardv(nth_kday);
+
+ y = -4712;
+ m = 1;
+ n = 1;
+ k = 1;
+
+ h = min = s = 0;
+ rof = 0;
+ sg = ITALY;
+
+ switch (argc) {
+ case 9:
+ sg = NUM2DBL(vsg);
+ case 8:
+ vof = sof2nof(vof);
+ if (!daydiff_to_sec(vof, &rof))
+ return c_cforwardv(nth_kday);
+ case 7:
+ s = NUM2INT(vs);
+ case 6:
+ min = NUM2INT(vmin);
+ case 5:
+ h = NUM2INT(vh);
+ case 4:
+ k = NUM2INT(vk);
+ case 3:
+ n = NUM2INT(vn);
+ case 2:
+ m = NUM2INT(vm);
+ case 1:
+ y = NUM2INT(vy);
+ if (!LIGHTABLE_YEAR(y))
+ return c_cforwardv(nth_kday);
+ }
+
+ {
+ long jd;
+ int ns;
+
+ if (!valid_nth_kday_p(y, m, n, k, sg, &rm, &rn, &rk, &jd, &ns))
+ rb_raise(rb_eArgError, "invalid date");
+ if (!valid_time_p(h, min, s, &rh, &rmin, &rs))
+ rb_raise(rb_eArgError, "invalid date");
+
+ if (!LIGHTABLE_JD(jd) || !ns)
+ return c_cforwardv(nth_kday);
+
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(rh, rmin, rs),
+ rof),
+ 0, 0, rof, sg,
+ 0, 0, 0, rh, rmin, rs,
+ HAVE_JD | HAVE_TIME);
+ }
+}
+#endif
+
/*
* call-seq:
* DateTime.now([start=Date::ITALY])
@@ -3252,15 +6862,15 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
#endif
time_t sec;
struct tm tm;
- long sf;
- int y, m, d, h, min, s, of;
+ long sf, of;
+ int y, m, d, h, min, s;
rb_scan_args(argc, argv, "01", &vsg);
- if (!NIL_P(vsg))
- sg = NUM2DBL(vsg);
- else
+ if (argc < 1)
sg = ITALY;
+ else
+ sg = NUM2DBL(vsg);
#ifdef HAVE_CLOCK_GETTIME
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
@@ -3282,9 +6892,9 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
if (s == 60)
s = 59;
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
- of = (int)tm.tm_gmtoff;
+ of = tm.tm_gmtoff;
#else
- of = (int)-timezone;
+ of = -timezone;
#endif
#ifdef HAVE_CLOCK_GETTIME
sf = ts.tv_nsec;
@@ -3292,28 +6902,67 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
sf = tv.tv_usec * 1000;
#endif
+#ifdef FORCE_RIGHT
+ goto right;
+#endif
+
if (!LIGHTABLE_YEAR(y))
- rb_raise(rb_eArgError, "cannot create");
+ goto right;
+
+ if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS)
+ goto right;
if (isinf(sg) && sg < 0)
- return dt_lite_s_new_internal(klass, 0, 0, sf, of, sg,
- y, m, d, h, min, s,
- LIGHT_MODE | HAVE_CIVIL | HAVE_TIME);
+ return dt_lite_new_internal(klass, 0, 0, sf, (int)of, sg,
+ y, m, d, h, min, s,
+ HAVE_CIVIL | HAVE_TIME);
else {
long jd;
int ns;
civil_to_jd(y, m, d, sg, &jd, &ns);
- return dt_lite_s_new_internal(klass,
- jd_local_to_utc(jd,
- time_to_df(h, min, s),
- of),
- 0, sf, of, sg,
- y, m, d, h, min, s,
- LIGHT_MODE | HAVE_JD |
- HAVE_CIVIL | HAVE_TIME);
+ return dt_lite_new_internal(klass,
+ jd_local_to_utc(jd,
+ time_to_df(h, min, s),
+ of),
+ 0, sf, of, sg,
+ y, m, d, h, min, s,
+ HAVE_JD | HAVE_CIVIL | HAVE_TIME);
}
+ right:
+ {
+ VALUE jd, fr, vof, ajd;
+
+ jd = rt_civil_to_jd(INT2FIX(y), INT2FIX(m), INT2FIX(d), DBL2NUM(sg));
+ fr = rt_time_to_day_fraction(INT2FIX(h), INT2FIX(min), INT2FIX(s));
+ fr = f_add(fr, rb_rational_new(LONG2NUM(sf), day_in_nanoseconds));
+ vof = rb_rational_new(LONG2NUM(of), INT2FIX(DAY_IN_SECONDS));
+ ajd = rt_jd_to_ajd(jd, fr, vof);
+ return dt_right_new(klass, ajd, vof, DBL2NUM(sg));
+ }
+}
+
+static VALUE
+dt_switch_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
+{
+ VALUE jd, fr, of, t;
+
+ hash = rt_rewrite_frags(hash);
+ hash = rt_complete_frags(klass, hash);
+ jd = rt__valid_date_frags_p(hash, sg);
+ fr = rt__valid_time_frags_p(hash);
+ if (NIL_P(jd) || NIL_P(fr))
+ rb_raise(rb_eArgError, "invalid date");
+ t = ref_hash("sec_fraction");
+ if (!NIL_P(t))
+ fr = f_add(fr, f_div(t, INT2FIX(DAY_IN_SECONDS)));
+ t = ref_hash("offset");
+ if (NIL_P(t))
+ of = INT2FIX(0);
+ else
+ of = rb_rational_new2(t, INT2FIX(DAY_IN_SECONDS));
+ return dt_switch_new_jd(klass, jd, fr, of, sg);
}
/*
@@ -3330,6 +6979,272 @@ datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
+ * DateTime.strptime([string="-4712-01-01T00:00:00+00:00"[, format="%FT%T%z"[,start=ITALY]]])
+ *
+ * Create a new DateTime object by parsing from a String
+ * according to a specified format.
+ *
+ * +str+ is a String holding a date-time representation.
+ * +fmt+ is the format that the date-time is in. See
+ * date/format.rb for details on supported formats.
+ *
+ * The default +str+ is '-4712-01-01T00:00:00+00:00', and the default
+ * +fmt+ is '%FT%T%z'. This gives midnight on Julian Day Number day 0.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ *
+ * An ArgumentError will be raised if +str+ cannot be
+ * parsed.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = fmt;
+ hash = date_s__strptime(2, argv2, klass);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * Date.parse(string="-4712-01-01T00:00:00+00:00"[, comp=true[,start=ITALY]])
+ *
+ * Create a new DateTime object by parsing from a String,
+ * without specifying the format.
+ *
+ * +str+ is a String holding a date-time representation.
+ * +comp+ specifies whether to interpret 2-digit years
+ * as 19XX (>= 69) or 20XX (< 69); the default is to.
+ * The method will attempt to parse a date-time from the String
+ * using various heuristics; see #_parse in date/format.rb
+ * for more details. If parsing fails, an ArgumentError
+ * will be raised.
+ *
+ * The default +str+ is '-4712-01-01T00:00:00+00:00'; this is Julian
+ * Day Number day 0.
+ *
+ * +sg+ specifies the Day of Calendar Reform.
+ */
+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(ITALY);
+ }
+
+ {
+ VALUE argv2[2], hash;
+
+ argv2[0] = str;
+ argv2[1] = comp;
+ hash = date_s__parse(2, argv2, klass);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.iso8601(string="-4712-01-01T00:00:00+00:00"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical ISO 8601 format.
+ */
+static VALUE
+datetime_s_iso8601(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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__iso8601(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.rfc3339(string="-4712-01-01T00:00:00+00:00"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical RFC 3339 format.
+ */
+static VALUE
+datetime_s_rfc3339(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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__rfc3339(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.xmlschema(string="-4712-01-01T00:00:00+00:00"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical XML Schema format.
+ */
+static VALUE
+datetime_s_xmlschema(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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__xmlschema(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.rfc2822(string="Mon, 1 Jan -4712 00:00:00 +0000"[,start=ITALY])
+ * DateTime.rfc822(string="Mon, 1 Jan -4712 00:00:00 +0000"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical RFC 2822 format.
+ */
+static VALUE
+datetime_s_rfc2822(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("Mon, 1 Jan -4712 00:00:00 +0000");
+ case 1:
+ comp = Qtrue;
+ case 2:
+ sg = INT2FIX(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__rfc2822(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.httpdate(string="Mon, 01 Jan -4712 00:00:00 GMT"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some RFC 2616 format.
+ */
+static VALUE
+datetime_s_httpdate(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("Mon, 01 Jan -4712 00:00:00 GMT");
+ case 1:
+ comp = Qtrue;
+ case 2:
+ sg = INT2FIX(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__httpdate(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
+ * DateTime.jisx0301(string="-4712-01-01T00:00:00+00:00"[,start=ITALY])
+ *
+ * Create a new Date object by parsing from a String
+ * according to some typical JIS X 0301 format.
+ */
+static VALUE
+datetime_s_jisx0301(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(ITALY);
+ }
+
+ {
+ VALUE hash = date_s__jisx0301(klass, str);
+ return dt_switch_new_by_frags(klass, hash, sg);
+ }
+}
+
+/*
+ * call-seq:
* dt.ajd
*
* Get the date as an Astronomical Julian Day Number.
@@ -3356,6 +7271,21 @@ dt_lite_ajd(VALUE self)
}
}
+#undef c_iforward0
+#undef c_iforwardv
+#undef c_iforwardop
+#define c_iforward0(m) dt_right_##m(self)
+#define c_iforwardv(m) dt_right_##m(argc, argv, self)
+#define c_iforwardop(m) dt_right_##m(self, other)
+
+static VALUE
+dt_right_amjd(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return rt_ajd_to_amjd(dat->r.ajd);
+}
+
/*
* call-seq:
* dt.amjd
@@ -3367,7 +7297,7 @@ dt_lite_amjd(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("amjd_r");
+ return c_iforward0(amjd);
{
VALUE r;
@@ -3384,6 +7314,34 @@ dt_lite_amjd(VALUE self)
}
}
+#undef return_once
+#define return_once(k, expr)\
+{\
+ VALUE id, val;\
+ get_dt1(self);\
+ id = ID2SYM(rb_intern(#k));\
+ val = rb_hash_aref(dat->r.cache, id);\
+ if (!NIL_P(val))\
+ return val;\
+ val = expr;\
+ rb_hash_aset(dat->r.cache, id, val);\
+ return val;\
+}
+
+static VALUE
+dt_right_daynum(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(daynum, rt_ajd_to_jd(dat->r.ajd, dat->r.of));
+}
+
+static VALUE
+dt_right_jd(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(daynum))[0];
+}
+
/*
* call-seq:
* dt.jd
@@ -3395,7 +7353,7 @@ dt_lite_jd(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("jd_r");
+ return c_iforward0(jd);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3403,6 +7361,14 @@ dt_lite_jd(VALUE self)
}
}
+static VALUE
+dt_right_mjd(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return rt_jd_to_mjd(dt_right_jd(self));
+}
+
/*
* call-seq:
* dt.mjd
@@ -3414,7 +7380,7 @@ dt_lite_mjd(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("mjd_r");
+ return c_iforward0(mjd);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3422,6 +7388,14 @@ dt_lite_mjd(VALUE self)
}
}
+static VALUE
+dt_right_ld(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return rt_jd_to_ld(dt_right_jd(self));
+}
+
/*
* call-seq:
* dt.ld
@@ -3433,7 +7407,7 @@ dt_lite_ld(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("ld_r");
+ return c_iforward0(ld);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3441,6 +7415,20 @@ dt_lite_ld(VALUE self)
}
}
+static VALUE
+dt_right_civil(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(civil, rt_jd_to_civil(dt_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+dt_right_year(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[0];
+}
+
/*
* call-seq:
* dt.year
@@ -3452,13 +7440,27 @@ dt_lite_year(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("year_r");
+ return c_iforward0(year);
{
get_dt_civil(dat);
return INT2FIX(dat->l.year);
}
}
+static VALUE
+dt_right_ordinal(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(ordinal, rt_jd_to_ordinal(dt_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+dt_right_yday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(ordinal))[1];
+}
+
/*
* call-seq:
* dt.yday
@@ -3472,13 +7474,19 @@ dt_lite_yday(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("yday_r");
+ return c_iforward0(yday);
{
get_dt_civil(dat);
return INT2FIX(civil_to_yday(dat->l.year, dat->l.mon, dat->l.mday));
}
}
+static VALUE
+dt_right_mon(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[1];
+}
+
/*
* call-seq:
* dt.mon
@@ -3492,13 +7500,19 @@ dt_lite_mon(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("mon_r");
+ return c_iforward0(mon);
{
get_dt_civil(dat);
return INT2FIX(dat->l.mon);
}
}
+static VALUE
+dt_right_mday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(civil))[2];
+}
+
/*
* call-seq:
* dt.mday
@@ -3510,13 +7524,19 @@ dt_lite_mday(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("mday_r");
+ return c_iforward0(mday);
{
get_dt_civil(dat);
return INT2FIX(dat->l.mday);
}
}
+static VALUE
+dt_right_day_fraction(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(daynum))[1];
+}
+
/*
* call-seq:
* dt.day_fraction
@@ -3528,7 +7548,7 @@ dt_lite_day_fraction(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("day_fraction_r");
+ return c_iforward0(day_fraction);
{
get_dt_df(dat);
return rb_rational_new2(INT2FIX(local_df(dat)),
@@ -3537,13 +7557,28 @@ dt_lite_day_fraction(VALUE self)
}
static VALUE
+dt_right_weeknum0(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(weeknum0, rt_jd_to_weeknum(dt_right_jd(self),
+ INT2FIX(0), dat->r.sg));
+}
+
+static VALUE
+dt_right_wnum0(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(weeknum0))[1];
+}
+
+static VALUE
dt_lite_wnum0(VALUE self)
{
int ry, rw, rd;
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("wnum0_r");
+ return c_iforward0(wnum0);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3553,13 +7588,28 @@ dt_lite_wnum0(VALUE self)
}
static VALUE
+dt_right_weeknum1(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(weeknum1, rt_jd_to_weeknum(dt_right_jd(self),
+ INT2FIX(1), dat->r.sg));
+}
+
+static VALUE
+dt_right_wnum1(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(weeknum1))[1];
+}
+
+static VALUE
dt_lite_wnum1(VALUE self)
{
int ry, rw, rd;
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("wnum1_r");
+ return c_iforward0(wnum1);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3568,6 +7618,45 @@ dt_lite_wnum1(VALUE self)
}
}
+#ifndef NDEBUG
+static VALUE
+dt_right_time(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(time, rt_day_fraction_to_time(dt_right_day_fraction(self)));
+}
+#endif
+
+static VALUE
+dt_right_time_wo_sf(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(time_wo_sf,
+ rt_day_fraction_to_time_wo_sf(dt_right_day_fraction(self)));
+}
+
+static VALUE
+dt_right_time_sf(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(time_sf, f_mul(f_mod(dt_right_day_fraction(self),
+ SECONDS_IN_DAY),
+ INT2FIX(DAY_IN_SECONDS)));
+}
+
+static VALUE
+dt_right_hour(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[0];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[0];
+#endif
+}
+
/*
* call-seq:
* dt.hour
@@ -3579,13 +7668,23 @@ dt_lite_hour(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("hour_r");
+ return c_iforward0(hour);
{
get_dt_time(dat);
return INT2FIX(dat->l.hour);
}
}
+static VALUE
+dt_right_min(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[1];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[1];
+#endif
+}
+
/*
* call-seq:
* dt.min
@@ -3598,13 +7697,23 @@ dt_lite_min(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("min_r");
+ return c_iforward0(min);
{
get_dt_time(dat);
return INT2FIX(dat->l.min);
}
}
+static VALUE
+dt_right_sec(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[2];
+#else
+ return RARRAY_PTR(c_iforward0(time_wo_sf))[2];
+#endif
+}
+
/*
* call-seq:
* dt.sec
@@ -3617,13 +7726,23 @@ dt_lite_sec(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("sec_r");
+ return c_iforward0(sec);
{
get_dt_time(dat);
return INT2FIX(dat->l.sec);
}
}
+static VALUE
+dt_right_sec_fraction(VALUE self)
+{
+#if 0
+ return RARRAY_PTR(c_iforward0(time))[3];
+#else
+ return c_iforward0(time_sf);
+#endif
+}
+
/*
* call-seq:
* dt.sec_fraction
@@ -3636,7 +7755,7 @@ dt_lite_sec_fraction(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("sec_fraction_r");
+ return c_iforward0(sec_fraction);
return rb_rational_new2(INT2FIX(dat->l.sf), INT2FIX(SECOND_IN_NANOSECONDS));
}
@@ -3660,8 +7779,38 @@ dt_lite_offset(VALUE self)
int a;\
s = (of < 0) ? '-' : '+';\
a = (of < 0) ? -of : of;\
- h = a / 3600;\
- m = a % 3600 / 60;\
+ h = a / HOUR_IN_SECONDS;\
+ m = a % HOUR_IN_SECONDS / MINUTE_IN_SECONDS;\
+}
+
+static VALUE
+dt_right_zone(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ {
+ int sign;
+ VALUE hh, mm, ss, fr;
+
+ if (f_negative_p(dat->r.of)) {
+ sign = '-';
+ fr = f_abs(dat->r.of);
+ }
+ else {
+ sign = '+';
+ fr = dat->r.of;
+ }
+ ss = f_div(fr, SECONDS_IN_DAY);
+
+ hh = f_idiv(ss, INT2FIX(HOUR_IN_SECONDS));
+ ss = f_mod(ss, INT2FIX(HOUR_IN_SECONDS));
+
+ mm = f_idiv(ss, INT2FIX(MINUTE_IN_SECONDS));
+
+ return rb_enc_sprintf(rb_usascii_encoding(),
+ "%c%02d:%02d",
+ sign, NUM2INT(hh), NUM2INT(mm));
+ }
}
/*
@@ -3677,11 +7826,25 @@ dt_lite_zone(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("zone_r");
+ return c_iforward0(zone);
decode_offset(dat->l.of, s, h, m);
return rb_enc_sprintf(rb_usascii_encoding(), "%c%02d:%02d", s, h, m);
}
+static VALUE
+dt_right_commercial(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return_once(commercial, rt_jd_to_commercial(dt_right_jd(self), dat->r.sg));
+}
+
+static VALUE
+dt_right_cwyear(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[0];
+}
+
/*
* call-seq:
* dt.cwyear
@@ -3696,7 +7859,7 @@ dt_lite_cwyear(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("cwyear_r");
+ return c_iforward0(cwyear);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3705,6 +7868,12 @@ dt_lite_cwyear(VALUE self)
}
}
+static VALUE
+dt_right_cweek(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[1];
+}
+
/*
* call-seq:
* dt.cweek
@@ -3718,7 +7887,7 @@ dt_lite_cweek(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("cweek_r");
+ return c_iforward0(cweek);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3727,6 +7896,12 @@ dt_lite_cweek(VALUE self)
}
}
+static VALUE
+dt_right_cwday(VALUE self)
+{
+ return RARRAY_PTR(c_iforward0(commercial))[2];
+}
+
/*
* call-seq:
* dt.cwday
@@ -3741,7 +7916,7 @@ dt_lite_cwday(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("cwday_r");
+ return c_iforward0(cwday);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3752,6 +7927,12 @@ dt_lite_cwday(VALUE self)
}
}
+static VALUE
+dt_right_wday(VALUE self)
+{
+ return rt_jd_to_wday(dt_right_jd(self));
+}
+
/*
* call-seq:
* dt.wday
@@ -3766,7 +7947,7 @@ dt_lite_wday(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("wday_r");
+ return c_iforward0(wday);
{
get_dt_jd(dat);
get_dt_df(dat);
@@ -3777,6 +7958,98 @@ dt_lite_wday(VALUE self)
/*
* call-seq:
+ * dt.monday?
+ *
+ * Is the current date Monday?
+ */
+static VALUE
+dt_lite_sunday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(0));
+}
+
+/*
+ * call-seq:
+ * dt.monday?
+ *
+ * Is the current date Monday?
+ */
+static VALUE
+dt_lite_monday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(1));
+}
+
+/*
+ * call-seq:
+ * dt.tuesday?
+ *
+ * Is the current date Tuesday?
+ */
+static VALUE
+dt_lite_tuesday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(2));
+}
+
+/*
+ * call-seq:
+ * dt.wednesday?
+ *
+ * Is the current date Wednesday?
+ */
+static VALUE
+dt_lite_wednesday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(3));
+}
+
+/*
+ * call-seq:
+ * dt.thursday?
+ *
+ * Is the current date Thursday?
+ */
+static VALUE
+dt_lite_thursday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(4));
+}
+
+/*
+ * call-seq:
+ * dt.friday?
+ *
+ * Is the current date Friday?
+ */
+static VALUE
+dt_lite_friday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(5));
+}
+
+/*
+ * call-seq:
+ * dt.saturday?
+ *
+ * Is the current date Saturday?
+ */
+static VALUE
+dt_lite_saturday_p(VALUE self)
+{
+ return f_eqeq_p(dt_lite_wday(self), INT2FIX(6));
+}
+
+static VALUE
+dt_right_julian_p(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return f_lt_p(dt_right_jd(self), dat->r.sg);
+}
+
+/*
+ * call-seq:
* dt.julian?
*
* Is the current date old-style (Julian Calendar)?
@@ -3786,10 +8059,18 @@ dt_lite_julian_p(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("julian_r?");
+ return c_iforward0(julian_p);
return Qfalse;
}
+static VALUE
+dt_right_gregorian_p(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return dt_right_julian_p(self) ? Qfalse : Qtrue;
+}
+
/*
* call-seq:
* dt.gregorian?
@@ -3801,10 +8082,33 @@ dt_lite_gregorian_p(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("gregorian_r?");
+ return c_iforward0(gregorian_p);
return Qtrue;
}
+static VALUE
+dt_right_fix_style(VALUE self)
+{
+ if (dt_right_julian_p(self))
+ return DBL2NUM(JULIAN);
+ return DBL2NUM(GREGORIAN);
+}
+
+static VALUE
+dt_right_leap_p(VALUE self)
+{
+ VALUE style, a;
+
+ style = dt_right_fix_style(self);
+ a = rt_jd_to_civil(f_sub(rt_civil_to_jd(dt_right_year(self),
+ INT2FIX(3), INT2FIX(1), style),
+ INT2FIX(1)),
+ style);
+ if (f_eqeq_p(RARRAY_PTR(a)[2], INT2FIX(29)))
+ return Qtrue;
+ return Qfalse;
+}
+
/*
* call-seq:
* dt.leap?
@@ -3816,7 +8120,7 @@ dt_lite_leap_p(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("leap_r?");
+ return c_iforward0(leap_p);
{
get_dt_civil(dat);
return leap_p(dat->l.year) ? Qtrue : Qfalse;
@@ -3838,6 +8142,16 @@ dt_lite_start(VALUE self)
return DBL2NUM(dat->l.sg);
}
+static VALUE
+dt_right_new_start(int argc, VALUE *argv, VALUE self)
+{
+ get_dt1(self);
+ return dt_right_new(CLASS_OF(self),
+ dt_lite_ajd(self),
+ dt_lite_offset(self),
+ (argc >= 1) ? argv[0] : INT2FIX(ITALY));
+}
+
/*
* call-seq:
* dt.new_start([start=Date::ITALY])
@@ -3853,34 +8167,103 @@ dt_lite_new_start(int argc, VALUE *argv, VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforwardv("new_start_r");
+ return c_iforwardv(new_start);
rb_scan_args(argc, argv, "01", &vsg);
- if (!NIL_P(vsg))
+ sg = ITALY;
+ if (argc >= 1)
sg = NUM2DBL(vsg);
- else
- sg = ITALY;
{
get_dt_jd(dat);
get_dt_df(dat);
if (dat->l.jd < sg)
- return iforwardv("new_start_r");
-
- return dt_lite_s_new_internal_wo_civil(CLASS_OF(self),
- dat->l.jd,
- dat->l.df,
- dat->l.sf,
- dat->l.of,
- sg,
- LIGHT_MODE | HAVE_JD | HAVE_DF);
+ return c_iforwardv(new_start);
+
+ return dt_lite_new_internal_wo_civil(CLASS_OF(self),
+ dat->l.jd,
+ dat->l.df,
+ dat->l.sf,
+ dat->l.of,
+ sg,
+ HAVE_JD | HAVE_DF);
}
}
/*
* call-seq:
+ * dt.italy
+ *
+ * Create a copy of this Date object that uses the Italian/Catholic
+ * Day of Calendar Reform.
+ */
+static VALUE
+dt_lite_italy(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = INT2FIX(ITALY);
+ return dt_lite_new_start(1, argv, self);
+}
+
+/*
+ * call-seq:
+ * dt.england
+ *
+ * Create a copy of this Date object that uses the English/Colonial
+ * Day of Calendar Reform.
+ */
+static VALUE
+dt_lite_england(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = INT2FIX(ENGLAND);
+ return dt_lite_new_start(1, argv, self);
+}
+
+/*
+ * call-seq:
+ * dt.julian
+ *
+ * Create a copy of this Date object that always uses the Julian
+ * Calendar.
+ */
+static VALUE
+dt_lite_julian(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = DBL2NUM(JULIAN);
+ return dt_lite_new_start(1, argv, self);
+}
+
+/*
+ * call-seq:
+ * dt.gregorian
+ *
+ * Create a copy of this Date object that always uses the Gregorian
+ * Calendar.
+ */
+static VALUE
+dt_lite_gregorian(VALUE self)
+{
+ VALUE argv[1];
+ argv[0] = DBL2NUM(GREGORIAN);
+ return dt_lite_new_start(1, argv, self);
+}
+
+static VALUE
+dt_right_new_offset(int argc, VALUE *argv, VALUE self)
+{
+ get_dt1(self);
+ return dt_right_new(CLASS_OF(self),
+ dt_lite_ajd(self),
+ (argc >= 1) ? sof2nof(argv[0]) : INT2FIX(0),
+ dt_lite_start(self));
+}
+
+/*
+ * call-seq:
* dt.new_offset([offset=0])
*
* Create a copy of this Date object using a new offset.
@@ -3894,31 +8277,48 @@ dt_lite_new_offset(int argc, VALUE *argv, VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforwardv("new_offset_r");
+ return c_iforwardv(new_offset);
rb_scan_args(argc, argv, "01", &vof);
if (NIL_P(vof))
rof = 0;
else {
+ vof = sof2nof(vof);
if (!daydiff_to_sec(vof, &rof))
- return iforwardv("new_offset_r");
+ return c_iforwardv(new_offset);
}
{
get_dt_jd(dat);
get_dt_df(dat);
- return dt_lite_s_new_internal_wo_civil(CLASS_OF(self),
- dat->l.jd,
- dat->l.df,
- dat->l.sf,
- rof,
- dat->l.sg,
- LIGHT_MODE | HAVE_JD | HAVE_DF);
+ return dt_lite_new_internal_wo_civil(CLASS_OF(self),
+ dat->l.jd,
+ dat->l.df,
+ dat->l.sf,
+ rof,
+ dat->l.sg,
+ HAVE_JD | HAVE_DF);
}
}
+static VALUE
+dt_right_plus(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_dt1(self);
+ if (TYPE(other) == T_FLOAT)
+ other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)),
+ day_in_nanoseconds);
+ return dt_right_new(CLASS_OF(self),
+ f_add(dt_lite_ajd(self), other),
+ dt_lite_offset(self),
+ dt_lite_start(self));
+ }
+ rb_raise(rb_eTypeError, "expected numeric");
+}
+
/*
* call-seq:
* dt + n
@@ -3939,7 +8339,7 @@ dt_lite_plus(VALUE self, VALUE other)
get_dt1(self);
if (!light_mode_p(dat))
- return iforwardop("plus_r");
+ return c_iforwardop(plus);
switch (TYPE(other)) {
case T_FIXNUM:
@@ -3953,17 +8353,18 @@ dt_lite_plus(VALUE self, VALUE other)
jd = dat->l.jd + FIX2LONG(other);
if (LIGHTABLE_JD(jd) && jd >= dat->l.sg)
- return dt_lite_s_new_internal(CLASS_OF(self),
- jd,
- dat->l.df,
- dat->l.sf,
- dat->l.of,
- dat->l.sg,
- 0, 0, 0,
- dat->l.hour,
- dat->l.min,
- dat->l.sec,
- dat->l.flags & ~HAVE_CIVIL);
+ return dt_lite_new_internal(CLASS_OF(self),
+ jd,
+ dat->l.df,
+ dat->l.sf,
+ dat->l.of,
+ dat->l.sg,
+ 0, 0, 0,
+ dat->l.hour,
+ dat->l.min,
+ dat->l.sec,
+ (dat->l.flags | HAVE_JD) &
+ ~HAVE_CIVIL);
}
break;
case T_FLOAT:
@@ -4022,23 +8423,43 @@ dt_lite_plus(VALUE self, VALUE other)
jd = dat->l.jd + jd;
if (LIGHTABLE_JD(jd) && jd >= dat->l.sg)
- return dt_lite_s_new_internal(CLASS_OF(self),
- (long)jd,
- df,
- sf,
- dat->l.of,
- dat->l.sg,
- 0, 0, 0,
- dat->l.hour,
- dat->l.min,
- dat->l.sec,
- dat->l.flags &
- ~HAVE_CIVIL &
- ~HAVE_TIME);
+ return dt_lite_new_internal(CLASS_OF(self),
+ (long)jd,
+ df,
+ sf,
+ dat->l.of,
+ dat->l.sg,
+ 0, 0, 0,
+ dat->l.hour,
+ dat->l.min,
+ dat->l.sec,
+ (dat->l.flags |
+ HAVE_JD | HAVE_DF) &
+ ~HAVE_CIVIL &
+ ~HAVE_TIME);
}
break;
}
- return iforwardop("plus_r");
+ return c_iforwardop(plus);
+}
+
+static VALUE
+dt_right_minus(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_dt1(self);
+ if (TYPE(other) == T_FLOAT)
+ other = rb_rational_new2(f_round(f_mul(other, day_in_nanoseconds)),
+ day_in_nanoseconds);
+ return dt_right_new(CLASS_OF(self),
+ f_sub(dt_lite_ajd(self), other),
+ dt_lite_offset(self),
+ dt_lite_start(self));
+ }
+ else if (k_date_p(other)) {
+ return f_sub(dt_lite_ajd(self), f_ajd(other));
+ }
+ rb_raise(rb_eTypeError, "expected numeric");
}
/*
@@ -4067,9 +8488,185 @@ dt_lite_minus(VALUE self, VALUE other)
case T_FLOAT:
return dt_lite_plus(self, DBL2NUM(-NUM2DBL(other)));
}
- return iforwardop("minus_r");
+ return c_iforwardop(minus);
+}
+
+/*
+ * call-seq:
+ * dt.next_day([n=1])
+ *
+ * Equivalent to dt + n.
+ */
+static VALUE
+dt_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 dt_lite_plus(self, n);
+}
+
+/*
+ * call-seq:
+ * dt.prev_day([n=1])
+ *
+ * Equivalent to dt - n.
+ */
+static VALUE
+dt_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 dt_lite_minus(self, n);
+}
+
+/*
+ * call-seq:
+ * dt.next
+ *
+ * Return a new Date one day after this one.
+ */
+static VALUE
+dt_lite_next(VALUE self)
+{
+ return dt_lite_next_day(0, (VALUE *)NULL, self);
+}
+
+/*
+ * call-seq:
+ * dt >> n
+ *
+ * Return a new Date object that is +n+ months later than
+ * the current one.
+ *
+ * If the day-of-the-month of the current Date is greater
+ * than the last day of the target month, the day-of-the-month
+ * of the returned Date will be the last day of the target month.
+ */
+static VALUE
+dt_lite_rshift(VALUE self, VALUE other)
+{
+ VALUE t, y, m, d, sg, j;
+
+ t = f_add3(f_mul(dt_lite_year(self), INT2FIX(12)),
+ f_sub(dt_lite_mon(self), INT2FIX(1)),
+ other);
+ y = f_idiv(t, INT2FIX(12));
+ m = f_mod(t, INT2FIX(12));
+ m = f_add(m, INT2FIX(1));
+ d = dt_lite_mday(self);
+ sg = dt_lite_start(self);
+
+ while (NIL_P(j = rt__valid_civil_p(y, m, d, sg))) {
+ d = f_sub(d, INT2FIX(1));
+ if (f_lt_p(d, INT2FIX(1)))
+ rb_raise(rb_eArgError, "invalid date");
+ }
+ return f_add(self, f_sub(j, dt_lite_jd(self)));
+}
+
+/*
+ * call-seq:
+ * dt << n
+ *
+ * Return a new Date object that is +n+ months earlier than
+ * the current one.
+ *
+ * If the day-of-the-month of the current Date is greater
+ * than the last day of the target month, the day-of-the-month
+ * of the returned Date will be the last day of the target month.
+ */
+static VALUE
+dt_lite_lshift(VALUE self, VALUE other)
+{
+ return dt_lite_rshift(self, f_negate(other));
+}
+
+/*
+ * call-seq:
+ * dt.next_month([n=1])
+ *
+ * Equivalent to dt >> n
+ */
+static VALUE
+dt_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 dt_lite_rshift(self, n);
+}
+
+/*
+ * call-seq:
+ * dt.prev_month([n=1])
+ *
+ * Equivalent to dt << n
+ */
+static VALUE
+dt_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 dt_lite_lshift(self, n);
+}
+
+/*
+ * call-seq:
+ * dt.next_year([n=1])
+ *
+ * Equivalent to dt >> (n * 12)
+ */
+static VALUE
+dt_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 dt_lite_rshift(self, f_mul(n, INT2FIX(12)));
+}
+
+/*
+ * call-seq:
+ * dt.prev_year([n=1])
+ *
+ * Equivalent to dt << (n * 12)
+ */
+static VALUE
+dt_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 dt_lite_lshift(self, f_mul(n, INT2FIX(12)));
}
+static VALUE
+dt_right_cmp(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_dt1(self);
+ return f_cmp(dt_lite_ajd(self), other);
+ }
+ else if (k_date_p(other)) {
+ return f_cmp(dt_lite_ajd(self), f_ajd(other));
+ }
+ return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
+}
/*
* call-seq:
* dt <=> n
@@ -4092,7 +8689,20 @@ dt_lite_cmp(VALUE self, VALUE other)
{
if (k_date_p(other))
return cmp_dd(self, other);
- return iforwardop("cmp_r");
+ return c_iforwardop(cmp);
+}
+
+static VALUE
+dt_right_equal(VALUE self, VALUE other)
+{
+ if (k_numeric_p(other)) {
+ get_dt1(self);
+ return f_eqeq_p(dt_lite_jd(self), other);
+ }
+ else if (k_date_p(other)) {
+ return f_eqeq_p(dt_lite_jd(self), f_jd(other));
+ }
+ return rb_num_coerce_cmp(self, other, rb_intern("=="));
}
/*
@@ -4111,7 +8721,15 @@ dt_lite_equal(VALUE self, VALUE other)
{
if (k_date_p(other))
return equal_dd(self, other);
- return iforwardop("equal_r");
+ return c_iforwardop(equal);
+}
+
+static VALUE
+dt_right_eql_p(VALUE self, VALUE other)
+{
+ if (k_date_p(other) && f_eqeq_p(self, other))
+ return Qtrue;
+ return Qfalse;
}
/*
@@ -4127,7 +8745,15 @@ dt_lite_eql_p(VALUE self, VALUE other)
{
if (k_date_p(other))
return eql_p_dd(self, other);
- return iforwardop("eql_r?");
+ return c_iforwardop(eql_p);
+}
+
+static VALUE
+dt_right_hash(VALUE self)
+{
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+ return rb_hash(dat->r.ajd);
}
/*
@@ -4141,10 +8767,32 @@ dt_lite_hash(VALUE self)
{
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("hash_r");
+ return c_iforward0(hash);
return rb_hash(dt_lite_ajd(self));
}
+static VALUE
+dt_right_to_s(VALUE self)
+{
+ VALUE a, b, c, argv[8];
+
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+
+ argv[0] = rb_usascii_str_new2("%.4d-%02d-%02dT%02d:%02d:%02d%s");
+ a = dt_right_civil(self);
+ b = dt_right_time_wo_sf(self);
+ c = dt_right_zone(self);
+ argv[1] = RARRAY_PTR(a)[0];
+ argv[2] = RARRAY_PTR(a)[1];
+ argv[3] = RARRAY_PTR(a)[2];
+ argv[4] = RARRAY_PTR(b)[0];
+ argv[5] = RARRAY_PTR(b)[1];
+ argv[6] = RARRAY_PTR(b)[2];
+ argv[7] = c;
+ return rb_f_sprintf(8, argv);
+}
+
/*
* call-seq:
* dt.to_s
@@ -4158,7 +8806,7 @@ dt_lite_to_s(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("to_s_r");
+ return c_iforward0(to_s);
{
get_dt_civil(dat);
get_dt_time(dat);
@@ -4171,6 +8819,23 @@ dt_lite_to_s(VALUE self)
}
}
+static VALUE
+dt_right_inspect(VALUE self)
+{
+ VALUE argv[6];
+
+ get_dt1(self);
+ assert(!light_mode_p(dat));
+
+ argv[0] = rb_usascii_str_new2("#<%s[R]: %s (%s,%s,%s)>");
+ argv[1] = rb_class_name(CLASS_OF(self));
+ argv[2] = dt_right_to_s(self);
+ argv[3] = dat->r.ajd;
+ argv[4] = dat->r.of;
+ argv[5] = dat->r.sg;
+ return rb_f_sprintf(6, argv);
+}
+
/*
* call-seq:
* dt.inspect
@@ -4184,7 +8849,7 @@ dt_lite_inspect(VALUE self)
get_dt1(self);
if (!light_mode_p(dat))
- return iforward0("inspect_r");
+ return c_iforward0(inspect);
{
get_dt_civil(dat);
get_dt_time(dat);
@@ -4210,20 +8875,18 @@ dt_lite_set_tmx(VALUE self, struct tmx *tmx)
get_dt1(self);
if (!light_mode_p(dat)) {
- tmx->year = iforward0("year_r");
- tmx->yday = FIX2INT(iforward0("yday_r"));
- tmx->mon = FIX2INT(iforward0("mon_r"));
- tmx->mday = FIX2INT(iforward0("mday_r"));
- tmx->hour = FIX2INT(iforward0("hour_r"));
- tmx->min = FIX2INT(iforward0("min_r"));
- tmx->sec = FIX2INT(iforward0("sec_r"));
- tmx->wday = FIX2INT(iforward0("wday_r"));
- tmx->offset = INT2FIX(0);
- tmx->zone = RSTRING_PTR(iforward0("zone_r"));
- tmx->timev = f_mul(f_sub(dat->r.ajd,
- rb_rational_new2(INT2FIX(4881175),
- INT2FIX(2))),
- INT2FIX(86400));
+ tmx->year = dt_right_year(self);
+ tmx->yday = FIX2INT(dt_right_yday(self));
+ tmx->mon = FIX2INT(dt_right_mon(self));
+ tmx->mday = FIX2INT(dt_right_mday(self));
+ tmx->hour = FIX2INT(dt_right_hour(self));
+ tmx->min = FIX2INT(dt_right_min(self));
+ tmx->sec = FIX2INT(dt_right_sec(self));
+ tmx->wday = FIX2INT(dt_right_wday(self));
+ tmx->offset = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS));
+ tmx->zone = RSTRING_PTR(dt_right_zone(self));
+ tmx->timev = f_mul(f_sub(dat->r.ajd, UNIX_EPOCH_IN_AJD),
+ INT2FIX(DAY_IN_SECONDS));
}
else {
get_dt_jd(dat);
@@ -4241,10 +8904,8 @@ dt_lite_set_tmx(VALUE self, struct tmx *tmx)
tmx->wday = jd_to_wday(local_jd(dat));
tmx->offset = INT2FIX(dat->l.of);
tmx->zone = RSTRING_PTR(dt_lite_zone(self));
- tmx->timev = f_mul(f_sub(dt_lite_ajd(self),
- rb_rational_new2(INT2FIX(4881175),
- INT2FIX(2))),
- INT2FIX(86400));
+ tmx->timev = f_mul(f_sub(dt_lite_ajd(self), UNIX_EPOCH_IN_AJD),
+ INT2FIX(DAY_IN_SECONDS));
}
}
@@ -4261,6 +8922,134 @@ dt_lite_strftime(int argc, VALUE *argv, VALUE self)
"%FT%T%:z", dt_lite_set_tmx);
}
+static VALUE
+dt_lite_iso8601_timediv(VALUE self, VALUE n)
+{
+ VALUE f, fmt;
+
+ if (f_lt_p(n, INT2FIX(1)))
+ f = rb_usascii_str_new2("");
+ else {
+ VALUE argv[3];
+
+ argv[0] = rb_usascii_str_new2(".%0*d");
+ argv[1] = n;
+ argv[2] = f_round(f_div(dt_lite_sec_fraction(self),
+ rb_rational_new2(INT2FIX(1),
+ f_expt(INT2FIX(10), n))));
+ f = rb_f_sprintf(3, argv);
+ }
+ fmt = f_add3(rb_usascii_str_new2("T%T"),
+ f,
+ rb_usascii_str_new2("%:z"));
+ return strftimev(RSTRING_PTR(fmt), self, dt_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * dt.asctime
+ * dt.ctime
+ *
+ * Equivalent to strftime('%c').
+ * See also asctime(3) or ctime(3).
+ */
+static VALUE
+dt_lite_asctime(VALUE self)
+{
+ return strftimev("%c", self, dt_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * dt.iso8601([n=0])
+ * dt.xmlschema([n=0])
+ *
+ * Equivalent to strftime('%FT%T').
+ * The optional argument n is length of fractional seconds.
+ */
+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("%F", self, dt_lite_set_tmx),
+ dt_lite_iso8601_timediv(self, n));
+}
+
+/*
+ * call-seq:
+ * dt.rfc3339([n=0])
+ *
+ * Equivalent to strftime('%FT%T').
+ * The optional argument n is length of fractional seconds.
+ */
+static VALUE
+dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
+{
+ return dt_lite_iso8601(argc, argv, self);
+}
+
+/*
+ * call-seq:
+ * dt.rfc2822
+ * dt.rfc822
+ *
+ * Equivalent to strftime('%a, %-d %b %Y %T %z').
+ */
+static VALUE
+dt_lite_rfc2822(VALUE self)
+{
+ return strftimev("%a, %-d %b %Y %T %z", self, dt_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * dt.httpdate
+ *
+ * Equivalent to strftime('%a, %d %b %Y %T GMT').
+ * See also RFC 2616.
+ */
+static VALUE
+dt_lite_httpdate(VALUE self)
+{
+ VALUE argv[1], d;
+
+ argv[0] = INT2FIX(0);
+ d = dt_lite_new_offset(1, argv, self);
+ return strftimev("%a, %d %b %Y %T GMT", d, dt_lite_set_tmx);
+}
+
+/*
+ * call-seq:
+ * dt.jisx0301
+ *
+ * Return a string as a JIS X 0301 format.
+ */
+static VALUE
+dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
+{
+ VALUE n, argv2[2];
+
+ rb_scan_args(argc, argv, "01", &n);
+
+ if (argc < 1)
+ n = INT2FIX(0);
+
+ if (!gengo(dt_lite_jd(self),
+ dt_lite_year(self),
+ argv2))
+ return f_add(strftimev("%F", self, dt_lite_set_tmx),
+ dt_lite_iso8601_timediv(self, n));
+ return f_add(f_add(rb_f_sprintf(2, argv2),
+ strftimev(".%m.%d", self, dt_lite_set_tmx)),
+ dt_lite_iso8601_timediv(self, n));
+}
+
/*
* call-seq:
* dt.marshal_dump
@@ -4313,12 +9102,12 @@ dt_lite_marshal_load(VALUE self, VALUE a)
dat->r.of = RARRAY_PTR(a)[1];
dat->r.sg = RARRAY_PTR(a)[2];
dat->r.cache = rb_hash_new();
- dat->r.flags = 0;
+ dat->r.flags = DATETIME_OBJ;
break;
case 5:
dat->l.jd = NUM2LONG(RARRAY_PTR(a)[0]);
dat->l.df = FIX2INT(RARRAY_PTR(a)[1]);
- dat->l.sf = FIX2INT(RARRAY_PTR(a)[2]);
+ dat->l.sf = NUM2LONG(RARRAY_PTR(a)[2]);
dat->l.of = FIX2INT(RARRAY_PTR(a)[3]);
dat->l.sg = NUM2DBL(RARRAY_PTR(a)[4]);
dat->l.year = 0;
@@ -4327,7 +9116,7 @@ dt_lite_marshal_load(VALUE self, VALUE a)
dat->l.hour = 0;
dat->l.min = 0;
dat->l.sec = 0;
- dat->l.flags = LIGHT_MODE | HAVE_JD | HAVE_DF;
+ dat->l.flags = LIGHT_MODE | HAVE_JD | HAVE_DF | DATETIME_OBJ;
break;
default:
rb_raise(rb_eTypeError, "invalid size");
@@ -4342,22 +9131,261 @@ dt_lite_marshal_load(VALUE self, VALUE a)
return self;
}
+/* 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
+ *
+ * Return 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
+ *
+ * Return a Date object which denotes self.
+ */
+static VALUE
+time_to_date(VALUE self)
+{
+ VALUE jd;
+
+ jd = rt_civil_to_jd(f_year(self), f_mon(self), f_mday(self),
+ INT2FIX(ITALY));
+ return d_switch_new_jd(cDate, jd, INT2FIX(ITALY));
+}
+
+/*
+ * call-seq:
+ * t.to_datetime
+ *
+ * Return a DateTime object which denotes self.
+ */
+static VALUE
+time_to_datetime(VALUE self)
+{
+ VALUE jd, sec, fr, of;
+
+ jd = rt_civil_to_jd(f_year(self), f_mon(self), f_mday(self),
+ INT2FIX(ITALY));
+ sec = f_sec(self);
+ if (f_gt_p(sec, INT2FIX(59)))
+ sec = INT2FIX(59);
+ fr = rt_time_to_day_fraction(f_hour(self), f_min(self), sec);
+ fr = f_add(fr, rb_Rational(f_subsec(self), INT2FIX(DAY_IN_SECONDS)));
+ of = rb_rational_new2(f_utc_offset(self), INT2FIX(DAY_IN_SECONDS));
+ return dt_switch_new_jd(cDateTime, jd, fr, of, INT2FIX(ITALY));
+}
+
+/*
+ * call-seq:
+ * d.to_time
+ *
+ * Return a Time object which denotes self.
+ */
+static VALUE
+date_to_time(VALUE self)
+{
+ return f_local3(rb_cTime,
+ d_lite_year(self),
+ d_lite_mon(self),
+ d_lite_mday(self));
+}
+
+/*
+ * call-seq:
+ * d.to_date
+ *
+ * Return self;
+ */
+static VALUE
+date_to_date(VALUE self)
+{
+ return self;
+}
+
+/*
+ * call-seq:
+ * d.to_datetime
+ *
+ * Return a DateTime object which denotes self.
+ */
+static VALUE
+date_to_datetime(VALUE self)
+{
+ return dt_switch_new_jd(cDateTime,
+ d_lite_jd(self),
+ INT2FIX(0),
+ d_lite_offset(self),
+ d_lite_start(self));
+}
+
+#ifndef NDEBUG
static VALUE
-dt_right_cache(VALUE self)
+date_to_right(VALUE self)
+{
+ get_d1(self);
+ if (!light_mode_p(dat))
+ return self;
+ return d_right_new(CLASS_OF(self),
+ d_lite_ajd(self),
+ d_lite_offset(self),
+ d_lite_start(self));
+}
+
+static VALUE
+date_to_light(VALUE self)
+{
+ get_d1(self);
+ if (light_mode_p(dat))
+ return self;
+ {
+ VALUE t, jd, df;
+
+ t = rt_ajd_to_jd(dat->r.ajd, INT2FIX(0)); /* as utc */
+ jd = RARRAY_PTR(t)[0];
+ df = RARRAY_PTR(t)[1];
+
+ if (!LIGHTABLE_JD(NUM2LONG(jd)))
+ rb_raise(rb_eRangeError, "jd too big to convert into light");
+
+ if (!f_zero_p(df))
+ rb_warning("day fraction is ignored");
+
+ if (!f_zero_p(dat->r.of))
+ rb_warning("nonzero offset is ignored");
+
+ return d_lite_new(CLASS_OF(self), jd, dat->r.sg);
+ }
+}
+#endif
+
+/*
+ * call-seq:
+ * dt.to_time
+ *
+ * Return a Time object which denotes self.
+ */
+static VALUE
+datetime_to_time(VALUE self)
+{
+ VALUE argv[1], d;
+
+ argv[0] = INT2FIX(0);
+ d = dt_lite_new_offset(1, argv, self);
+ d = f_utc6(rb_cTime,
+ dt_lite_year(d),
+ dt_lite_mon(d),
+ dt_lite_mday(d),
+ dt_lite_hour(d),
+ dt_lite_min(d),
+ f_add(dt_lite_sec(d), dt_lite_sec_fraction(d)));
+ return f_getlocal(d);
+}
+
+/*
+ * call-seq:
+ * dt.to_date
+ *
+ * Return a Date object which denotes self.
+ */
+static VALUE
+datetime_to_date(VALUE self)
+{
+ return d_switch_new_jd(cDate,
+ dt_lite_jd(self),
+ dt_lite_start(self));
+}
+
+/*
+ * call-seq:
+ * dt.to_datetime
+ *
+ * Return self.
+ */
+static VALUE
+datetime_to_datetime(VALUE self)
+{
+ return self;
+}
+
+#ifndef NDEBUG
+static VALUE
+datetime_to_right(VALUE self)
+{
+ get_dt1(self);
+ if (!light_mode_p(dat))
+ return self;
+ return dt_right_new(CLASS_OF(self),
+ dt_lite_ajd(self),
+ dt_lite_offset(self),
+ dt_lite_start(self));
+}
+
+static VALUE
+datetime_to_light(VALUE self)
{
get_dt1(self);
if (light_mode_p(dat))
- return Qnil;
- return dat->r.cache;
+ return self;
+ {
+ VALUE t, jd, df, sf, odf;
+
+ t = rt_ajd_to_jd(dat->r.ajd, INT2FIX(0)); /* as utc */
+ jd = RARRAY_PTR(t)[0];
+ df = RARRAY_PTR(t)[1];
+
+ if (!LIGHTABLE_JD(NUM2LONG(jd)))
+ rb_raise(rb_eRangeError, "jd too big to convert into light");
+
+ if (f_lt_p(dat->r.of, INT2FIX(-1)) ||
+ f_gt_p(dat->r.of, INT2FIX(1)))
+ rb_raise(rb_eRangeError, "offset too big to convert into light");
+
+ t = f_mul(df, INT2FIX(DAY_IN_SECONDS));
+ df = f_idiv(t, INT2FIX(1));
+ sf = f_mod(t, INT2FIX(1));
+
+ t = f_mul(sf, INT2FIX(SECOND_IN_NANOSECONDS));
+ sf = f_idiv(t, INT2FIX(1));
+
+ if (f_eqeq_p(t, sf))
+ rb_warning("second fraction is truncated");
+
+ t = f_mul(dat->r.of, INT2FIX(DAY_IN_SECONDS));
+ odf = f_truncate(t);
+
+ if (f_eqeq_p(t, odf))
+ rb_warning("offset is truncated");
+
+ return dt_lite_new(CLASS_OF(self),
+ jd, df, sf, odf, dat->r.sg);
+ }
}
+#endif
#ifndef NDEBUG
+/* tests */
+
static int
test_civil(long from, long to, double sg)
{
long j;
- fprintf(stderr, "%ld...%ld (%ld) - %.0f\n", from, to, to - from, sg);
+ fprintf(stderr, "test_civil: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
for (j = from; j <= to; j++) {
int y, m, d, ns;
long rj;
@@ -4397,7 +9425,8 @@ test_ordinal(long from, long to, double sg)
{
long j;
- fprintf(stderr, "%ld...%ld (%ld) - %.0f\n", from, to, to - from, sg);
+ fprintf(stderr, "test_ordinal: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
for (j = from; j <= to; j++) {
int y, d, ns;
long rj;
@@ -4437,7 +9466,8 @@ test_commercial(long from, long to, double sg)
{
long j;
- fprintf(stderr, "%ld...%ld (%ld) - %.0f\n", from, to, to - from, sg);
+ fprintf(stderr, "test_commercial: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
for (j = from; j <= to; j++) {
int y, w, d, ns;
long rj;
@@ -4477,7 +9507,8 @@ test_weeknum(long from, long to, int f, double sg)
{
long j;
- fprintf(stderr, "%ld...%ld (%ld) - %.0f\n", from, to, to - from, sg);
+ fprintf(stderr, "test_weeknum: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
for (j = from; j <= to; j++) {
int y, w, d, ns;
long rj;
@@ -4516,13 +9547,13 @@ date_s_test_weeknum(VALUE klass)
return Qtrue;
}
-
static int
test_nth_kday(long from, long to, double sg)
{
long j;
- fprintf(stderr, "%ld...%ld (%ld) - %.0f\n", from, to, to - from, sg);
+ fprintf(stderr, "test_nth_kday: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
for (j = from; j <= to; j++) {
int y, m, n, k, ns;
long rj;
@@ -4557,6 +9588,119 @@ date_s_test_nth_kday(VALUE klass)
return Qtrue;
}
+static int
+print_emesg(VALUE x, VALUE y)
+{
+ VALUE argv[3];
+ argv[0] = rb_usascii_str_new2("%s != %s\n");
+ argv[1] = x;
+ argv[2] = y;
+ return fputs(RSTRING_PTR(rb_f_sprintf(3, argv)), stderr);
+}
+
+static int
+test_d_switch_new(long from, long to, double sg)
+{
+ long j;
+
+ fprintf(stderr, "test_d_switch_new: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ VALUE jd, ajd, rd, sd;
+
+ jd = LONG2NUM(j);
+ ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
+ rd = d_right_new(cDate, ajd, INT2FIX(0), DBL2NUM(sg));
+ sd = d_switch_new(cDate, ajd, INT2FIX(0), DBL2NUM(sg));
+ if (!f_eqeq_p(rd, sd)) {
+ print_emesg(rd, sd);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static VALUE
+date_s_test_d_switch_new(VALUE klass)
+{
+ if (!test_d_switch_new(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_d_switch_new(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_d_switch_new(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_d_switch_new(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_d_switch_new(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_d_switch_new(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
+static int
+test_dt_switch_new(long from, long to, double sg)
+{
+ long j;
+
+ fprintf(stderr, "test_dt_switch_new: %ld...%ld (%ld) - %.0f\n",
+ from, to, to - from, sg);
+ for (j = from; j <= to; j++) {
+ VALUE jd, vof, ajd, rd, sd;
+ int of, df;
+ long sf;
+
+ jd = LONG2NUM(j);
+ ajd = rt_jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
+ rd = dt_right_new(cDateTime, ajd, INT2FIX(0), DBL2NUM(sg));
+ sd = dt_switch_new(cDateTime, ajd, INT2FIX(0), DBL2NUM(sg));
+ if (!f_eqeq_p(rd, sd)) {
+ print_emesg(rd, sd);
+ return 0;
+ }
+
+ of = (int)((labs(j) % (DAY_IN_SECONDS * 2)) - DAY_IN_SECONDS);
+ vof = rb_rational_new2(INT2FIX(of), INT2FIX(DAY_IN_SECONDS));
+ df = time_to_df(4, 5, 6);
+ sf = 123456789L;
+ ajd = rt_jd_to_ajd(jd,
+ f_add(rb_rational_new2(INT2FIX(df),
+ INT2FIX(DAY_IN_SECONDS)),
+ rb_rational_new2(LONG2NUM(sf),
+ day_in_nanoseconds)),
+ vof);
+ rd = dt_right_new(cDateTime, ajd, vof, DBL2NUM(sg));
+ sd = dt_switch_new(cDateTime, ajd, vof, DBL2NUM(sg));
+ if (!f_eqeq_p(rd, sd)) {
+ print_emesg(rd, sd);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static VALUE
+date_s_test_dt_switch_new(VALUE klass)
+{
+ if (!test_dt_switch_new(MIN_JD, MIN_JD + 366, GREGORIAN))
+ return Qfalse;
+ if (!test_dt_switch_new(2305814, 2598007, GREGORIAN))
+ return Qfalse;
+ if (!test_dt_switch_new(MAX_JD - 366, MAX_JD, GREGORIAN))
+ return Qfalse;
+
+ if (!test_dt_switch_new(MIN_JD, MIN_JD + 366, ITALY))
+ return Qfalse;
+ if (!test_dt_switch_new(2305814, 2598007, ITALY))
+ return Qfalse;
+ if (!test_dt_switch_new(MAX_JD - 366, MAX_JD, ITALY))
+ return Qfalse;
+
+ return Qtrue;
+}
+
static VALUE
date_s_test_all(VALUE klass)
{
@@ -4570,10 +9714,237 @@ date_s_test_all(VALUE klass)
return Qfalse;
if (date_s_test_nth_kday(klass) == Qfalse)
return Qfalse;
+ if (date_s_test_d_switch_new(klass) == Qfalse)
+ return Qfalse;
+ if (date_s_test_dt_switch_new(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_str_new2(a[i]);
+ rb_obj_freeze(e);
+ }
+ rb_ary_push(o, e);
+ }
+ rb_obj_freeze(o);
+ return o;
+}
+
+/*
+ * date.rb - date and time library
+ *
+ * Author: Tadayoshi Funaba 1998-2011
+ *
+ * Initial Documentation: William Webber <[email protected]>
+ *
+ * == Overview
+ *
+ * This file provides two classes for working with
+ * dates and times.
+ *
+ * The first class, Date, represents dates.
+ * It works with years, months, weeks, and days.
+ * See the Date class documentation for more details.
+ *
+ * The second, DateTime, extends Date to include hours,
+ * minutes, seconds, and fractions of a second. It
+ * provides basic support for time zones. See the
+ * DateTime class documentation for more details.
+ *
+ * === Ways of calculating the date.
+ *
+ * In common usage, the date is reckoned in years since or
+ * before the Common Era (CE/BCE, also known as AD/BC), then
+ * as a month and day-of-the-month within the current year.
+ * This is known as the *Civil* *Date*, and abbreviated
+ * as +civil+ in the Date class.
+ *
+ * Instead of year, month-of-the-year, and day-of-the-month,
+ * the date can also be reckoned in terms of year and
+ * day-of-the-year. This is known as the *Ordinal* *Date*,
+ * and is abbreviated as +ordinal+ in the Date class. (Note
+ * that referring to this as the Julian date is incorrect.)
+ *
+ * The date can also be reckoned in terms of year, week-of-the-year,
+ * and day-of-the-week. This is known as the *Commercial*
+ * *Date*, and is abbreviated as +commercial+ in the
+ * Date class. The commercial week runs Monday (day-of-the-week
+ * 1) to Sunday (day-of-the-week 7), in contrast to the civil
+ * week which runs Sunday (day-of-the-week 0) to Saturday
+ * (day-of-the-week 6). The first week of the commercial year
+ * starts on the Monday on or before January 1, and the commercial
+ * year itself starts on this Monday, not January 1.
+ *
+ * For scientific purposes, it is convenient to refer to a date
+ * simply as a day count, counting from an arbitrary initial
+ * day. The date first chosen for this was January 1, 4713 BCE.
+ * A count of days from this date is the *Julian* *Day* *Number*
+ * or *Julian* *Date*, which is abbreviated as +jd+ in the
+ * Date class. This is in local time, and counts from midnight
+ * on the initial day. The stricter usage is in UTC, and counts
+ * from midday on the initial day. This is referred to in the
+ * Date class as the *Astronomical* *Julian* *Day* *Number*, and
+ * abbreviated as +ajd+. In the Date class, the Astronomical
+ * Julian Day Number includes fractional days.
+ *
+ * Another absolute day count is the *Modified* *Julian* *Day*
+ * *Number*, which takes November 17, 1858 as its initial day.
+ * This is abbreviated as +mjd+ in the Date class. There
+ * is also an *Astronomical* *Modified* *Julian* *Day* *Number*,
+ * which is in UTC and includes fractional days. This is
+ * abbreviated as +amjd+ in the Date class. Like the Modified
+ * Julian Day Number (and unlike the Astronomical Julian
+ * Day Number), it counts from midnight.
+ *
+ * Alternative calendars such as the Ethiopic Solar Calendar,
+ * the Islamic Lunar Calendar, or the French Revolutionary Calendar
+ * are not supported by the Date class; nor are calendars that
+ * are based on an Era different from the Common Era, such as
+ * the Japanese Era.
+ *
+ * === Calendar Reform
+ *
+ * The standard civil year is 365 days long. However, the
+ * solar year is fractionally longer than this. To account
+ * for this, a *leap* *year* is occasionally inserted. This
+ * is a year with 366 days, the extra day falling on February 29.
+ * In the early days of the civil calendar, every fourth
+ * year without exception was a leap year. This way of
+ * reckoning leap years is the *Julian* *Calendar*.
+ *
+ * However, the solar year is marginally shorter than 365 1/4
+ * days, and so the *Julian* *Calendar* gradually ran slow
+ * over the centuries. To correct this, every 100th year
+ * (but not every 400th year) was excluded as a leap year.
+ * This way of reckoning leap years, which we use today, is
+ * the *Gregorian* *Calendar*.
+ *
+ * The Gregorian Calendar was introduced at different times
+ * in different regions. The day on which it was introduced
+ * for a particular region is the *Day* *of* *Calendar*
+ * *Reform* for that region. This is abbreviated as +sg+
+ * (for Start of Gregorian calendar) in the Date class.
+ *
+ * Two such days are of particular
+ * significance. The first is October 15, 1582, which was
+ * the Day of Calendar Reform for Italy and most Catholic
+ * countries. The second is September 14, 1752, which was
+ * the Day of Calendar Reform for England and its colonies
+ * (including what is now the United States). These two
+ * dates are available as the constants Date::ITALY and
+ * Date::ENGLAND, respectively. (By comparison, Germany and
+ * Holland, less Catholic than Italy but less stubborn than
+ * England, changed over in 1698; Sweden in 1753; Russia not
+ * till 1918, after the Revolution; and Greece in 1923. Many
+ * Orthodox churches still use the Julian Calendar. A complete
+ * list of Days of Calendar Reform can be found at
+ * http://www.polysyllabic.com/GregConv.html.)
+ *
+ * Switching from the Julian to the Gregorian calendar
+ * involved skipping a number of days to make up for the
+ * accumulated lag, and the later the switch was (or is)
+ * done, the more days need to be skipped. So in 1582 in Italy,
+ * 4th October was followed by 15th October, skipping 10 days; in 1752
+ * in England, 2nd September was followed by 14th September, skipping
+ * 11 days; and if I decided to switch from Julian to Gregorian
+ * Calendar this midnight, I would go from 27th July 2003 (Julian)
+ * today to 10th August 2003 (Gregorian) tomorrow, skipping
+ * 13 days. The Date class is aware of this gap, and a supposed
+ * date that would fall in the middle of it is regarded as invalid.
+ *
+ * The Day of Calendar Reform is relevant to all date representations
+ * involving years. It is not relevant to the Julian Day Numbers,
+ * except for converting between them and year-based representations.
+ *
+ * In the Date and DateTime classes, the Day of Calendar Reform or
+ * +sg+ can be specified a number of ways. First, it can be as
+ * the Julian Day Number of the Day of Calendar Reform. Second,
+ * it can be using the constants Date::ITALY or Date::ENGLAND; these
+ * are in fact the Julian Day Numbers of the Day of Calendar Reform
+ * of the respective regions. Third, it can be as the constant
+ * Date::JULIAN, which means to always use the Julian Calendar.
+ * Finally, it can be as the constant Date::GREGORIAN, which means
+ * to always use the Gregorian Calendar.
+ *
+ * Note: in the Julian Calendar, New Years Day was March 25. The
+ * Date class does not follow this convention.
+ *
+ * === Offsets
+ *
+ * DateTime objects support a simple representation
+ * of offsets. Offsets are represented as an offset
+ * from UTC (UTC is not identical GMT; GMT is a historical term),
+ * as a fraction of a day. This offset is the
+ * how much local time is later (or earlier) than UTC.
+ * As you travel east, the offset increases until you
+ * reach the dateline in the middle of the Pacific Ocean;
+ * as you travel west, the offset decreases. This offset
+ * is abbreviated as +of+ in the Date class.
+ *
+ * This simple representation of offsets does not take
+ * into account the common practice of Daylight Savings
+ * Time or Summer Time.
+ *
+ * Most DateTime methods return the date and the
+ * time in local time. The two exceptions are
+ * #ajd() and #amjd(), which return the date and time
+ * in UTC time, including fractional days.
+ *
+ * The Date class does not support offsets, in that
+ * there is no way to create a Date object with non-utc offset.
+ *
+ * == Examples of use
+ *
+ * === Print out the date of every Sunday between two dates.
+ *
+ * def print_sundays(d1, d2)
+ * d1 += 1 until d1.sunday?
+ * d1.step(d2, 7) do |d|
+ * puts d.strftime('%B %-d')
+ * end
+ * end
+ *
+ * print_sundays(Date.new(2003, 4, 8), Date.new(2003, 5, 23))
+ */
void
Init_date_core(void)
{
@@ -4581,19 +9952,105 @@ Init_date_core(void)
rzero = rb_rational_new1(INT2FIX(0));
rhalf = rb_rational_new2(INT2FIX(1), INT2FIX(2));
- day_in_nanoseconds = DAY_IN_NANOSECONDS;
+
+#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(rzero);
rb_gc_register_mark_object(rhalf);
rb_gc_register_mark_object(day_in_nanoseconds);
- /* date */
-
+ /*
+ * Class representing a date.
+ *
+ * See the documentation to the file date.rb for an overview.
+ *
+ * Internally, the date is represented as an Astronomical
+ * Julian Day Number, +ajd+. The Day of Calendar Reform, +sg+, is
+ * also stored, for conversions to other date formats. (There
+ * is also an +of+ field for a time zone offset, but this
+ * is only for the use of the DateTime subclass.)
+ *
+ * A new Date object is created using one of the object creation
+ * class methods named after the corresponding date format, and the
+ * arguments appropriate to that date format; for instance,
+ * Date::civil() (aliased to Date::new()) with year, month,
+ * and day-of-month, or Date::ordinal() with year and day-of-year.
+ * All of these object creation class methods also take the
+ * Day of Calendar Reform as an optional argument.
+ *
+ * Date objects are immutable once created.
+ *
+ * Once a Date has been created, date values
+ * can be retrieved for the different date formats supported
+ * using instance methods. For instance, #mon() gives the
+ * Civil month, #cwday() gives the Commercial day of the week,
+ * and #yday() gives the Ordinal day of the year. Date values
+ * can be retrieved in any format, regardless of what format
+ * was used to create the Date instance.
+ *
+ * The Date class includes the Comparable module, allowing
+ * date objects to be compared and sorted, ranges of dates
+ * to be created, and so forth.
+ */
cDate = rb_define_class("Date", rb_cObject);
+ rb_include_module(cDate, rb_mComparable);
+
+ /*
+ * Full month names, in English. Months count from 1 to 12; a
+ * month's numerical representation indexed into this array
+ * gives the name of that month (hence the first element is nil).
+ */
+ rb_define_const(cDate, "MONTHNAMES", mk_ary_of_str(13, monthnames));
+
+ /* Abbreviated month names, in English. */
+ rb_define_const(cDate, "ABBR_MONTHNAMES",
+ mk_ary_of_str(13, abbr_monthnames));
+
+ /*
+ * Full names of days of the week, in English. Days of the week
+ * count from 0 to 6 (except in the commercial week); a day's numerical
+ * representation indexed into this array gives the name of that day.
+ */
+ rb_define_const(cDate, "DAYNAMES", mk_ary_of_str(7, daynames));
+
+ /* Abbreviated day names, in English. */
+ 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 the 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));
+ /* A constant used to indicate that a Date should always use the
+ * Julian calendar.
+ */
+ rb_define_const(cDate, "JULIAN", DBL2NUM(JULIAN));
+ /* A constant used to indicate that a Date should always use the
+ * Gregorian calendar.
+ */
+ rb_define_const(cDate, "GREGORIAN", DBL2NUM(GREGORIAN));
+
rb_define_alloc_func(cDate, d_lite_s_alloc);
+
+#ifndef NDEBUG
rb_define_singleton_method(cDate, "new_r!", date_s_new_r_bang, -1);
rb_define_singleton_method(cDate, "new_l!", date_s_new_l_bang, -1);
+ rb_define_singleton_method(cDate, "new!", date_s_new_bang, -1);
+#endif
#ifndef NDEBUG
rb_define_private_method(CLASS_OF(cDate), "_valid_jd?",
@@ -4606,6 +10063,10 @@ Init_date_core(void)
date_s__valid_civil_p, -1);
rb_define_private_method(CLASS_OF(cDate), "_valid_commercial?",
date_s__valid_commercial_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "_valid_weeknum?",
+ date_s__valid_weeknum_p, -1);
+ rb_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);
@@ -4616,14 +10077,51 @@ Init_date_core(void)
rb_define_singleton_method(cDate, "valid_commercial?",
date_s_valid_commercial_p, -1);
+#ifndef NDEBUG
+ rb_define_private_method(CLASS_OF(cDate), "valid_weeknum?",
+ date_s_valid_weeknum_p, -1);
+ rb_define_private_method(CLASS_OF(cDate), "valid_nth_kday?",
+ date_s_valid_nth_kday_p, -1);
+ rb_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);
+
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
+ rb_define_singleton_method(cDate, "weeknum", date_s_weeknum, -1);
+ rb_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);
rb_define_method(cDate, "ajd", d_lite_ajd, 0);
rb_define_method(cDate, "amjd", d_lite_amjd, 0);
@@ -4658,17 +10156,50 @@ Init_date_core(void)
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
+ rb_define_method(cDate, "nth_kday?", generic_nth_kday_p, 2);
+#endif
+
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", generic_step, -1);
+ rb_define_method(cDate, "upto", generic_upto, 1);
+ rb_define_method(cDate, "downto", generic_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);
@@ -4678,17 +10209,30 @@ Init_date_core(void)
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);
+
rb_define_method(cDate, "marshal_dump", d_lite_marshal_dump, 0);
rb_define_method(cDate, "marshal_load", d_lite_marshal_load, 1);
- rb_define_private_method(cDate, "__ca__", d_right_cache, 0);
-
/* datetime */
cDateTime = rb_define_class("DateTime", cDate);
rb_define_alloc_func(cDateTime, dt_lite_s_alloc);
+
+#ifndef NDEBUG
+ rb_define_singleton_method(cDateTime, "new_r!", datetime_s_new_r_bang, -1);
rb_define_singleton_method(cDateTime, "new_l!", datetime_s_new_l_bang, -1);
+ rb_define_singleton_method(cDateTime, "new!", datetime_s_new_bang, -1);
+#endif
rb_undef_method(CLASS_OF(cDateTime), "today");
@@ -4698,9 +10242,35 @@ Init_date_core(void)
rb_define_singleton_method(cDateTime, "new", datetime_s_civil, -1);
rb_define_singleton_method(cDateTime, "commercial",
datetime_s_commercial, -1);
+
+#ifndef NDEBUG
+ rb_define_singleton_method(cDateTime, "weeknum",
+ datetime_s_weeknum, -1);
+ rb_define_singleton_method(cDateTime, "nth_kday",
+ datetime_s_nth_kday, -1);
+#endif
+
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);
rb_define_method(cDateTime, "ajd", dt_lite_ajd, 0);
rb_define_method(cDateTime, "amjd", dt_lite_amjd, 0);
@@ -4735,17 +10305,42 @@ Init_date_core(void)
rb_define_method(cDateTime, "wday", dt_lite_wday, 0);
+ rb_define_method(cDateTime, "sunday?", dt_lite_sunday_p, 0);
+ rb_define_method(cDateTime, "monday?", dt_lite_monday_p, 0);
+ rb_define_method(cDateTime, "tuesday?", dt_lite_tuesday_p, 0);
+ rb_define_method(cDateTime, "wednesday?", dt_lite_wednesday_p, 0);
+ rb_define_method(cDateTime, "thursday?", dt_lite_thursday_p, 0);
+ rb_define_method(cDateTime, "friday?", dt_lite_friday_p, 0);
+ rb_define_method(cDateTime, "saturday?", dt_lite_saturday_p, 0);
+
rb_define_method(cDateTime, "julian?", dt_lite_julian_p, 0);
rb_define_method(cDateTime, "gregorian?", dt_lite_gregorian_p, 0);
rb_define_method(cDateTime, "leap?", dt_lite_leap_p, 0);
rb_define_method(cDateTime, "start", dt_lite_start, 0);
rb_define_method(cDateTime, "new_start", dt_lite_new_start, -1);
+ rb_define_method(cDateTime, "italy", dt_lite_italy, 0);
+ rb_define_method(cDateTime, "england", dt_lite_england, 0);
+ rb_define_method(cDateTime, "julian", dt_lite_julian, 0);
+ rb_define_method(cDateTime, "gregorian", dt_lite_gregorian, 0);
rb_define_method(cDateTime, "new_offset", dt_lite_new_offset, -1);
rb_define_method(cDateTime, "+", dt_lite_plus, 1);
rb_define_method(cDateTime, "-", dt_lite_minus, 1);
+ rb_define_method(cDateTime, "next_day", dt_lite_next_day, -1);
+ rb_define_method(cDateTime, "prev_day", dt_lite_prev_day, -1);
+ rb_define_method(cDateTime, "next", dt_lite_next, 0);
+ rb_define_method(cDateTime, "succ", dt_lite_next, 0);
+
+ rb_define_method(cDateTime, ">>", dt_lite_rshift, 1);
+ rb_define_method(cDateTime, "<<", dt_lite_lshift, 1);
+
+ rb_define_method(cDateTime, "next_month", dt_lite_next_month, -1);
+ rb_define_method(cDateTime, "prev_month", dt_lite_prev_month, -1);
+ rb_define_method(cDateTime, "next_year", dt_lite_next_year, -1);
+ rb_define_method(cDateTime, "prev_year", dt_lite_prev_year, -1);
+
rb_define_method(cDateTime, "<=>", dt_lite_cmp, 1);
rb_define_method(cDateTime, "===", dt_lite_equal, 1);
rb_define_method(cDateTime, "eql?", dt_lite_eql_p, 1);
@@ -4755,18 +10350,56 @@ Init_date_core(void)
rb_define_method(cDateTime, "inspect", dt_lite_inspect, 0);
rb_define_method(cDateTime, "strftime", dt_lite_strftime, -1);
+ rb_define_method(cDateTime, "asctime", dt_lite_asctime, 0);
+ rb_define_method(cDateTime, "ctime", dt_lite_asctime, 0);
+ 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, "rfc2822", dt_lite_rfc2822, 0);
+ rb_define_method(cDateTime, "rfc822", dt_lite_rfc2822, 0);
+ rb_define_method(cDateTime, "httpdate", dt_lite_httpdate, 0);
+ rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
+
rb_define_method(cDateTime, "marshal_dump", dt_lite_marshal_dump, 0);
rb_define_method(cDateTime, "marshal_load", dt_lite_marshal_load, 1);
- rb_define_private_method(cDateTime, "__ca__", dt_right_cache, 0);
+ /* 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);
#ifndef NDEBUG
+ rb_define_method(cDate, "to_right", date_to_right, 0);
+ rb_define_method(cDate, "to_light", date_to_light, 0);
+#endif
+
+ 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
+ rb_define_method(cDateTime, "to_right", datetime_to_right, 0);
+ rb_define_method(cDateTime, "to_light", datetime_to_light, 0);
+#endif
+
+#ifndef NDEBUG
+ /* tests */
+
rb_define_singleton_method(cDate, "test_civil", date_s_test_civil, 0);
rb_define_singleton_method(cDate, "test_ordinal", date_s_test_ordinal, 0);
rb_define_singleton_method(cDate, "test_commercial",
date_s_test_commercial, 0);
rb_define_singleton_method(cDate, "test_weeknum", date_s_test_weeknum, 0);
rb_define_singleton_method(cDate, "test_nth_kday", date_s_test_nth_kday, 0);
+ rb_define_singleton_method(cDate, "test_d_switch_new",
+ date_s_test_d_switch_new, 0);
+ rb_define_singleton_method(cDate, "test_dt_switch_new",
+ date_s_test_dt_switch_new, 0);
rb_define_singleton_method(cDate, "test_all", date_s_test_all, 0);
#endif
}