Feature #4068 » stolen_base.patch
| time.c (working copy) | ||
|---|---|---|
|
rb_define_virtual_variable("$find_time_numguess", find_time_numguess_getter, NULL);
|
||
|
#endif
|
||
|
}
|
||
|
#if 1 /* stolen_base - written by tadayoshi funaba 2010 */
|
||
|
VALUE rb_cDate, rb_cDateTime;
|
||
|
static const int monthtab[2][13] = {
|
||
|
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||
|
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||
|
};
|
||
|
static int
|
||
|
last_day_of_month(VALUE y, int m)
|
||
|
{
|
||
|
return monthtab[leap_year_p(NUM2LONG(mod(y, INT2FIX(400)))) ? 0 : 1][m];
|
||
|
}
|
||
|
static VALUE
|
||
|
date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
|
||
|
{
|
||
|
VALUE v[4];
|
||
|
VALUE y;
|
||
|
int m, d;
|
||
|
rb_scan_args(argc, argv, "31", &v[0],&v[1],&v[2],&v[3]);
|
||
|
y = obj2vint(v[0]);
|
||
|
m = obj2int(v[1]);
|
||
|
d = obj2int(v[2]);
|
||
|
{
|
||
|
int last = last_day_of_month(y, m);
|
||
|
if (m < 0)
|
||
|
m = 13 + m;
|
||
|
if (d < 0)
|
||
|
d = last_day_of_month(y, m) + d + 1;
|
||
|
return (!(m < 0 || m > 12 ||
|
||
|
d < 1 || d > last)) ? Qtrue : Qfalse;
|
||
|
}
|
||
|
}
|
||
|
static void
|
||
|
date_validate_vtm(struct vtm *vtm)
|
||
|
{
|
||
|
int last = last_day_of_month(vtm->year, vtm->mon);
|
||
|
if ( vtm->mon < 1 || vtm->mon > 12
|
||
|
|| vtm->mday < 1 || vtm->mday > last
|
||
|
|| vtm->hour < 0 || vtm->hour > 24
|
||
|
|| (vtm->hour == 24 && (vtm->min > 0 || vtm->sec > 0))
|
||
|
|| vtm->min < 0 || vtm->min > 59
|
||
|
|| vtm->sec < 0 || vtm->sec > 59
|
||
|
|| lt(vtm->subsecx, INT2FIX(0)) || ge(vtm->subsecx, INT2FIX(TIME_SCALE))
|
||
|
|| (!NIL_P(vtm->utc_offset) && (validate_utc_offset(vtm->utc_offset), 0)))
|
||
|
rb_raise(rb_eArgError, "invalid date");
|
||
|
}
|
||
|
static VALUE
|
||
|
datetime_init_1(int argc, VALUE *argv, VALUE time)
|
||
|
{
|
||
|
struct vtm vtm;
|
||
|
VALUE v[8];
|
||
|
struct time_object *tobj;
|
||
|
vtm.wday = -1;
|
||
|
vtm.yday = 0;
|
||
|
vtm.zone = "";
|
||
|
/* year mon mday hour min sec off sg */
|
||
|
rb_scan_args(argc, argv, "08", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
|
||
|
vtm.year = NIL_P(v[0]) ? INT2FIX(-4713) : obj2vint(v[0]);
|
||
|
if (NIL_P(v[0])) {
|
||
|
vtm.mon = NIL_P(v[1]) ? 11 : obj2int(v[1]);
|
||
|
vtm.mday = NIL_P(v[2]) ? 24 : obj2int(v[2]);
|
||
|
}
|
||
|
else {
|
||
|
vtm.mon = NIL_P(v[1]) ? 1 : obj2int(v[1]);
|
||
|
vtm.mday = NIL_P(v[2]) ? 1 : obj2int(v[2]);
|
||
|
}
|
||
|
vtm.hour = NIL_P(v[3]) ? 0 : obj2int(v[3]);
|
||
|
vtm.min = NIL_P(v[4]) ? 0 : obj2int(v[4]);
|
||
|
vtm.sec = 0;
|
||
|
vtm.subsecx = INT2FIX(0);
|
||
|
if (!NIL_P(v[5])) {
|
||
|
VALUE sec = num_exact(v[5]);
|
||
|
VALUE subsec;
|
||
|
divmodv(sec, INT2FIX(1), &sec, &subsec);
|
||
|
vtm.sec = NUM2INT(sec);
|
||
|
vtm.subsecx = w2v(rb_time_magnify(v2w(subsec)));
|
||
|
}
|
||
|
vtm.isdst = -1;
|
||
|
vtm.utc_offset = INT2FIX(0);
|
||
|
if (!NIL_P(v[6])) {
|
||
|
VALUE arg = v[6];
|
||
|
vtm.utc_offset = utc_offset_arg(arg);
|
||
|
}
|
||
|
{
|
||
|
if (vtm.mon < 0)
|
||
|
vtm.mon = 13 + vtm.mon;
|
||
|
if (vtm.mday < 0)
|
||
|
vtm.mday = last_day_of_month(vtm.year, vtm.mon) + vtm.mday + 1;
|
||
|
if (vtm.hour < 0)
|
||
|
vtm.hour = 24 + vtm.hour;
|
||
|
if (vtm.min < 0)
|
||
|
vtm.min = 60 + vtm.min;
|
||
|
if (vtm.sec < 0)
|
||
|
vtm.sec = 60 + vtm.sec;
|
||
|
if (vtm.sec == 60)
|
||
|
vtm.sec = 59;
|
||
|
}
|
||
|
date_validate_vtm(&vtm);
|
||
|
time_modify(time);
|
||
|
GetTimeval(time, tobj);
|
||
|
tobj->tm_got=0;
|
||
|
tobj->timew = WINT2FIXWV(0);
|
||
|
{
|
||
|
VALUE off = vtm.utc_offset;
|
||
|
vtm_add_offset(&vtm, neg(off));
|
||
|
vtm.utc_offset = Qnil;
|
||
|
tobj->timew = timegmw_noleapsecond(&vtm);
|
||
|
return time_set_utc_offset(time, off);
|
||
|
}
|
||
|
}
|
||
|
static VALUE
|
||
|
datetime_init(int argc, VALUE *argv, VALUE time)
|
||
|
{
|
||
|
if (argc >= 7 && TYPE(argv[6]) == T_RATIONAL)
|
||
|
argv[6] = rb_funcall(argv[6], '*', 1, INT2FIX(86400));
|
||
|
return datetime_init_1(argc, argv, time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_init_1(int argc, VALUE *argv, VALUE time)
|
||
|
{
|
||
|
VALUE v[8];
|
||
|
/* year mon mday sg */
|
||
|
rb_scan_args(argc, argv, "04", &v[0],&v[1],&v[2],&v[3]);
|
||
|
v[7] = v[3];
|
||
|
v[3] = Qnil;
|
||
|
v[4] = Qnil;
|
||
|
v[5] = Qnil;
|
||
|
v[6] = Qnil;
|
||
|
return datetime_init_1(argc, v, time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_init(int argc, VALUE *argv, VALUE time)
|
||
|
{
|
||
|
return date_init_1(argc, argv, time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_s_civil(int argc, VALUE *argv, VALUE klass)
|
||
|
{
|
||
|
VALUE time = time_s_alloc(klass);
|
||
|
return date_init(argc, argv, time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_s_today_or_now(VALUE klass, int today)
|
||
|
{
|
||
|
struct timespec ts;
|
||
|
#ifdef HAVE_CLOCK_GETTIME
|
||
|
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
|
||
|
rb_sys_fail("clock_gettime");
|
||
|
}
|
||
|
#else
|
||
|
{
|
||
|
struct timeval tv;
|
||
|
if (gettimeofday(&tv, 0) < 0) {
|
||
|
rb_sys_fail("gettimeofday");
|
||
|
}
|
||
|
ts.tv_sec = tv.tv_sec;
|
||
|
ts.tv_nsec = tv.tv_usec * 1000;
|
||
|
}
|
||
|
#endif
|
||
|
{
|
||
|
wideval_t timew = timespec2timew(&ts);
|
||
|
VALUE time = time_s_alloc(klass);
|
||
|
struct vtm vtm;
|
||
|
VALUE v[8];
|
||
|
if (!localtimew(timew, &vtm))
|
||
|
rb_raise(rb_eArgError, "localtime error");
|
||
|
v[0] = vtm.year;
|
||
|
v[1] = INT2FIX(vtm.mon);
|
||
|
v[2] = INT2FIX(vtm.mday);
|
||
|
if (today) {
|
||
|
return date_init(3, v, time);
|
||
|
}
|
||
|
else {
|
||
|
v[3] = INT2FIX(vtm.hour);
|
||
|
v[4] = INT2FIX(vtm.min);
|
||
|
v[5] = rb_funcall(INT2FIX(vtm.sec), '+', 1,
|
||
|
rb_funcall(vtm.subsecx, rb_intern("quo"), 1,
|
||
|
INT2FIX(TIME_SCALE)));
|
||
|
v[6] = vtm.utc_offset;
|
||
|
return datetime_init(7, v, time);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
static VALUE
|
||
|
date_s_today(VALUE klass)
|
||
|
{
|
||
|
return date_s_today_or_now(klass, 1);
|
||
|
}
|
||
|
static VALUE
|
||
|
datetime_s_now(VALUE klass)
|
||
|
{
|
||
|
return date_s_today_or_now(klass, 0);
|
||
|
}
|
||
|
static VALUE
|
||
|
datetime_to_s(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return strftimev("%Y-%m-%dT%H:%M:%S%:z", time);
|
||
|
}
|
||
|
static VALUE
|
||
|
datetime_inspect(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return strftimev("#<DateTime (sb): %Y-%m-%dT%H:%M:%S%:z (%s.%N)>", time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_to_s(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return strftimev("%Y-%m-%d", time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_inspect(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return strftimev("#<Date (sb): %Y-%m-%d (%s.%N)>", time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_add(struct time_object *tobj, VALUE offset, int sign, VALUE klass)
|
||
|
{
|
||
|
VALUE result;
|
||
|
offset = num_exact(offset);
|
||
|
if (sign < 0)
|
||
|
result = time_new_timew(klass, wsub(tobj->timew, rb_time_magnify(v2w(offset))));
|
||
|
else
|
||
|
result = time_new_timew(klass, wadd(tobj->timew, rb_time_magnify(v2w(offset))));
|
||
|
if (TIME_UTC_P(tobj)) {
|
||
|
GetTimeval(result, tobj);
|
||
|
TIME_SET_UTC(tobj);
|
||
|
}
|
||
|
else if (TIME_FIXOFF_P(tobj)) {
|
||
|
VALUE off = tobj->vtm.utc_offset;
|
||
|
GetTimeval(result, tobj);
|
||
|
TIME_SET_FIXOFF(tobj, off);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
static VALUE
|
||
|
date_plus(VALUE time1, VALUE time2)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time1, tobj);
|
||
|
if (IsTimeval(time2)) {
|
||
|
rb_raise(rb_eTypeError, "date + date?");
|
||
|
}
|
||
|
return date_add(tobj, rb_funcall
|
||
|
(time2, '*', 1, INT2FIX(86400)), 1, CLASS_OF(time1));
|
||
|
}
|
||
|
static VALUE
|
||
|
date_minus(VALUE time1, VALUE time2)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time1, tobj);
|
||
|
if (IsTimeval(time2)) {
|
||
|
struct time_object *tobj2;
|
||
|
GetTimeval(time2, tobj2);
|
||
|
return rb_Float(rb_funcall(rb_time_unmagnify_to_float
|
||
|
(wsub(tobj->timew,
|
||
|
tobj2->timew)),
|
||
|
rb_intern("quo"), 1, INT2FIX(86400)));
|
||
|
}
|
||
|
return date_add(tobj, rb_funcall
|
||
|
(time2, '*', 1, INT2FIX(86400)), -1, CLASS_OF(time1));
|
||
|
}
|
||
|
static VALUE
|
||
|
date_succ(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return date_add(tobj, INT2FIX(86400), 1, CLASS_OF(time));
|
||
|
}
|
||
|
static VALUE
|
||
|
date_subsec(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return rb_funcall(quo(w2v(wmod(tobj->timew, WINT2FIXWV(TIME_SCALE))),
|
||
|
INT2FIX(TIME_SCALE)), rb_intern("to_f"), 0);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_astro_num(VALUE time, double epoch)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
VALUE f;
|
||
|
GetTimeval(time, tobj);
|
||
|
f = rb_Float(rb_time_unmagnify_to_float(tobj->timew));
|
||
|
return rb_funcall(rb_funcall(f, rb_intern("fdiv"), 1, INT2FIX(86400)),
|
||
|
'+', 1, DBL2NUM(epoch));
|
||
|
}
|
||
|
static VALUE
|
||
|
date_ajd(VALUE time)
|
||
|
{
|
||
|
return date_astro_num(time, 2440587.5);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_amjd(VALUE time)
|
||
|
{
|
||
|
return date_astro_num(time, 40587.0);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_chrono_num(VALUE time, int epoch)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
VALUE s;
|
||
|
GetTimeval(time, tobj);
|
||
|
s = w2v(wdiv(tobj->timew, WINT2FIXWV(TIME_SCALE)));
|
||
|
s = rb_funcall(s, '+', 1, tobj->vtm.utc_offset);
|
||
|
return rb_funcall(rb_funcall(s, rb_intern("div"), 1,
|
||
|
INT2FIX(86400)), '+', 1,
|
||
|
INT2FIX(epoch));
|
||
|
}
|
||
|
static VALUE
|
||
|
date_jd(VALUE time)
|
||
|
{
|
||
|
return date_chrono_num(time, 2440588);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_mjd(VALUE time)
|
||
|
{
|
||
|
return date_chrono_num(time, 40587);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_ld(VALUE time)
|
||
|
{
|
||
|
return date_chrono_num(time, 141428);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_zone(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
return strftimev("%:z", time);
|
||
|
}
|
||
|
static VALUE
|
||
|
date_utc_offset(VALUE time)
|
||
|
{
|
||
|
struct time_object *tobj;
|
||
|
GetTimeval(time, tobj);
|
||
|
MAKE_TM(time, tobj);
|
||
|
if (TIME_UTC_P(tobj)) {
|
||
|
return INT2FIX(0);
|
||
|
}
|
||
|
else {
|
||
|
return rb_funcall(tobj->vtm.utc_offset,
|
||
|
rb_intern("fdiv"), 1, INT2FIX(86400));
|
||
|
}
|
||
|
}
|
||
|
void
|
||
|
Init_Date(void)
|
||
|
{
|
||
|
#undef rb_intern
|
||
|
#define rb_intern(str) rb_intern_const(str)
|
||
|
rb_cDate = rb_define_class("Date", rb_cObject);
|
||
|
rb_include_module(rb_cDate, rb_mComparable);
|
||
|
rb_define_alloc_func(rb_cDate, time_s_alloc);
|
||
|
rb_define_singleton_method(rb_cDate, "valid_civil?", date_s_valid_civil_p, -1);
|
||
|
rb_define_singleton_method(rb_cDate, "valid_date?", date_s_valid_civil_p, -1);
|
||
|
rb_define_singleton_method(rb_cDate, "civil", date_s_civil, -1);
|
||
|
rb_define_singleton_method(rb_cDate, "today", date_s_today, 0);
|
||
|
rb_define_method(rb_cDate, "<=>", time_cmp, 1);
|
||
|
rb_define_method(rb_cDate, "eql?", time_eql, 1);
|
||
|
rb_define_method(rb_cDate, "hash", time_hash, 0);
|
||
|
rb_define_method(rb_cDate, "initialize", date_init, -1);
|
||
|
rb_define_method(rb_cDate, "initialize_copy", time_init_copy, 1);
|
||
|
rb_define_method(rb_cDate, "ctime", time_asctime, 0);
|
||
|
rb_define_method(rb_cDate, "asctime", time_asctime, 0);
|
||
|
rb_define_method(rb_cDate, "to_s", date_to_s, 0);
|
||
|
rb_define_method(rb_cDate, "inspect", date_inspect, 0);
|
||
|
rb_define_method(rb_cDate, "+", date_plus, 1);
|
||
|
rb_define_method(rb_cDate, "-", date_minus, 1);
|
||
|
rb_define_method(rb_cDate, "succ", date_succ, 0);
|
||
|
rb_define_method(rb_cDate, "next", date_succ, 0);
|
||
|
rb_define_method(rb_cDate, "mday", time_mday, 0);
|
||
|
rb_define_method(rb_cDate, "day", time_mday, 0);
|
||
|
rb_define_method(rb_cDate, "mon", time_mon, 0);
|
||
|
rb_define_method(rb_cDate, "month", time_mon, 0);
|
||
|
rb_define_method(rb_cDate, "year", time_year, 0);
|
||
|
rb_define_method(rb_cDate, "wday", time_wday, 0);
|
||
|
rb_define_method(rb_cDate, "yday", time_yday, 0);
|
||
|
rb_define_method(rb_cDate, "ajd", date_ajd, 0);
|
||
|
rb_define_method(rb_cDate, "amjd", date_amjd, 0);
|
||
|
rb_define_method(rb_cDate, "jd", date_jd, 0);
|
||
|
rb_define_method(rb_cDate, "mjd", date_mjd, 0);
|
||
|
rb_define_method(rb_cDate, "ld", date_ld, 0);
|
||
|
rb_define_method(rb_cDate, "sunday?", time_sunday, 0);
|
||
|
rb_define_method(rb_cDate, "monday?", time_monday, 0);
|
||
|
rb_define_method(rb_cDate, "tuesday?", time_tuesday, 0);
|
||
|
rb_define_method(rb_cDate, "wednesday?", time_wednesday, 0);
|
||
|
rb_define_method(rb_cDate, "thursday?", time_thursday, 0);
|
||
|
rb_define_method(rb_cDate, "friday?", time_friday, 0);
|
||
|
rb_define_method(rb_cDate, "saturday?", time_saturday, 0);
|
||
|
rb_define_method(rb_cDate, "strftime", time_strftime, 1);
|
||
|
/* methods for marshaling */
|
||
|
rb_define_method(rb_cDate, "_dump", time_dump, -1);
|
||
|
rb_define_singleton_method(rb_cDate, "_load", time_load, 1);
|
||
|
}
|
||
|
void
|
||
|
Init_DateTime(void)
|
||
|
{
|
||
|
rb_cDateTime = rb_define_class("DateTime", rb_cDate);
|
||
|
rb_undef_method(CLASS_OF(rb_cDateTime), "today");
|
||
|
rb_define_singleton_method(rb_cDateTime, "now", datetime_s_now, 0);
|
||
|
rb_define_method(rb_cDateTime, "initialize", datetime_init, -1);
|
||
|
rb_define_method(rb_cDateTime, "initialize_copy", time_init_copy, 1);
|
||
|
rb_define_method(rb_cDateTime, "to_s", datetime_to_s, 0);
|
||
|
rb_define_method(rb_cDateTime, "inspect", datetime_inspect, 0);
|
||
|
rb_define_method(rb_cDateTime, "sec", time_sec, 0);
|
||
|
rb_define_method(rb_cDateTime, "second", time_sec, 0);
|
||
|
rb_define_method(rb_cDateTime, "sec_fraction", date_subsec, 0);
|
||
|
rb_define_method(rb_cDateTime, "second_fraction", date_subsec, 0);
|
||
|
rb_define_method(rb_cDateTime, "min", time_min, 0);
|
||
|
rb_define_method(rb_cDateTime, "minute", time_min, 0);
|
||
|
rb_define_method(rb_cDateTime, "hour", time_hour, 0);
|
||
|
rb_define_method(rb_cDateTime, "zone", date_zone, 0);
|
||
|
rb_define_method(rb_cDateTime, "offset", date_utc_offset, 0);
|
||
|
}
|
||
|
#endif /* stolen_base */
|
||
| inits.c (working copy) | ||
|---|---|---|
|
CALL(IO);
|
||
|
CALL(Dir);
|
||
|
CALL(Time);
|
||
|
CALL(Date);
|
||
|
CALL(DateTime);
|
||
|
CALL(Random);
|
||
|
CALL(signal);
|
||
|
CALL(process);
|
||