[#15357] Regexp literal and Regexp.new() — TAKAHASHI Masayoshi <maki@...>
高橋征義です。
高橋征義です。むーん、問題のありかが違ったかも。
まつもと ゆきひろです
[#15369] ruby_init_loadpath() on Windows — Shugo Maeda <shugo@...>
前田です。
わたなべです。
[#15395] UnboundMethod.bind to derived class instance — nobu.nakada@...
なかだです。
まつもと ゆきひろです
なかだです。
[#15410] pp - pretty printing — Tanaka Akira <akr@...17n.org>
さて、time.rb が片付いたので、次は pp.rb のご意見募集です。
In article <hvod71ntocb.fsf@coulee.a02.aist.go.jp>,
In article <hvo1yhuqhvk.fsf@coulee.a02.aist.go.jp>,
高橋征義です。
In article <20011224230059I.maki@rubycolor.org>,
[#15411] inconsistency of STR_ASSOC — "K.Kosako" <kosako@...>
Version : 1.7 latest (2001-12-10)
[#15418] block for MatchData#select, Hash#select — nobu.nakada@...
なかだです。
[#15430] [BUG] Segmentation fault/ruby 1.7.2 (2001-12-10) — WATANABE Tetsuya <tetsu@...>
渡辺哲也です。
[#15435] Time#utcoff — Tanaka Akira <akr@...17n.org>
In article <hvosnahj702.fsf@coulee.a02.aist.go.jp>,
まつもと ゆきひろです
わたなべです。
In article <1008292110.329151.8468.nullmailer@ev.netlab.jp>,
まつもと ゆきひろです
In article <1008320813.231850.10341.nullmailer@ev.netlab.jp>,
In article <hvosnaeblzu.fsf@coulee.a02.aist.go.jp>,
[#15441] exported symbol — nobu.nakada@...
なかだです。
[#15456] irb/completion で Segmentation fault — Kazuhiro NISHIYAMA <zn@...>
西山和広です。
まつもと ゆきひろです
On Sat, 15 Dec 2001 18:28:12 +0900
まつもと ゆきひろです
[#15464] gsub weirdness: gsub(/.*$/, "foo") — "Akinori MUSHA" <knu@...>
なんか gsub がおかしいような気がするんですが、これはこういう
青山です。
At Mon, 17 Dec 2001 05:22:53 +0900,
[#15466] listen for sockets in both IPv4 and IPv6 — Ryo HAYASAKA <ryoh@...>
早坂@北陸先端です.
[#15479] [BUG] thread with tempfile.rb — keiju@... (Keiju ISHITSUKA)
けいじゅ@日本ラショナルソフトウェアです.
[#15500] Re: define_method() does not properly set noex (PR#218) — nobu.nakada@...
なかだです。
[#15505] ERb — m_seki@...
In article <20011220114249J.seki@mr.nasu.toshiba.co.jp>,
In article <m3eljr5o9m.wl@edwin.mva.biglobe.ne.jp>,
高橋征義です。
In article <20020215085405G.seki@mr.nasu.toshiba.co.jp>,
ただただしです。
まつもと ゆきひろです
新井です。
西山和広です。
>>>>> In [ruby-dev : No.15909]
まつもと ゆきひろです
なかだです。
まつもと ゆきひろです
なかだです。
At Mon, 18 Feb 2002 12:50:31 +0900,
なかだです。
In message <200202201003.g1KA3As11455@sharui.nakada.kanuma.tochigi.jp>
新井です。
あづみです。
[#15507] fileutils (2) — Minero Aoki <aamine@...>
あおきです。
高橋征義です。
あおきです。
高橋征義です。結論は最後に。
あおきです。
高橋征義です。
あおきです。
高橋征義です。
あおきです。
高橋征義です。
あおきです。
高橋征義です。
あおきです。
けいじゅ@日本ラショナルソフトウェアです.
[#15519] typo in tracer.rb (SCRIPT_LINES__) — sheepman <sheepman@...>
こんにちは。
なひです。
まつもと ゆきひろです
なひです。
[#15556] TCPSocket#open で Errno::EALREADY — Kazuhiro NISHIYAMA <zn@...>
西山和広です。
[#15569] [REQ] File?chmod — keiju@... (Keiju ISHITSUKA)
けいじゅ@日本ラショナルソフトウェアです.
まつもと ゆきひろです
[#15573] [patch] resolv.rb for win32 platform — Tietew <tietew-ml-ruby-dev@...>
Tietew です。
なかだです。
こんにちは、なかむら(う)です。
なかだです。
In message <20011228143615.32D8.TIETEW-ML-RUBY-DEV@tietew.net>
こんにちは、なかむら(う)です。
Tietew です。
[#15603] filename within eval — nobu.nakada@...
なかだです。
[ruby-dev:15462] Re: Time#utcoff
In article <hvosnaeblzu.fsf@coulee.a02.aist.go.jp>,
Tanaka Akira <akr@m17n.org> writes:
> また、make_time_t の方は厄介で、二分探索しようにも初期状態の範囲の端点
> で localtime/gmtime が失敗するので話になりません。たぶん。
この原因がわかりました。64bit な time_t だと 32bit な tm_year が
overflow することがあり、その場合 localtime/gmtime が NULL を返します。
つまり、-(1<<32)+1900年の始まりから (1<<32)-1+1900年の終わりまでしか扱
えません。この両端は時差によって異なるので、二分探索の初期範囲を固定す
ることが出来ません。というわけでさきに述べた通り(存在する場合には)
mktime/timegm を使うことにしました。
というわけで疑問は解消したのでパッチをつけときます。
なお、time_arg が 2, 3桁 year をサポートしている都合上、西暦 0年から
38年および 69年から 138年は指定できません。いっそ消すかとも思ったので
すが、rb_warning でがまんしてあります。
(38年と半端なのは 32bit time_t でエラーになる奴は互換性の問題がないの
でそのまま西暦と解釈するようにしたからです。)
また、make_time_t の速度を計測したところ、少なくとも手元の FreeBSD で
は、さらに低下しました。この速度は mktime/timegm の速度によって決まる
ので、私のせいじゃない、と思っています。他のシステムでは別の結果が出る
かも知れません。
あと、missing/strftime.c のパッチは (1<<32) 以上の年を正しく扱うための
ものです。gawk-3.1.0 や glibc のにも同様な問題が残っていました。報告は
しておきましたが。
# tzcode も同様な問題がありましたが、Linux でテストして報告するのも何
# なのでこっちはなにもしてない。
> > gmtoffってのはstruct tmのメンバにもありますし、gmtをutcに置
> > き換えるってのはTimeクラスのほかのメソッドでも広く行っている
> > ので自然な経緯だと思うのですが、utcoffって名前はなぜこんなに
> > 違和感があるんでしょう? わたしだけ?
これは utc_offset, gmt_offset, gmtoff にしました。
Index: time.c
===================================================================
RCS file: /src/ruby/time.c,v
retrieving revision 1.47
diff -u -r1.47 time.c
--- time.c 2001/12/13 08:19:07 1.47
+++ time.c 2001/12/16 05:40:17
@@ -173,7 +173,7 @@
VALUE time, t;
if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
- tv.tv_sec = NUM2INT(time);
+ tv.tv_sec = NUM2LONG(time);
tv.tv_usec = NUM2INT(t);
}
else {
@@ -215,6 +215,7 @@
{
VALUE v[7];
int i;
+ long year;
MEMZERO(tm, struct tm, 1);
if (argc == 10) {
@@ -230,11 +231,23 @@
else {
rb_scan_args(argc, argv, "16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
*usec = (argc == 7) ? NUM2INT(v[6]) : 0;
+ tm->tm_isdst = -1;
}
- tm->tm_year = obj2long(v[0]);
- if (0 <= tm->tm_year && tm->tm_year < 69) tm->tm_year += 100;
- if (tm->tm_year >= 1900) tm->tm_year -= 1900;
+ year = obj2long(v[0]);
+
+ if (0 <= year && year < 39) {
+ year += 2000;
+ rb_warning("2 digits year is used");
+ }
+ else if (69 <= year && year < 139) {
+ year += 1900;
+ rb_warning("2 or 3 digits year is used");
+ }
+
+ year -= 1900;
+ tm->tm_year = year;
+
if (NIL_P(v[1])) {
tm->tm_mon = 0;
}
@@ -270,6 +283,7 @@
/* value validation */
if (
+ tm->tm_year != year ||
#ifndef NEGATIVE_TIME_T
tm->tm_year < 69 ||
#endif
@@ -307,7 +321,7 @@
}
static time_t
-make_time_t(tptr, utc_p)
+search_time_t(tptr, utc_p)
struct tm *tptr;
int utc_p;
{
@@ -316,10 +330,10 @@
int d, have_guess;
int find_dst;
- find_dst = 1;
+ find_dst = 0 < tptr->tm_isdst;
#ifdef NEGATIVE_TIME_T
- guess_lo = 1 << (8 * sizeof(time_t) - 1);
+ guess_lo = 1L << (8 * sizeof(time_t) - 1);
#else
guess_lo = 0;
#endif
@@ -536,6 +550,35 @@
return 0; /* not reached */
}
+static time_t
+make_time_t(tptr, utc_p)
+ struct tm *tptr;
+ int utc_p;
+{
+ time_t t;
+ struct tm *tmp, buf;
+ buf = *tptr;
+ if (utc_p) {
+#if defined(HAVE_TIMEGM)
+ t = timegm(&buf);
+ if (t == -1)
+#endif
+ t = search_time_t(&buf, utc_p);
+ if (!(tmp = gmtime(&t)))
+ rb_raise(rb_eArgError, "gmtime error");
+ }
+ else {
+#if defined(HAVE_MKTIME)
+ t = mktime(&buf);
+ if (t == -1)
+#endif
+ t = search_time_t(&buf, utc_p);
+ if (!(tmp = localtime(&t)))
+ rb_raise(rb_eArgError, "localtime error");
+ }
+ return t;
+}
+
static VALUE
time_utc_or_local(argc, argv, utc_p, klass)
int argc;
@@ -578,7 +621,7 @@
struct time_object *tobj;
GetTimeval(time, tobj);
- return INT2NUM(tobj->tv.tv_sec);
+ return LONG2NUM(tobj->tv.tv_sec);
}
static VALUE
@@ -746,6 +789,8 @@
}
t = tobj->tv.tv_sec;
tm_tmp = localtime(&t);
+ if (!tm_tmp)
+ rb_raise(rb_eArgError, "localtime error");
tobj->tm = *tm_tmp;
tobj->tm_got = 1;
tobj->gmt = 0;
@@ -770,6 +815,8 @@
}
t = tobj->tv.tv_sec;
tm_tmp = gmtime(&t);
+ if (!tm_tmp)
+ rb_raise(rb_eArgError, "gmtime error");
tobj->tm = *tm_tmp;
tobj->tm_got = 1;
tobj->gmt = 1;
@@ -1002,7 +1049,7 @@
if (tobj->tm_got == 0) {
time_get_tm(time, tobj->gmt);
}
- return INT2FIX(tobj->tm.tm_year+1900);
+ return LONG2NUM((long)tobj->tm.tm_year+1900);
}
static VALUE
@@ -1071,6 +1118,48 @@
}
static VALUE
+time_utc_offset(time)
+ VALUE time;
+{
+ struct time_object *tobj;
+
+ GetTimeval(time, tobj);
+ if (tobj->tm_got == 0) {
+ time_get_tm(time, tobj->gmt);
+ }
+
+ if (tobj->gmt == 1) {
+ return INT2FIX(0);
+ }
+ else {
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+ return INT2NUM(tobj->tm.tm_gmtoff);
+#else
+ struct tm *u, *l;
+ time_t t;
+ int off;
+ l = &tobj->tm;
+ t = tobj->tv.tv_sec;
+ u = gmtime(&t);
+ if (!u)
+ rb_raise(rb_eArgError, "gmtime error");
+ if (l->tm_year != u->tm_year)
+ off = l->tm_year < u->tm_year ? -1 : 1;
+ else if (l->tm_mon != u->tm_mon)
+ off = l->tm_mon < u->tm_mon ? -1 : 1;
+ else if (l->tm_mday != u->tm_mday)
+ off = l->tm_mday < u->tm_mday ? -1 : 1;
+ else
+ off = 0;
+ off = off * 24 + l->tm_hour - u->tm_hour;
+ off = off * 60 + l->tm_min - u->tm_min;
+ off = off * 60 + l->tm_sec - u->tm_sec;
+ return INT2FIX(off);
+#endif
+ }
+}
+
+static VALUE
time_to_a(time)
VALUE time;
{
@@ -1086,7 +1175,7 @@
INT2FIX(tobj->tm.tm_hour),
INT2FIX(tobj->tm.tm_mday),
INT2FIX(tobj->tm.tm_mon+1),
- INT2FIX(tobj->tm.tm_year+1900),
+ LONG2NUM((long)tobj->tm.tm_year+1900),
INT2FIX(tobj->tm.tm_wday),
INT2FIX(tobj->tm.tm_yday+1),
tobj->tm.tm_isdst?Qtrue:Qfalse,
@@ -1200,6 +1289,9 @@
t = tobj->tv.tv_sec;
tm = gmtime(&t);
+ if ((tm->tm_year & 0x1ffff) != tm->tm_year)
+ rb_raise(rb_eArgError, "too big year to marshal");
+
p = 0x1 << 31 | /* 1 */
tm->tm_year << 14 | /* 17 */
tm->tm_mon << 10 | /* 4 */
@@ -1255,8 +1347,9 @@
tm.tm_hour = p & 0x1f;
tm.tm_min = (s >> 26) & 0x3f;
tm.tm_sec = (s >> 20) & 0x3f;
+ tm.tm_isdst = 0;
- sec = make_time_t(&tm, gmtime);
+ sec = make_time_t(&tm, Qtrue);
usec = (time_t) s & 0xfffff;
return time_new_internal(klass, sec, usec);
@@ -1315,6 +1408,9 @@
rb_define_method(rb_cTime, "isdst", time_isdst, 0);
rb_define_method(rb_cTime, "dst?", time_isdst, 0);
rb_define_method(rb_cTime, "zone", time_zone, 0);
+ rb_define_method(rb_cTime, "gmtoff", time_utc_offset, 0);
+ rb_define_method(rb_cTime, "gmt_offset", time_utc_offset, 0);
+ rb_define_method(rb_cTime, "utc_offset", time_utc_offset, 0);
rb_define_method(rb_cTime, "utc?", time_utc_p, 0);
rb_define_method(rb_cTime, "gmt?", time_utc_p, 0);
Index: configure.in
===================================================================
RCS file: /src/ruby/configure.in,v
retrieving revision 1.103
diff -u -r1.103 configure.in
--- configure.in 2001/12/03 09:38:35 1.103
+++ configure.in 2001/12/16 05:40:20
@@ -300,8 +300,17 @@
setitimer setruid seteuid setreuid setresuid setproctitle\
setrgid setegid setregid setresgid pause lchown lchmod\
getpgrp setpgrp getpgid setpgid getgroups getpriority getrlimit\
- dlopen sigprocmask sigaction _setjmp setsid telldir seekdir fchmod)
+ dlopen sigprocmask sigaction _setjmp setsid telldir seekdir fchmod\
+ mktime timegm)
AC_STRUCT_TIMEZONE
+AC_CACHE_CHECK(for struct tm.tm_gmtoff, rb_cv_member_struct_tm_tm_gmtoff,
+ [AC_TRY_COMPILE([#include <time.h>],
+ [struct tm t; t.tm_gmtoff = 3600;],
+ [rb_cv_member_struct_tm_tm_gmtoff=yes],
+ [rb_cv_member_struct_tm_tm_gmtoff=no])])
+if test "$rb_cv_member_struct_tm_tm_gmtoff" = yes; then
+ AC_DEFINE(HAVE_STRUCT_TM_TM_GMTOFF)
+fi
AC_CACHE_CHECK(for external int daylight, rb_cv_have_daylight,
[AC_TRY_LINK([#include <time.h>
int i;],
@@ -337,7 +346,7 @@
struct tm *tm;
check(gmtime(&t), 69, 12, 31, 23, 59);
- t = -0x80000000;
+ t = ~(time_t)0 << 31;
check(gmtime(&t), 1, 12, 13, 20, 52);
return 0;
}
Index: missing/strftime.c
===================================================================
RCS file: /src/ruby/missing/strftime.c,v
retrieving revision 1.4
diff -u -r1.4 strftime.c
--- missing/strftime.c 2001/01/15 07:01:00 1.4
+++ missing/strftime.c 2001/12/16 05:40:23
@@ -175,7 +175,8 @@
char *start = s;
auto char tbuf[100];
long off;
- int i, w, y;
+ int i, w;
+ long y;
static short first = 1;
#ifdef POSIX_SEMANTICS
static char *savetz = NULL;
@@ -378,7 +379,7 @@
break;
case 'Y': /* year with century */
- sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
+ sprintf(tbuf, "%ld", 1900L + timeptr->tm_year);
break;
#ifdef MAILHEADER_EXT
@@ -503,10 +504,10 @@
#ifdef VMS_EXT
case 'v': /* date as dd-bbb-YYYY */
- sprintf(tbuf, "%2d-%3.3s-%4d",
+ sprintf(tbuf, "%2d-%3.3s-%4ld",
range(1, timeptr->tm_mday, 31),
months_a[range(0, timeptr->tm_mon, 11)],
- timeptr->tm_year + 1900);
+ timeptr->tm_year + 1900L);
for (i = 3; i < 6; i++)
if (islower(tbuf[i]))
tbuf[i] = toupper(tbuf[i]);
@@ -516,7 +517,7 @@
#ifdef POSIX2_DATE
case 'C':
- sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
+ sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
break;
@@ -550,16 +551,16 @@
*/
w = iso8601wknum(timeptr);
if (timeptr->tm_mon == 11 && w == 1)
- y = 1900 + timeptr->tm_year + 1;
+ y = 1900L + timeptr->tm_year + 1;
else if (timeptr->tm_mon == 0 && w >= 52)
- y = 1900 + timeptr->tm_year - 1;
+ y = 1900L + timeptr->tm_year - 1;
else
- y = 1900 + timeptr->tm_year;
+ y = 1900L + timeptr->tm_year;
if (*format == 'G')
- sprintf(tbuf, "%d", y);
+ sprintf(tbuf, "%ld", y);
else
- sprintf(tbuf, "%02d", y % 100);
+ sprintf(tbuf, "%02ld", y % 100);
break;
#endif /* ISO_DATE_EXT */
default:
@@ -590,10 +591,10 @@
#ifndef __STDC__
static int
isleap(year)
-int year;
+long year;
#else
static int
-isleap(int year)
+isleap(long year)
#endif
{
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
@@ -684,7 +685,7 @@
dec31ly.tm_mon = 11;
dec31ly.tm_mday = 31;
dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
- dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
+ dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900L);
weeknum = iso8601wknum(& dec31ly);
#endif
}
--
[田中 哲][たなか あきら][Tanaka Akira]
「ふえろ! わかめちゃん作戦です$(C⊇」(Little Worker, 桂遊生丸)