e$B:G6a!“e(Bnanosecond e$BC10L$Je(B timestamp e$B$,$”$k$h$&$G$9!#e(B
e$B$?$H$($Pe(B boron e$B$@$He(B timestamp e$B$,e(B nanosecond
e$BC10L$G$9!#e(B
% stat .
File: `.’
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: fe02h/65026d Inode: 12583040 Links: 14
Access: (0755/drwxr-xr-x) Uid: ( 1033/ akr) Gid: ( 100/ users)
Access: 2007-11-17 17:38:05.613931200 +0900
Modify: 2007-11-17 14:31:00.182456176 +0900
Change: 2007-11-17 14:31:00.182456176 +0900
e$B>e5-$Ne(B filesystem e$B$Oe(B XFS e$B$G$9$,!"e(BGNU/Linux
e$B$@$HB>$Ke(B JFS e$B$,%5e(B
e$B%]!<%H$7$F$$$^$9!#$^$?!"e(Bext4 e$B$b%5%]!<%H$9$k$h$&$G$9!#e(B
NetBSD, FreeBSD, OpenBSD e$B$b!“e(Bstruct stat e$B$K$O$b$&MQ0U$,$”$je(B
e$B$^$9!#e(B(e$B<B:]$K$=$l$r;H$&e(B filesystem
e$B$,$"$k$+$OCN$j$^$;$se(B)
e$B$G!"$3$l$re(B Ruby e$B$G07$C$F$_$h$&$+$H;W$C$F!"e(B
- Time e$B$N@:EY$re(B microsecond e$B$+$ie(B nanosecond e$B$K$"$2$Fe(B
- File.mtime e$BEy$Ge(B nanosecond e$BC10L$Ne(B timestamp
e$B$r<h$j=P$9e(B
e$B$H$7$F$_$^$7$?!#e(B
e$B$=$l$K$H$b$J$C$F!"e(B
- Time#tv_nsec, Time#nsec e$B$NDI2Ce(B
- Time.at e$B$N:G8e$N0z?t$Ge(B Float e$B$de(B Rational
e$B$r<u$1IU$1$ke(B - Time.local, Time.utc e$B$N:G8e$N0z?t$,e(B sec
e$B$N$H$-$bF1MM$K<u$1IU$1$ke(B
e$B$H$7$F$"$j$^$9!#e(B
Rational e$B$r07$($ke(B (e$B$H$$$&$+!"%/%i%9$r5$$K$;$:$KC1$Ke(B divmod
e$B$H$+$r8F$S=P$7$F@0?tItJ,$d>.?tItJ,$r<h$j=P$9e(B)
e$B$h$&$K$7$?$N$O!"e(B
IEEE 754 double e$B$@$H!"8=;~E@$N;~9o$re(B nanosecond e$BC10L$^$G$N@:e(B
e$BEY$G$OI=8=$G$-$J$$$+$i$G$9!#e(BTime.at
e$B$KBhe(B3e$B0z?t$r$D$1$k$H$+e(B
Time.utc e$B$N0z?t$r$5$i$KJ#;($K$9$k$H$$$&$N$O$J$s$G$9$7!#e(B
e$B$"$H!“e(BMarshal e$B$OG:$s$@$N$G<j$r$D$1$F$J$/$F!”:#$^$G$I$*$je(B
microsecond e$B$^$G$7$+=q$-=P$5$l$^$;$s!#FI$_=P$9$H$-$Oe(B
microsecond e$BL$K~$Oe(B 0 e$B$K$J$j$^$9!#e(B
e$B$I$&$G$9$+$M!#e(B
Index: time.c
— time.c (revision 13950)
+++ time.c (working copy)
@@ -24,7 +24,7 @@
static VALUE time_utc_offset _((VALUE));
struct time_object {
- struct timeval tv;
-
struct timespec ts;
struct tm tm;
int gmt;
int tm_got;
@@ -47,8 +47,8 @@obj = Data_Make_Struct(klass, struct time_object, 0, time_free,
tobj);
tobj->tm_got=0;
- tobj->tv.tv_sec = 0;
- tobj->tv.tv_usec = 0;
-
tobj->ts.tv_sec = 0;
-
tobj->ts.tv_nsec = 0;
return obj;
}
@@ -93,11 +93,22 @@
time_modify(time);
GetTimeval(time, tobj);
tobj->tm_got=0;
- tobj->tv.tv_sec = 0;
- tobj->tv.tv_usec = 0;
- if (gettimeofday(&tobj->tv, 0) < 0) {
- rb_sys_fail(“gettimeofday”);
-
tobj->ts.tv_sec = 0;
-
tobj->ts.tv_nsec = 0;
+#ifdef HAVE_CLOCK_GETTIME -
if (clock_gettime(CLOCK_REALTIME, &tobj->ts) == -1) {
-
rb_sys_fail(“clock_gettime”);
}
+#else -
{
-
struct timeval tv;
-
if (gettimeofday(&tv, 0) < 0) {
-
rb_sys_fail("gettimeofday");
-
}
-
tobj->ts.tv_sec = tv.tv_sec;
-
tobj->ts.tv_nsec = tv.tv_usec * 1000;
-
}
+#endifreturn time;
}
@@ -106,9 +117,10 @@
#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
static void
-time_overflow_p(time_t *secp, time_t *usecp)
+time_overflow_p(time_t *secp, long *usecp)
{
- time_t tmp, sec = *secp, usec = *usecp;
-
time_t tmp, sec = *secp;
-
long usec = *usecp;
if (usec >= 1000000) { /* usec positive overflow */
tmp = sec + usec / 1000000;
@@ -134,78 +146,152 @@
*usecp = usec;
}
+static void
+time_nano_overflow_p(time_t *secp, long *nsecp)
+{
- time_t tmp, sec = *secp;
- long nsec = *nsecp;
- if (nsec >= 1000000000) { /* nsec positive overflow */
- tmp = sec + nsec / 1000000000;
- nsec %= 1000000000;
- if (sec > 0 && tmp < 0) {
-
rb_raise(rb_eRangeError, "out of Time range");
- }
- sec = tmp;
- }
- if (nsec < 0) { /* nsec negative overflow */
- tmp = sec + NDIV(nsec,1000000000); /* negative div */
- nsec = NMOD(nsec,1000000000); /* negative mod */
- if (sec < 0 && tmp > 0) {
-
rb_raise(rb_eRangeError, "out of Time range");
- }
- sec = tmp;
- }
+#ifndef NEGATIVE_TIME_T - if (sec < 0)
- rb_raise(rb_eArgError, “time must be positive”);
+#endif - *secp = sec;
- *nsecp = nsec;
+}
static VALUE
-time_new_internal(VALUE klass, time_t sec, time_t usec)
+time_new_internal(VALUE klass, time_t sec, long usec)
{
VALUE time = time_s_alloc(klass);
struct time_object *tobj;
GetTimeval(time, tobj);
time_overflow_p(&sec, &usec);
- tobj->tv.tv_sec = sec;
- tobj->tv.tv_usec = usec;
-
tobj->ts.tv_sec = sec;
-
tobj->ts.tv_nsec = usec * 1000;
return time;
}
+static VALUE
+time_nano_new_internal(VALUE klass, time_t sec, long nsec)
+{
- VALUE time = time_s_alloc(klass);
- struct time_object *tobj;
- GetTimeval(time, tobj);
- time_nano_overflow_p(&sec, &nsec);
- tobj->ts.tv_sec = sec;
- tobj->ts.tv_nsec = nsec;
- return time;
+}
VALUE
-rb_time_new(time_t sec, time_t usec)
+rb_time_new(time_t sec, long usec)
{
return time_new_internal(rb_cTime, sec, usec);
}
-static struct timeval
-time_timeval(VALUE time, int interval)
+VALUE
+rb_time_nano_new(time_t sec, long nsec)
{
- struct timeval t;
- return time_nano_new_internal(rb_cTime, sec, nsec);
+}
+static struct timespec
+time_timespec(VALUE num, int interval)
+{
- struct timespec t;
const char *tstr = interval ? “time interval” : “time”; - VALUE i, f, ary;
#ifndef NEGATIVE_TIME_T
interval = 1;
#endif
- switch (TYPE(time)) {
- switch (TYPE(num)) {
case T_FIXNUM:
- t.tv_sec = FIX2LONG(time);
- t.tv_sec = FIX2LONG(num);
if (interval && t.tv_sec < 0)
rb_raise(rb_eArgError, “%s must be positive”, tstr);
- t.tv_usec = 0;
-
t.tv_nsec = 0;
break;case T_FLOAT:
- if (interval && RFLOAT_VALUE(time) < 0.0)
- if (interval && RFLOAT_VALUE(num) < 0.0)
rb_raise(rb_eArgError, “%s must be positive”, tstr);
else {
double f, d;
-
d = modf(RFLOAT_VALUE(time), &f);
-
d = modf(RFLOAT_VALUE(num), &f); t.tv_sec = (time_t)f; if (f != t.tv_sec) {
- rb_raise(rb_eRangeError, “%f out of Time range”,
RFLOAT_VALUE(time));
- rb_raise(rb_eRangeError, “%f out of Time range”,
RFLOAT_VALUE(num));
}
-
t.tv_usec = (time_t)(d*1e6+0.5);
-
t.tv_nsec = (long)(d*1e9+0.5);
}
break;case T_BIGNUM:
- t.tv_sec = NUM2LONG(time);
- t.tv_sec = NUM2LONG(num);
if (interval && t.tv_sec < 0)
rb_raise(rb_eArgError, “%s must be positive”, tstr);
- t.tv_usec = 0;
-
t.tv_nsec = 0;
break;default:
- rb_raise(rb_eTypeError, “can’t convert %s into %s”,
-
rb_obj_classname(time), tstr);
-
ary = rb_check_array_type(rb_funcall(num, rb_intern("divmod"),
1, INT2FIX(1)));
-
if (NIL_P(ary)) {
-
rb_raise(rb_eTypeError, "can't convert %s into %s",
-
rb_obj_classname(num), tstr);
-
}
-
i = rb_ary_entry(ary, 0);
-
f = rb_ary_entry(ary, 1);
-
t.tv_sec = NUM2LONG(i);
- if (interval && t.tv_sec < 0)
-
rb_raise(rb_eArgError, "%s must be positive", tstr);
-
f = rb_funcall(f, rb_intern("*"), 1, INT2FIX(1000000000));
-
break;t.tv_nsec = NUM2LONG(f);
}
return t;
}
+static struct timeval
+time_timeval(VALUE num, int interval)
+{
- struct timespec ts;
- struct timeval tv;
- ts = time_timespec(num, interval);
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
- return tv;
+}
struct timeval
-rb_time_interval(VALUE time)
+rb_time_interval(VALUE num)
{
- return time_timeval(time, Qtrue);
- return time_timeval(num, Qtrue);
}
struct timeval
@@ -216,12 +302,27 @@
if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
GetTimeval(time, tobj);
- t = tobj->tv;
-
t.tv_sec = tobj->ts.tv_sec;
-
return t;t.tv_usec = tobj->ts.tv_nsec / 1000;
}
return time_timeval(time, Qfalse);
}
+struct timespec
+rb_time_timespec(VALUE time)
+{
- struct time_object *tobj;
- struct timespec t;
- if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
- GetTimeval(time, tobj);
-
t = tobj->ts;
- return t;
- }
- return time_timespec(time, Qfalse);
+}
/*
- call-seq:
-
Time.at( aTime ) => time
@@ -229,7 +330,7 @@
*
- Creates a new time object with the value given by aTime, or
- the given number of seconds (and optional
-
- microseconds) from epoch. A non-portable feature allows the
-
-
microseconds) from the Epoch. A non-portable feature allows
the - offset to be negative on some systems.
-
Time.at(0) #=> Wed Dec 31 18:00:00 CST 1969
-
microseconds) from the Epoch. A non-portable feature allows
@@ -240,17 +341,17 @@
static VALUE
time_s_at(int argc, VALUE *argv, VALUE klass)
{
- struct timeval tv;
-
struct timespec ts;
VALUE time, t;if (rb_scan_args(argc, argv, “11”, &time, &t) == 2) {
- tv.tv_sec = NUM2LONG(time);
- tv.tv_usec = NUM2LONG(t);
- ts.tv_sec = NUM2LONG(time);
- ts.tv_nsec = NUM2LONG(rb_funcall(t, rb_intern("*"), 1,
INT2FIX(1000)));
}
else {
- tv = rb_time_timeval(time);
- ts = rb_time_timespec(time);
}
- t = time_new_internal(klass, tv.tv_sec, tv.tv_usec);
- t = time_nano_new_internal(klass, ts.tv_sec, ts.tv_nsec);
if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
struct time_object *tobj, *tobj2;
@@ -276,15 +377,42 @@
return NUM2LONG(obj);
}
+static long
+obj2nsec(VALUE obj, long *nsec)
+{
- struct timespec ts;
- if (TYPE(obj) == T_STRING) {
- obj = rb_str_to_inum(obj, 10, Qfalse);
-
*nsec = 0;
-
return NUM2LONG(obj) * 1000;
- }
- ts = time_timespec(obj, 1);
- *nsec = ts.tv_nsec;
- return ts.tv_sec;
+}
+static long
+obj2long1000(VALUE obj)
+{
- if (TYPE(obj) == T_STRING) {
- obj = rb_str_to_inum(obj, 10, Qfalse);
-
return NUM2LONG(obj) * 1000;
- }
- return NUM2LONG(rb_funcall(obj, rb_intern("*"), 1, INT2FIX(1000)));
+}
static void
-time_arg(int argc, VALUE *argv, struct tm *tm, time_t *usec)
+time_arg(int argc, VALUE *argv, struct tm *tm, long *nsec)
{
VALUE v[8];
int i;
long year;
MEMZERO(tm, struct tm, 1);
- *usec = 0;
- *nsec = 0;
if (argc == 10) {
v[0] = argv[5];
v[1] = argv[4];
@@ -352,12 +480,13 @@
}
tm->tm_hour = NIL_P(v[3])?0:obj2long(v[3]);
tm->tm_min = NIL_P(v[4])?0:obj2long(v[4]);
- tm->tm_sec = NIL_P(v[5])?0:obj2long(v[5]);
- if (!NIL_P(v[6])) {
- if (!NIL_P(v[6]) && argc == 7) {
-
tm->tm_sec = NIL_P(v[5])?0:obj2long(v[5]);
-
*nsec = obj2long1000(v[6]);
- }
- else {
/* when argc == 8, v[6] is timezone, but ignored */
- if (argc == 7) {
-
*usec = obj2long(v[6]);
- }
-
tm->tm_sec = NIL_P(v[5])?0:obj2nsec(v[5], nsec);
}
/* value validation */
@@ -774,10 +903,10 @@
{
struct tm tm;
VALUE time;
- time_t usec;
- long nsec;
- time_arg(argc, argv, &tm, &usec);
- time = time_new_internal(klass, make_time_t(&tm, utc_p), usec);
- time_arg(argc, argv, &tm, &nsec);
- time = time_nano_new_internal(klass, make_time_t(&tm, utc_p),
nsec);
if (utc_p) return time_gmtime(time);
return time_localtime(time);
}
@@ -834,7 +963,7 @@
-
time.tv_sec => int
- Returns the value of time as an integer number of seconds
-
- since epoch.
-
- since the Epoch.
-
t = Time.now
-
"%10.5f" % t.to_f #=> "1049896564.17839"
@@ -847,7 +976,7 @@
struct time_object *tobj;
GetTimeval(time, tobj);
- return LONG2NUM(tobj->tv.tv_sec);
- return LONG2NUM(tobj->ts.tv_sec);
}
/*
@@ -855,11 +984,14 @@
-
time.to_f => float
- Returns the value of time as a floating point number of
-
- seconds since epoch.
-
- seconds since the Epoch.
-
t = Time.now
-
"%10.5f" % t.to_f #=> "1049896564.13654"
-
t.to_i #=> 1049896564
-
-
- Note that IEEE 754 double is not accurate enough to represent
-
- nanoseconds from the Epoch.
*/
- nanoseconds from the Epoch.
static VALUE
@@ -868,7 +1000,7 @@
struct time_object *tobj;
GetTimeval(time, tobj);
- return
DOUBLE2NUM((double)tobj->tv.tv_sec+(double)tobj->tv.tv_usec/1e6);
- return
DOUBLE2NUM((double)tobj->ts.tv_sec+(double)tobj->ts.tv_nsec/1e9);
}
/*
@@ -889,17 +1021,41 @@
struct time_object *tobj;
GetTimeval(time, tobj);
- return LONG2NUM(tobj->tv.tv_usec);
- return LONG2NUM(tobj->ts.tv_nsec/1000);
}
/*
- call-seq:
-
-
time.nsec => int
-
-
-
time.tv_nsec => int
-
-
-
- Returns just the number of nanoseconds for time.
-
-
-
t = Time.now #=> 2007-11-17 15:18:03 +0900
-
-
-
"%10.9f" % t.to_f #=> "1195280283.536151409"
-
-
-
t.nsec #=> 536151406
-
-
-
- Note that IEEE 754 double is not accurate enough to represent
-
- nanoseconds from the Epoch.
- */
+static VALUE
+time_nsec(VALUE time)
+{
- struct time_object *tobj;
- GetTimeval(time, tobj);
- return LONG2NUM(tobj->ts.tv_nsec);
+}
+/*
-
- call-seq:
-
time <=> other_time => -1, 0, +1
-
time <=> numeric => -1, 0, +1
- Comparison—Compares time with other_time or with
- numeric, which is the number of seconds (possibly
-
- fractional) since epoch.
-
- fractional) since the Epoch.
-
t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
-
t2 = t + 2592000 #=> Fri May 09 08:56:03 CDT 2003
@@ -916,12 +1072,12 @@
GetTimeval(time1, tobj1);
if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
GetTimeval(time2, tobj2);
- if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
-
if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0);
-
if (tobj1->tv.tv_usec > tobj2->tv.tv_usec) return INT2FIX(1);
- if (tobj1->ts.tv_sec == tobj2->ts.tv_sec) {
-
if (tobj1->ts.tv_nsec == tobj2->ts.tv_nsec) return INT2FIX(0);
-
}if (tobj1->ts.tv_nsec > tobj2->ts.tv_nsec) return INT2FIX(1); return INT2FIX(-1);
- if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1);
- if (tobj1->ts.tv_sec > tobj2->ts.tv_sec) return INT2FIX(1);
return INT2FIX(-1);
}
@@ -945,8 +1101,8 @@
GetTimeval(time1, tobj1);
if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
GetTimeval(time2, tobj2);
- if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
-
if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return Qtrue;
-
if (tobj1->ts.tv_sec == tobj2->ts.tv_sec) {
-
if (tobj1->ts.tv_nsec == tobj2->ts.tv_nsec) return Qtrue;
}
}
return Qfalse;
@@ -995,7 +1151,7 @@
long hash;GetTimeval(time, tobj);
- hash = tobj->tv.tv_sec ^ tobj->tv.tv_usec;
- hash = tobj->ts.tv_sec ^ tobj->ts.tv_nsec;
return LONG2FIX(hash);
}
@@ -1053,7 +1209,7 @@
else {
time_modify(time);
}
- t = tobj->tv.tv_sec;
- t = tobj->ts.tv_sec;
tm_tmp = localtime(&t);
if (!tm_tmp)
rb_raise(rb_eArgError, “localtime error”);
@@ -1096,7 +1252,7 @@
else {
time_modify(time);
}
- t = tobj->tv.tv_sec;
- t = tobj->ts.tv_sec;
tm_tmp = gmtime(&t);
if (!tm_tmp)
rb_raise(rb_eArgError, “gmtime error”);
@@ -1211,7 +1367,7 @@
len = strftime(buf, 128, “%Y-%m-%d %H:%M:%S UTC”, &tobj->tm);
}
else {
- time_t off;
- long off;
char buf2[32];
char sign = ‘+’;
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
@@ -1237,7 +1393,8 @@
double v = NUM2DBL(offset);
double f, d;
unsigned_time_t sec_off;
- time_t usec_off, sec, usec;
-
time_t sec;
-
long nsec_off, nsec;
VALUE result;if (v < 0) {
@@ -1249,21 +1406,21 @@
if (f != (double)sec_off)
rb_raise(rb_eRangeError, “time %s %f out of Time range”,
sign < 0 ? “-” : “+”, v);
- usec_off = (time_t)(d*1e6+0.5);
-
nsec_off = (long)(d*1e9+0.5);
if (sign < 0) {
- sec = tobj->tv.tv_sec - sec_off;
- usec = tobj->tv.tv_usec - usec_off;
- if (sec > tobj->tv.tv_sec)
- sec = tobj->ts.tv_sec - sec_off;
- nsec = tobj->ts.tv_nsec - nsec_off;
- if (sec > tobj->ts.tv_sec)
rb_raise(rb_eRangeError, “time - %f out of Time range”, v);
}
else {
- sec = tobj->tv.tv_sec + sec_off;
- usec = tobj->tv.tv_usec + usec_off;
- if (sec < tobj->tv.tv_sec)
- sec = tobj->ts.tv_sec + sec_off;
- nsec = tobj->ts.tv_nsec + nsec_off;
- if (sec < tobj->ts.tv_sec)
rb_raise(rb_eRangeError, “time + %f out of Time range”, v);
}
- result = rb_time_new(sec, usec);
- result = rb_time_nano_new(sec, nsec);
if (tobj->gmt) {
GetTimeval(result, tobj);
tobj->gmt = 1;
@@ -1320,9 +1477,10 @@
double f;
GetTimeval(time2, tobj2);
- f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec;
- f += ((double)tobj->tv.tv_usec - (double)tobj2->tv.tv_usec)*1e-6;
-
f = (double)tobj->ts.tv_sec - (double)tobj2->ts.tv_sec;
-
f += ((double)tobj->ts.tv_nsec - (double)tobj2->ts.tv_nsec)1e-9;
/ XXX: should check float overflow on 64bit time_t platforms */ -
/* XXX: double is not enough to represent nsec */
return DOUBLE2NUM(f);
}
@@ -1344,7 +1502,7 @@GetTimeval(time, tobj);
gmt = tobj->gmt;
- time = rb_time_new(tobj->tv.tv_sec + 1, tobj->tv.tv_usec);
- time = rb_time_nano_new(tobj->ts.tv_sec + 1, tobj->ts.tv_nsec);
GetTimeval(time, tobj);
tobj->gmt = gmt;
return time;
@@ -1745,7 +1903,7 @@
time_t t;
long off;
l = &tobj->tm;
- t = tobj->tv.tv_sec;
-
t = tobj->ts.tv_sec;
u = gmtime(&t);
if (!u)
rb_raise(rb_eArgError, “gmtime error”);
@@ -1935,7 +2093,7 @@GetTimeval(time, tobj);
- t = tobj->tv.tv_sec;
-
t = tobj->ts.tv_sec;
tm = gmtime(&t);if ((tm->tm_year & 0xffff) != tm->tm_year)
@@ -1949,7 +2107,7 @@
tm->tm_hour; /* 5 /
s = tm->tm_min << 26 | / 6 /
tm->tm_sec << 20 | / 6 */
- tobj->tv.tv_usec; /* 20 */
-
tobj->ts.tv_nsec / 1000; /* 20 */
for (i=0; i<4; i++) {
buf[i] = p & 0xff;
@@ -1991,7 +2149,8 @@
{
struct time_object *tobj;
unsigned long p, s;
- time_t sec, usec;
- time_t sec;
- long usec;
unsigned char *buf;
struct tm tm;
int i, gmt;
@@ -2028,15 +2187,15 @@
tm.tm_isdst = 0;
sec = make_time_t(&tm, Qtrue);
- usec = (time_t)(s & 0xfffff);
-
usec = (long)(s & 0xfffff);
}
time_overflow_p(&sec, &usec);GetTimeval(time, tobj);
tobj->tm_got = 0;
tobj->gmt = gmt;
- tobj->tv.tv_sec = sec;
- tobj->tv.tv_usec = usec;
- tobj->ts.tv_sec = sec;
- tobj->ts.tv_nsec = usec * 1000;
return time;
}
@@ -2060,7 +2219,7 @@
/*
-
Time
is an abstraction of dates and times. Time is - stored internally as the number of seconds and microseconds since
-
- the epoch, January 1, 1970 00:00 UTC. On some operating
-
- the Epoch, January 1, 1970 00:00 UTC. On some operating
- systems, this offset is allowed to be negative. Also see the
- library modules
Date
andParseDate
. The -
Time
class treats GMT (Greenwich Mean Time) and UTC
@@ -2145,6 +2304,8 @@
rb_define_method(rb_cTime, “tv_sec”, time_to_i, 0);
rb_define_method(rb_cTime, “tv_usec”, time_usec, 0);
rb_define_method(rb_cTime, “usec”, time_usec, 0);
-
rb_define_method(rb_cTime, “tv_nsec”, time_nsec, 0);
-
rb_define_method(rb_cTime, “nsec”, time_nsec, 0);
rb_define_method(rb_cTime, “strftime”, time_strftime, 1);
Index: include/ruby/missing.h
— include/ruby/missing.h (revision 13950)
+++ include/ruby/missing.h (working copy)
@@ -25,13 +25,20 @@
define time_t long
struct timeval {
time_t tv_sec; /* seconds */
- time_t tv_usec; /* microseconds */
- long tv_usec; /* microseconds */
};
#endif
#if defined(HAVE_SYS_TYPES_H)
include <sys/types.h>
#endif
+#if !defined(HAVE_STRUCT_TIMESPEC)
+struct timespec {
- time_t tv_sec; /* seconds */
- long tv_nsec; /* nanoseconds */
+};
+#endif
#ifndef HAVE_ACOSH
extern double acosh(double);
extern double asinh(double);
Index: include/ruby/intern.h
— include/ruby/intern.h (revision 13950)
+++ include/ruby/intern.h (working copy)
@@ -560,7 +560,8 @@
VALUE rb_barrier_wait(VALUE self);
VALUE rb_barrier_release(VALUE self);
/* time.c /
-VALUE rb_time_new(time_t, time_t);
+VALUE rb_time_new(time_t, long);
+VALUE rb_time_nano_new(time_t, long);
/ variable.c */
VALUE rb_mod_name(VALUE);
VALUE rb_class_path(VALUE);
Index: configure.in
— configure.in (revision 13950)
+++ configure.in (working copy)
@@ -513,6 +513,7 @@
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
AC_CHECK_LIB(socket, socketpair) # SunOS/Solaris
+AC_CHECK_LIB(rt, clock_gettime) # GNU/Linux
case “$target_cpu” in
alpha*) case “$target_os”::"$GCC" in
@@ -553,7 +554,12 @@
AC_STRUCT_ST_BLKSIZE
AC_STRUCT_ST_BLOCKS
AC_STRUCT_ST_RDEV
+AC_CHECK_MEMBERS([struct stat.st_mtim])
+AC_CHECK_MEMBERS([struct stat.st_mtimespec])
+AC_CHECK_MEMBERS([struct stat.st_mtimensec])
+AC_CHECK_TYPES(struct timespec)
+
AC_CHECK_TYPE(fd_mask, [AC_DEFINE(HAVE_RB_FD_INIT, 1)])
AC_CACHE_CHECK(for stack end address, rb_cv_stack_end_address,
@@ -593,8 +599,9 @@
getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups
getpriority getrlimit setrlimit sysconf group_member
dlopen sigprocmask sigaction _setjmp vsnprintf snprintf\
-
setsid telldir seekdir fchmod mktime timegm cosh sinh tanh log2
round\
-
setuid setgid daemon select_large_fdset setenv unsetenv)
-
setsid telldir seekdir fchmod cosh sinh tanh log2 round\
-
setuid setgid daemon select_large_fdset setenv unsetenv\
-
mktime timegm clock_gettime)
AC_ARG_ENABLE(setreuid,
[ --enable-setreuid use setreuid()/setregid() according
to need even if obsolete.],
[use_setreuid=$enableval])
Index: lib/time.rb
— lib/time.rb (revision 13950)
+++ lib/time.rb (working copy)
@@ -461,10 +461,10 @@
year, mon, day, hour, min, sec) +
if fraction_digits == 0
‘’
- elsif fraction_digits <= 6
-
'.' + sprintf('%06d', usec)[0, fraction_digits]
- elsif fraction_digits <= 9
-
else'.' + sprintf('%09d', nsec)[0, fraction_digits]
-
'.' + sprintf('%06d', usec) + '0' * (fraction_digits - 6)
-
end +'.' + sprintf('%09d', nsec) + '0' * (fraction_digits - 9)
if utc?
‘Z’
Index: test/ruby/test_time.rb
===================================================================
— test/ruby/test_time.rb (revision 13950)
+++ test/ruby/test_time.rb (working copy)
@@ -1,4 +1,5 @@
require ‘test/unit’
+require ‘rational’
class TestTime < Test::Unit::TestCase
def test_time_add()
@@ -71,4 +72,38 @@
assert_equal(Time.at(0x7fffffff), Time.at(-0x80000000) -
(-0xffffffff))
end
end
+
- def test_at
- assert_equal(100000, Time.at(0.1).usec)
- assert_equal(10000, Time.at(0.01).usec)
- assert_equal(1000, Time.at(0.001).usec)
- assert_equal(100, Time.at(0.0001).usec)
- assert_equal(10, Time.at(0.00001).usec)
- assert_equal(1, Time.at(0.000001).usec)
- assert_equal(100000000, Time.at(0.1).nsec)
- assert_equal(10000000, Time.at(0.01).nsec)
- assert_equal(1000000, Time.at(0.001).nsec)
- assert_equal(100000, Time.at(0.0001).nsec)
- assert_equal(10000, Time.at(0.00001).nsec)
- assert_equal(1000, Time.at(0.000001).nsec)
- assert_equal(100, Time.at(0.0000001).nsec)
- assert_equal(10, Time.at(0.00000001).nsec)
- assert_equal(1, Time.at(0.000000001).nsec)
- end
- def test_at2
- assert_equal(100, Time.at(0, 0.1).nsec)
- assert_equal(10, Time.at(0, 0.01).nsec)
- assert_equal(1, Time.at(0, 0.001).nsec)
- end
- def test_at_rational
- assert_equal(1, Time.at(Rational(1,1) / 1000000000).nsec)
- assert_equal(1, Time.at(1167609600 + Rational(1,1) /
1000000000).nsec) - end
- def test_utc_subsecond
- assert_equal(100000, Time.utc(2007,1,1,0,0,1.1).usec)
- assert_equal(100000, Time.utc(2007,1,1,0,0,Rational(11,10)).usec)
- end
end
Index: test/yaml/test_yaml.rb
===================================================================
— test/yaml/test_yaml.rb (revision 13950)
+++ test/yaml/test_yaml.rb (working copy)
@@ -54,7 +54,7 @@
hour = zone[0,3].to_i * 3600
min = zone[3,2].to_i * 60
ofs = (hour + min)
-
val = Time.at( val.to_f - ofs )
-
endval = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 )
return val
end
Index: file.c
===================================================================
— file.c (revision 13950)
+++ file.c (working copy)
@@ -43,8 +43,6 @@
#include <time.h>
-VALUE rb_time_new(time_t, time_t);
#ifdef HAVE_UTIME_H
#include <utime.h>
#elif defined HAVE_SYS_UTIME_H
@@ -494,7 +492,57 @@
#endif
}
+static VALUE
+stat_atime(struct stat *st)
+{
- time_t sec = st->st_atime;
- long nsec;
+#if defined(HAVE_STRUCT_STAT_ST_MTIM) - nsec = st->st_atim.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) - nsec = st->st_atimespec.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - nsec = st->st_atimensec;
+#else - nsec = 0;
+#endif - return rb_time_nano_new(sec, nsec);
+}
+static VALUE
+stat_mtime(struct stat *st)
+{
- time_t sec = st->st_mtime;
- long nsec;
+#if defined(HAVE_STRUCT_STAT_ST_MTIM) - nsec = st->st_mtim.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) - nsec = st->st_mtimespec.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - nsec = st->st_mtimensec;
+#else - nsec = 0;
+#endif - return rb_time_nano_new(sec, nsec);
+}
+static VALUE
+stat_ctime(struct stat *st)
+{
- time_t sec = st->st_ctime;
- long nsec;
+#if defined(HAVE_STRUCT_STAT_ST_MTIM) - nsec = st->st_ctim.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) - nsec = st->st_ctimespec.tv_nsec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - nsec = st->st_ctimensec;
+#else - nsec = 0;
+#endif - return rb_time_nano_new(sec, nsec);
+}
/*
- call-seq:
-
stat.atime => time
@@ -509,7 +557,7 @@
static VALUE
rb_stat_atime(VALUE self)
{
- return rb_time_new(get_stat(self)->st_atime, 0);
- return stat_atime(get_stat(self));
}
/*
@@ -525,7 +573,7 @@
static VALUE
rb_stat_mtime(VALUE self)
{
- return rb_time_new(get_stat(self)->st_mtime, 0);
- return stat_mtime(get_stat(self));
}
/*
@@ -543,7 +591,7 @@
static VALUE
rb_stat_ctime(VALUE self)
{
- return rb_time_new(get_stat(self)->st_ctime, 0);
- return stat_ctime(get_stat(self));
}
/*
@@ -1594,7 +1642,7 @@
if (rb_stat(fname, &st) < 0)
rb_sys_fail(StringValueCStr(fname));
- return rb_time_new(st.st_atime, 0);
- return stat_atime(&st);
}
/*
@@ -1618,7 +1666,7 @@
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail(fptr->path);
}
- return rb_time_new(st.st_atime, 0);
- return stat_atime(&st);
}
/*
@@ -1638,7 +1686,7 @@
if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING_PTR(fname));
- return rb_time_new(st.st_mtime, 0);
- return stat_mtime(&st);
}
/*
@@ -1661,7 +1709,7 @@
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail(fptr->path);
}
- return rb_time_new(st.st_mtime, 0);
- return stat_mtime(&st);
}
/*
@@ -1683,7 +1731,7 @@
if (rb_stat(fname, &st) < 0)
rb_sys_fail(RSTRING_PTR(fname));
- return rb_time_new(st.st_ctime, 0);
- return stat_ctime(&st);
}
/*
@@ -1707,7 +1755,7 @@
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail(fptr->path);
}
- return rb_time_new(st.st_ctime, 0);
- return stat_ctime(&st);
}
static void
@@ -3346,11 +3394,11 @@
switch (cmd) {
case ‘A’:
-
return rb_time_new(st.st_atime, 0);
-
case ‘M’:return stat_atime(&st);
-
return rb_time_new(st.st_mtime, 0);
-
case ‘C’:return stat_mtime(&st);
-
return rb_time_new(st.st_ctime, 0);
-
}return stat_ctime(&st);
}