summaryrefslogtreecommitdiff
path: root/time.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-12-03 10:07:48 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-12-03 10:07:48 +0000
commitb3144a7a0e08500d212c9f30e889dfcff631fbc4 (patch)
treef07f5ab290541a34d6ce978bc4961917c1c6ac54 /time.c
parent9e8553e5cccd1507597b7726da15a13fcae192af (diff)
* time.c (time_plus): must detect result overflow.
* time.c (time_minus): ditto. * time.c (time_new_internal): round usec overflow and underflow here. * time.c (time_plus): move operand overflow/underflow check to time_new_internal(). * time.c (time_minus): ditto. * time.c (time_cmp): should consider tv_usec too. * time.c (time_gmtime): time_modify() should be called even if tm struct is not calculated yet. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1880 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'time.c')
-rw-r--r--time.c62
1 files changed, 39 insertions, 23 deletions
diff --git a/time.c b/time.c
index e01f99fca5..35ef208802 100644
--- a/time.c
+++ b/time.c
@@ -68,6 +68,14 @@ time_new_internal(klass, sec, usec)
VALUE obj;
struct time_object *tobj;
+ if (usec >= 1000000) { /* usec overflow */
+ sec += usec / 1000000;
+ usec %= 1000000;
+ }
+ if (usec < 0) { /* usec underflow */
+ sec -= (-usec) / 1000000;
+ usec %= 1000000;
+ }
#ifndef NEGATIVE_TIME_T
if (sec < 0 || (sec == 0 && usec < 0))
rb_raise(rb_eArgError, "time must be positive");
@@ -601,7 +609,13 @@ time_cmp(time1, time2)
switch (TYPE(time2)) {
case T_FIXNUM:
i = FIX2LONG(time2);
- if (tobj1->tv.tv_sec == i) return INT2FIX(0);
+ if (tobj1->tv.tv_sec == i) {
+ if (tobj1->tv.tv_usec == 0)
+ return INT2FIX(0);
+ if (tobj1->tv.tv_usec > 0)
+ return INT2FIX(1);
+ return INT2FIX(-1);
+ }
if (tobj1->tv.tv_sec > i) return INT2FIX(1);
return INT2FIX(-1);
@@ -706,8 +720,11 @@ time_localtime(time)
time_t t;
GetTimeval(time, tobj);
- if (tobj->tm_got) {
- if (!tobj->gmt) return time;
+ if (!tobj->gmt) {
+ if (tobj->tm_got)
+ return time;
+ }
+ else {
time_modify(time);
}
t = tobj->tv.tv_sec;
@@ -727,8 +744,11 @@ time_gmtime(time)
time_t t;
GetTimeval(time, tobj);
- if (tobj->tm_got) {
- if (tobj->gmt) return time;
+ if (tobj->gmt) {
+ if (tobj->tm_got)
+ return time;
+ }
+ else {
time_modify(time);
}
t = tobj->tv.tv_sec;
@@ -804,14 +824,12 @@ time_plus(time1, time2)
usec = tobj->tv.tv_usec + (time_t)((f - (double)sec)*1e6);
sec = tobj->tv.tv_sec + sec;
- if (usec >= 1000000) { /* usec overflow */
- sec++;
- usec -= 1000000;
- }
- if (usec < 0) { /* usec underflow */
- sec--;
- usec += 1000000;
+#ifdef NEGATIVE_TIME_T
+ if ((tobj->tv.tv_sec > 0 && f > 0 && sec < 0) ||
+ (tobj->tv.tv_sec < 0 && f < 0 && sec > 0)) {
+ rb_raise(rb_eRangeError, "time + %f out of Time range", f);
}
+#endif
time2 = rb_time_new(sec, usec);
if (tobj->gmt) {
GetTimeval(time2, tobj);
@@ -833,8 +851,8 @@ time_minus(time1, time2)
struct time_object *tobj2;
GetTimeval(time2, tobj2);
- f = tobj->tv.tv_sec - tobj2->tv.tv_sec;
- f += (tobj->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
+ f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec;
+ f += ((double)tobj->tv.tv_usec - (double)tobj2->tv.tv_usec)*1e-6;
return rb_float_new(f);
}
@@ -844,16 +862,14 @@ time_minus(time1, time2)
usec = tobj->tv.tv_usec - (time_t)((f - (double)sec)*1e6);
sec = tobj->tv.tv_sec - sec;
}
-
- if (usec >= 1000000) { /* usec overflow */
- sec++;
- usec -= 1000000;
- }
- if (usec < 0) { /* usec underflow */
- sec--;
- usec += 1000000;
+#ifdef NEGATIVE_TIME_T
+ if ((tobj->tv.tv_sec < 0 && f > 0 && sec > 0) ||
+ (tobj->tv.tv_sec > 0 && f < 0 && sec < 0)) {
+ rb_raise(rb_eRangeError, "time - %f out of Time range", f);
}
- time2 = time_new_internal(rb_obj_class(time1), sec, usec);
+#endif
+
+ time2 = rb_time_new(sec, usec);
if (tobj->gmt) {
GetTimeval(time2, tobj);
tobj->gmt = 1;