1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* time.c: new method gmtoff', gmt_offset' and `utc_offset'.

(time_utc_offset): new function.
(Init_Time): bind above methods to `time_utc_offset'.

* time.c: 64bit time_t support.
(time_s_at): use NUM2LONG instead of NUM2INT for tv_sec.
(time_arg): initialize tm_isdst correctly.
use long to initialize tm_year.
(search_time_t): renamed from `make_time_t'.
(make_time_t): call `timegm' and `mktime' instead of `search_time_t'
if availabe.
(time_to_i): use LONG2NUM instead of INT2NUM.
(time_localtime): check localtime failure.
(time_gmtime): check gmtime failure.
(time_year): use LONG2NUM instead of INT2FIX.
(time_to_a): use long for tm_year.
(time_dump): check tm_year which is not representable with 17bit.
(time_load): initialize tm_isdst.

* configure.in: check existence of `mktime' and `timegm'.
check existence of tm_gmtoff field of struct tm.
fix negative time_t for 64bit time_t.

* missing/strftime.c: fix overflow by tm_year + 1900.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1912 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2001-12-17 06:45:37 +00:00
parent 39c0252e04
commit b48e38c526
4 changed files with 180 additions and 27 deletions

View file

@ -1,3 +1,30 @@
Mon Dec 17 15:19:32 2001 Tanaka Akira <akr@m17n.org>
* time.c: new method `gmtoff', `gmt_offset' and `utc_offset'.
(time_utc_offset): new function.
(Init_Time): bind above methods to `time_utc_offset'.
* time.c: 64bit time_t support.
(time_s_at): use NUM2LONG instead of NUM2INT for tv_sec.
(time_arg): initialize tm_isdst correctly.
use long to initialize tm_year.
(search_time_t): renamed from `make_time_t'.
(make_time_t): call `timegm' and `mktime' instead of `search_time_t'
if availabe.
(time_to_i): use LONG2NUM instead of INT2NUM.
(time_localtime): check localtime failure.
(time_gmtime): check gmtime failure.
(time_year): use LONG2NUM instead of INT2FIX.
(time_to_a): use long for tm_year.
(time_dump): check tm_year which is not representable with 17bit.
(time_load): initialize tm_isdst.
* configure.in: check existence of `mktime' and `timegm'.
check existence of tm_gmtoff field of struct tm.
fix negative time_t for 64bit time_t.
* missing/strftime.c: fix overflow by tm_year + 1900.
Fri Dec 14 04:23:36 2001 Minero Aoki <aamine@loveruby.net>
* lib/net/pop.rb: new method Net::POP3.APOP

View file

@ -300,8 +300,17 @@ AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall chroot\
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 @@ main()
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;
}

View file

@ -175,7 +175,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
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 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
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 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#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 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#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 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
*/
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 @@ out:
#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 @@ iso8601wknum(const struct tm *timeptr)
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
}

140
time.c
View file

@ -173,7 +173,7 @@ time_s_at(argc, argv, klass)
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 @@ time_arg(argc, argv, tm, usec)
{
VALUE v[7];
int i;
long year;
MEMZERO(tm, struct tm, 1);
if (argc == 10) {
@ -225,16 +226,28 @@ time_arg(argc, argv, tm, usec)
v[4] = argv[1];
v[5] = argv[0];
*usec = 0;
tm->tm_isdst = RTEST(argv[9]) ? 1 : 0;
tm->tm_isdst = RTEST(argv[8]) ? 1 : 0;
}
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 @@ time_arg(argc, argv, tm, usec)
/* value validation */
if (
tm->tm_year != year ||
#ifndef NEGATIVE_TIME_T
tm->tm_year < 69 ||
#endif
@ -307,7 +321,7 @@ tmcmp(a, b)
}
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 @@ make_time_t(tptr, utc_p)
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,55 @@ make_time_t(tptr, utc_p)
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) {
#ifdef NEGATIVE_TIME_T
if (!(tmp = gmtime(&t)) ||
tptr->tm_year != tmp->tm_year ||
tptr->tm_mon != tmp->tm_mon ||
tptr->tm_mday != tmp->tm_mday ||
tptr->tm_hour != tmp->tm_hour ||
tptr->tm_min != tmp->tm_min ||
tptr->tm_sec != tmp->tm_sec)
#endif
rb_raise(rb_eArgError, "gmtime error");
}
#else
t = search_time_t(&buf, utc_p);
#endif
}
else {
#if defined(HAVE_MKTIME)
t = mktime(&buf);
if (t == -1) {
#ifdef NEGATIVE_TIME_T
if (!(tmp = localtime(&t)) ||
tptr->tm_year != tmp->tm_year ||
tptr->tm_mon != tmp->tm_mon ||
tptr->tm_mday != tmp->tm_mday ||
tptr->tm_hour != tmp->tm_hour ||
tptr->tm_min != tmp->tm_min ||
tptr->tm_sec != tmp->tm_sec)
#endif
rb_raise(rb_eArgError, "localtime error");
}
#else
t = search_time_t(&buf, utc_p);
#endif
}
return t;
}
static VALUE
time_utc_or_local(argc, argv, utc_p, klass)
int argc;
@ -578,7 +641,7 @@ time_to_i(time)
struct time_object *tobj;
GetTimeval(time, tobj);
return INT2NUM(tobj->tv.tv_sec);
return LONG2NUM(tobj->tv.tv_sec);
}
static VALUE
@ -746,6 +809,8 @@ time_localtime(time)
}
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 +835,8 @@ time_gmtime(time)
}
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 +1069,7 @@ time_year(time)
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
@ -1070,6 +1137,48 @@ time_zone(time)
#endif
}
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 +1195,7 @@ time_to_a(time)
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 +1309,9 @@ time_dump(argc, argv, time)
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 +1367,9 @@ time_load(klass, str)
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 +1428,9 @@ Init_Time()
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);