Time e$B$G!"%*%V%8%’%/%HKh$KG$0U$N;~:9$r;XDj$G$-$k$h$&$K$9$k$Ne(B
e$B$O$I$&$G$7$g$&$+!#e(B
e$B$?$H$($P!"$R$H$D$NMQK!$H$7$F!“e(B[ruby-core:23036] e$B$G$b=R$Y$^$7e(B
e$B$?$,!“e(Bweb application e$B$G;~9o$r%f!<%6$KI=<($9$k:]!”%f!<%6$N;Xe(B
e$BDj$7$?%?%$%`%>!<%s$,$”$l$P!“e(BTime e$B%*%V%8%’%/%H$K$=$N;~:9$r@_e(B
e$BDj$7$FI=<($K;H$&!”$H$$$&$b$N$,9M$($i$l$^$9!#e(B
e$B$^$?!“J8;zNs$G<u$1<h$C$?;~9o$r!”$=$N;~:9$rJ]B8$7$?$^$^e(B Time
e$B%*%V%8%’%/%H$K$9$k$3$H$b$G$-$k$h$&$K$J$j$^$9!#e(B
e$B$H$j$"$($:e(B API e$B$H$7$F$Oe(B
- e$BF|IU$H;~:9$+$ie(B Time e$B%*%V%8%’%/%H$r@8@.$9$k%a%=%C%I$H!"e(B
- e$B;~:9$rJQ$($?e(B Time e$B%*%V%8%’%/%H$r@8@.$9$k%a%=%C%Ie(B
e$B$,I,MW$G$O$J$$$+$H;W$$$^$9!#e(B
e$B$H$$$&$o$1$G!"$=$l$>$l$KBP1~$9$ke(B
- Time.civil(year, mon, day, hour, min, sec, utc_offset) -> time
- Time#getlocal(utc_offset) -> time
e$B$H$$$&$N$rDI2C$9$k$N$O$I$&$G$7$g$&$+!#e(B
(year e$B0J30$N0z?t$O>JN,2DG=$G$9e(B)
civil e$B$H$$$&$N$O!"e(BDateTime.civil e$B$+$i$H$j$^$7$?!#e(B
Time.local e$B$"$?$j$r3HD%$9$k$3$H$b9M$($?$s$G$9$,!"e(BParseDate
e$BBP1~e(B [ruby-core:761] e$B$H$N7s$M9g$$$G$&$^$$$d$j$+$?$r;W$$$D$-e(B
e$B$^$;$s$G$7$?!#2>$K$=$A$i$G$&$^$$$d$j$+$?$r;W$$$D$$$F:n$k$3$He(B
e$B$K$J$C$?$H$7$F$b!“e(BDateTime e$B$HB?BV$J%a%=%C%I$,$”$k$N$ONI$$$3e(B
e$B$H$@$H;W$$$^$9!#e(B
(e$B$J$*!“e(BDateTime.civil e$B$O$b$&$R$H$De(B start
e$B$H$$$&0z?t$,$”$je(B
e$B$^$9$,!"e(BTime e$B$G$O2~Nq$O07$o$J$$$N$G!“e(BTime.civil
e$B$K$O$”$j$^$;e(B
e$B$s!#e(B)
% svn diff --diff-cmd diff -x ‘-u -p’
Index: time.c
— time.c (revision 23276)
+++ time.c (working copy)
@@ -59,6 +59,7 @@ static const char *find_time_t(struct tm
static struct vtm *localtimev(VALUE timev, struct vtm *result);
static int leap_year_p(long y);
+#define leap_year_v_p(y) leap_year_p(NUM2LONG(mod(v, INT2FIX(400))))
#define NDIV(x,y) (-(-((x)+1)/(y))-1)
#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
@@ -1002,6 +1003,12 @@ struct time_object {
#define TIME_LOCALTIME_P(tobj) ((tobj)->gmt == 0)
#define TIME_SET_LOCALTIME(tobj) ((tobj)->gmt = 0)
+#define TIME_FIXOFF_P(tobj) ((tobj)->gmt == 2)
+#define TIME_SET_FIXOFF(tobj, off) \
- ((tobj)->gmt = 2, \
-
(tobj)->vtm.utc_offset = (off), \
-
(tobj)->vtm.zone = NULL)
#define TIME_COPY_GMT(tobj1, tobj2) ((tobj1)->gmt = (tobj2)->gmt)
static VALUE time_get_tm(VALUE, struct time_object *);
@@ -1452,6 +1459,13 @@ month_arg(VALUE arg)
}
static void
+validate_utc_offset(VALUE utc_offset)
+{
- if (le(utc_offset, INT2FIX(-86400)) || ge(utc_offset,
INT2FIX(86400))) - rb_raise(rb_eArgError, “utc_offset out of range”);
+}
+static void
validate_vtm(struct vtm *vtm)
{
if ( vtm->mon < 1 || vtm->mon > 12
@@ -1460,7 +1474,8 @@ validate_vtm(struct vtm *vtm)
|| (vtm->hour == 24 && (vtm->min > 0 || vtm->sec > 0))
|| vtm->min < 0 || vtm->min > 59
|| vtm->sec < 0 || vtm->sec > 60
- || lt(vtm->subsec, INT2FIX(0)) || ge(vtm->subsec, INT2FIX(1)))
-
|| lt(vtm->subsec, INT2FIX(0)) || ge(vtm->subsec, INT2FIX(1))
-
|| (!NIL_P(vtm->utc_offset) &&
(validate_utc_offset(vtm->utc_offset), 0)))
rb_raise(rb_eArgError, “argument out of range”);
}
@@ -1945,6 +1960,240 @@ time_s_mktime(int argc, VALUE *argv, VAL
return time_utc_or_local(argc, argv, Qfalse, klass);
}
+static VALUE
+time_set_utc_offset(VALUE time, VALUE off)
+{
- struct time_object *tobj;
- off = num_exact(off);
- time_modify(time);
- GetTimeval(time, tobj);
- tobj->tm_got = 0;
- TIME_SET_FIXOFF(tobj, off);
- return time;
+}
+static void
+vtm_add_offset(struct vtm *vtm, VALUE off)
+{
- int sign;
- VALUE subsec, v;
- int sec, min, hour;
- int day;
- vtm->utc_offset = sub(vtm->utc_offset, off);
- if (RTEST(lt(off, INT2FIX(0)))) {
-
sign = -1;
-
off = neg(off);
- }
- else {
-
sign = 1;
- }
- divmodv(off, INT2FIX(1), &off, &subsec);
- divmodv(off, INT2FIX(60), &off, &v);
- sec = NUM2INT(v);
- divmodv(off, INT2FIX(60), &off, &v);
- min = NUM2INT(v);
- divmodv(off, INT2FIX(24), &off, &v);
- hour = NUM2INT(v);
- if (sign < 0) {
-
subsec = neg(subsec);
-
sec = -sec;
-
min = -min;
-
hour = -hour;
- }
- day = 0;
- if (!rb_equal(subsec, INT2FIX(0))) {
-
vtm->subsec = add(vtm->subsec, subsec);
-
if (lt(vtm->subsec, INT2FIX(0))) {
-
vtm->subsec = add(vtm->subsec, INT2FIX(1));
-
sec -= 1;
-
}
-
if (le(INT2FIX(1), vtm->subsec)) {
-
vtm->subsec = sub(vtm->subsec, INT2FIX(1));
-
sec += 1;
-
}
-
goto not_zero_sec;
- }
- if (sec) {
-
not_zero_sec:
-
/* If sec + subsec == 0, don't change vtm->sec.
-
* It may be 60 which is a leap second. */
-
vtm->sec += sec;
-
if (vtm->sec < 0) {
-
vtm->sec += 60;
-
min -= 1;
-
}
-
if (60 <= vtm->sec) {
-
vtm->sec -= 60;
-
min += 1;
-
}
- }
- if (min) {
-
vtm->min += min;
-
if (vtm->min < 0) {
-
vtm->min += 60;
-
hour -= 1;
-
}
-
if (60 <= vtm->min) {
-
vtm->min -= 60;
-
hour += 1;
-
}
- }
- if (hour) {
-
vtm->hour += hour;
-
if (vtm->hour < 0) {
-
vtm->hour += 24;
-
day = -1;
-
}
-
if (24 <= vtm->hour) {
-
vtm->hour -= 24;
-
day = 1;
-
}
- }
- if (day) {
-
if (day < 0) {
-
if (vtm->mon == 1 && vtm->mday == 1) {
-
vtm->mday = 31;
-
vtm->mon = 12; /* December */
-
vtm->year = sub(vtm->year, INT2FIX(1));
-
vtm->yday = leap_year_v_p(vtm->year) ? 365 : 364;
-
}
-
else if (vtm->mday == 1) {
-
const int *days_in_month = leap_year_v_p(vtm->year) ?
-
leap_year_days_in_month :
-
common_year_days_in_month;
-
vtm->mon--;
-
vtm->mday = days_in_month[vtm->mon-1];
-
vtm->yday--;
-
}
-
else {
-
vtm->mday--;
-
vtm->yday--;
-
}
-
vtm->wday = (vtm->wday + 6) % 7;
-
}
-
else {
-
int leap = leap_year_v_p(vtm->year);
-
if (vtm->mon == 12 && vtm->mday == 31) {
-
vtm->year = add(vtm->year, INT2FIX(1));
-
vtm->mon = 1; /* January */
-
vtm->mday = 1;
-
vtm->yday = 1;
-
}
-
else if (vtm->mday == (leap ? leap_year_days_in_month :
common_year_days_in_month)[vtm->mon-1]) {
-
vtm->mon++;
-
vtm->mday = 1;
-
vtm->yday++;
-
}
-
else {
-
vtm->mday++;
-
vtm->yday++;
-
}
-
vtm->wday = (vtm->wday + 1) % 7;
-
}
- }
+}
+static VALUE
+utc_offset_arg(VALUE arg)
+{
- VALUE tmp;
- if (!NIL_P(tmp = rb_check_string_type(arg))) {
-
int n;
-
char *s = RSTRING_PTR(tmp);
-
if (!rb_enc_str_asciicompat_p(tmp) ||
-
RSTRING_LEN(tmp) != 6 ||
-
(s[0] != '+' && s[0] != '-') ||
-
!ISDIGIT(s[1]) ||
-
!ISDIGIT(s[2]) ||
-
s[3] != ':' ||
-
!ISDIGIT(s[4]) ||
-
!ISDIGIT(s[5]))
-
rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected
for utc_offset");
-
n = strtol(s+1, NULL, 10) * 3600;
-
n += strtol(s+4, NULL, 10) * 60;
-
if (s[0] == '-')
-
n = -n;
-
return INT2FIX(n);
- }
- else {
-
return num_exact(arg);
- }
+}
+static VALUE
+time_s_civil(int argc, VALUE *argv, VALUE klass)
+{
- struct vtm vtm;
- VALUE time;
- VALUE v[7];
- int i;
- vtm.wday = -1;
- vtm.yday = 0;
- vtm.zone = “”;
- /* year mon mday hour min sec
off */ - rb_scan_args(argc, argv, “16”,
&v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]); - vtm.year = obj2vint(v[0]);
- vtm.mon = NIL_P(v[1]) ? 1 : month_arg(v[1]);
- vtm.mday = NIL_P(v[2]) ? 1 : obj2long(v[2]);
- vtm.hour = NIL_P(v[3]) ? 0 : obj2long(v[3]);
- vtm.min = NIL_P(v[4]) ? 0 : obj2long(v[4]);
- vtm.sec = 0;
- vtm.subsec = 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.subsec = subsec;
- }
- vtm.isdst = -1;
- vtm.utc_offset = Qnil;
- if (!NIL_P(v[6])) {
-
VALUE arg = v[6];
-
VALUE tmp;
-
if (arg == ID2SYM(rb_intern("dst")))
-
vtm.isdst = 1;
-
else if (arg == ID2SYM(rb_intern("std")))
-
vtm.isdst = 0;
-
else
-
vtm.utc_offset = utc_offset_arg(arg);
- }
- validate_vtm(&vtm);
- if (!NIL_P(vtm.utc_offset)) {
-
VALUE off = vtm.utc_offset;
-
vtm_add_offset(&vtm, neg(off));
-
vtm.utc_offset = Qnil;
-
time = time_new_timev(klass, timegmv(&vtm));
-
return time_set_utc_offset(time, off);
- }
- else {
-
time = time_new_timev(klass, timelocalv(&vtm));
-
return time_localtime(time);
- }
+}
/*
- call-seq:
-
time.to_i => int
@@ -2281,6 +2530,38 @@ time_gmtime(VALUE time)
return time;
}
+static VALUE
+time_fixoff(VALUE time)
+{
- struct time_object *tobj;
- struct vtm vtm;
- VALUE off;
- GetTimeval(time, tobj);
- if (TIME_FIXOFF_P(tobj)) {
-
if (tobj->tm_got)
-
return time;
- }
- else {
-
time_modify(time);
- }
- if (TIME_FIXOFF_P(tobj))
-
off = tobj->vtm.utc_offset;
- else
-
off = INT2FIX(0);
- if (!gmtimev(tobj->timev, &vtm))
-
rb_raise(rb_eArgError, "gmtime error");
- tobj->vtm = vtm;
- vtm_add_offset(&tobj->vtm, off);
- tobj->tm_got = 1;
- TIME_SET_FIXOFF(tobj, off);
- return time;
+}
/*
- call-seq:
-
time.getlocal => new_time
@@ -2296,8 +2577,20 @@ time_gmtime(VALUE time)
*/
static VALUE
-time_getlocaltime(VALUE time)
+time_getlocaltime(int argc, VALUE *argv, VALUE time)
{
- VALUE off;
- rb_scan_args(argc, argv, “01”, &off);
- if (!NIL_P(off)) {
-
off = utc_offset_arg(off);
-
validate_utc_offset(off);
-
time = time_dup(time);
-
time_set_utc_offset(time, off);
-
return time_fixoff(time);
- }
- return time_localtime(time_dup(time));
}
@@ -2326,6 +2619,7 @@ static VALUE
time_get_tm(VALUE time, struct time_object *tobj)
{
if (TIME_UTC_P(tobj)) return time_gmtime(time);
- if (TIME_FIXOFF_P(tobj)) return time_fixoff(time);
return time_localtime(time);
}
@@ -2829,6 +3123,8 @@ time_zone(VALUE time)
if (TIME_UTC_P(tobj)) {
return rb_str_new2(“UTC”);
}
- if (tobj->vtm.zone == NULL)
-
return rb_str_new2(tobj->vtm.zone);return Qnil;
}
@@ -3316,6 +3612,7 @@ Init_Time(void)
rb_define_singleton_method(rb_cTime, “gm”, time_s_mkutc, -1);
rb_define_singleton_method(rb_cTime, “local”, time_s_mktime, -1);
rb_define_singleton_method(rb_cTime, “mktime”, time_s_mktime, -1);
-
rb_define_singleton_method(rb_cTime, “civil”, time_s_civil, -1);
rb_define_method(rb_cTime, “to_i”, time_to_i, 0);
rb_define_method(rb_cTime, “to_f”, time_to_f, 0);
@@ -3328,7 +3625,7 @@ Init_Time(void)
rb_define_method(rb_cTime, “localtime”, time_localtime, 0);
rb_define_method(rb_cTime, “gmtime”, time_gmtime, 0);
rb_define_method(rb_cTime, “utc”, time_gmtime, 0);
- rb_define_method(rb_cTime, “getlocal”, time_getlocaltime, 0);
- rb_define_method(rb_cTime, “getlocal”, time_getlocaltime, -1);
rb_define_method(rb_cTime, “getgm”, time_getgmtime, 0);
rb_define_method(rb_cTime, “getutc”, time_getgmtime, 0);