summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-time/src/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-time/src/time.c')
-rw-r--r--mrbgems/mruby-time/src/time.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index 8903c522a..081e84c1c 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -4,6 +4,7 @@
** See Copyright Notice in mruby.h
*/
+#include <math.h>
#include <stdio.h>
#include <time.h>
#include "mruby.h"
@@ -80,7 +81,7 @@ gettimeofday(struct timeval *tv, void *tz)
t.u64 -= UI64(116444736000000000); /* Unix epoch bias */
t.u64 /= 10; /* to microseconds */
tv->tv_sec = (time_t)(t.u64 / (1000 * 1000));
- tv->tv_usec = t.u64 % 1000 * 1000;
+ tv->tv_usec = t.u64 % (1000 * 1000);
}
return 0;
}
@@ -200,20 +201,23 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
struct mrb_time *tm;
tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
- tm->sec = (time_t)sec;
if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
goto out_of_range;
}
- else if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) {
+ if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) {
+ goto out_of_range;
+ }
+ tm->sec = (time_t)sec;
+ if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) {
out_of_range:
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec));
}
- tm->usec = (time_t)((sec - tm->sec) * 1.0e6 + usec);
+ tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
while (tm->usec < 0) {
tm->sec--;
tm->usec += 1000000;
}
- while (tm->usec > 1000000) {
+ while (tm->usec >= 1000000) {
tm->sec++;
tm->usec -= 1000000;
}
@@ -235,7 +239,17 @@ current_mrb_time(mrb_state *mrb)
struct mrb_time *tm;
tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
-#ifdef NO_GETTIMEOFDAY
+#if defined(TIME_UTC)
+ {
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_UTC) == 0) {
+ mrb_free(mrb, tm);
+ mrb_raise(mrb, E_RUNTIME_ERROR, "timespec_get() failed for unknown reasons");
+ }
+ tm->sec = ts.tv_sec;
+ tm->usec = ts.tv_nsec / 1000;
+ }
+#elif defined(NO_GETTIMEOFDAY)
{
static time_t last_sec = 0, last_usec = 0;
@@ -561,8 +575,7 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
if (tm) {
mrb_free(mrb, tm);
}
- DATA_TYPE(self) = &mrb_time_type;
- DATA_PTR(self) = NULL;
+ mrb_data_init(self, NULL, &mrb_time_type);
n = mrb_get_args(mrb, "|iiiiiii",
&ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
@@ -572,7 +585,7 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
else {
tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
}
- DATA_PTR(self) = tm;
+ mrb_data_init(self, tm, &mrb_time_type);
return self;
}
@@ -589,8 +602,7 @@ mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
}
if (!DATA_PTR(copy)) {
- DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct mrb_time));
- DATA_TYPE(copy) = &mrb_time_type;
+ mrb_data_init(copy, mrb_malloc(mrb, sizeof(struct mrb_time)), &mrb_time_type);
}
*(struct mrb_time *)DATA_PTR(copy) = *(struct mrb_time *)DATA_PTR(src);
return copy;
@@ -673,6 +685,9 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
+ return mrb_float_value(mrb, (mrb_float)tm->sec);
+ }
return mrb_fixnum_value((mrb_int)tm->sec);
}
@@ -684,6 +699,9 @@ mrb_time_usec(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
+ return mrb_float_value(mrb, (mrb_float)tm->usec);
+ }
return mrb_fixnum_value((mrb_int)tm->usec);
}