Time* Time::from_array(STATE, Fixnum* sec, Fixnum* min, Fixnum* hour, Fixnum* mday, Fixnum* mon, Fixnum* year, Fixnum* usec, Fixnum* isdst, Object* from_gmt) { struct tm tm; tm.tm_sec = sec->to_native(); if(tm.tm_sec < 0 || tm.tm_sec > 60) { Exception::argument_error(state, "sec must be in 0..60"); } tm.tm_min = min->to_native(); if(tm.tm_min < 0 || tm.tm_min > 60) { Exception::argument_error(state, "min must be in 0..60"); } tm.tm_hour = hour->to_native(); if(tm.tm_hour < 0 || tm.tm_hour > 24) { Exception::argument_error(state, "hour must be in 0..24"); } tm.tm_mday = mday->to_native(); if(tm.tm_mday < 1 || tm.tm_mday > 31) { Exception::argument_error(state, "mday must be in 1..31"); } tm.tm_mon = mon->to_native() - 1; if(tm.tm_mon < 0 || tm.tm_mon > 11) { Exception::argument_error(state, "mon must be in 0..11"); } tm.tm_wday = -1; tm.tm_gmtoff = 0; tm.tm_zone = 0; tm.tm_year = year->to_native() - 1900; tm.tm_isdst = isdst->to_native(); time_t seconds = -1; if(RTEST(from_gmt)) { seconds = ::timegm(&tm); } else { tzset(); seconds = ::mktime(&tm); } int err = 0; if(seconds == -1) { int utc_p = from_gmt->true_p() ? 1 : 0; seconds = mktime_extended(&tm, utc_p, &err); } if(err) return (Time*)Primitives::failure(); Time* obj = state->new_object<Time>(G(time_class)); obj->seconds_ = seconds; obj->microseconds_ = usec->to_native(); obj->is_gmt(state, RTEST(from_gmt) ? Qtrue : Qfalse); return obj; }
Time* Time::from_array(STATE, Object* self, Fixnum* sec, Fixnum* min, Fixnum* hour, Fixnum* mday, Fixnum* mon, Fixnum* year, Fixnum* nsec, Fixnum* isdst, Object* from_gmt) { struct tm tm; tm.tm_sec = sec->to_native(); if(tm.tm_sec < 0 || tm.tm_sec > 60) { Exception::argument_error(state, "sec must be in 0..60"); } tm.tm_min = min->to_native(); if(tm.tm_min < 0 || tm.tm_min > 60) { Exception::argument_error(state, "min must be in 0..60"); } tm.tm_hour = hour->to_native(); if(tm.tm_hour < 0 || tm.tm_hour > 24) { Exception::argument_error(state, "hour must be in 0..24"); } tm.tm_mday = mday->to_native(); if(tm.tm_mday < 1 || tm.tm_mday > 31) { Exception::argument_error(state, "mday must be in 1..31"); } tm.tm_mon = mon->to_native() - 1; if(tm.tm_mon < 0 || tm.tm_mon > 11) { Exception::argument_error(state, "mon must be in 0..11"); } tm.tm_wday = -1; #ifdef HAVE_TM_GMTOFF tm.tm_gmtoff = 0; #endif #ifdef HAVE_TM_ZONE tm.tm_zone = 0; #endif tm.tm_year = year->to_native() - 1900; tm.tm_isdst = isdst->to_native(); time_t seconds = -1; if(CBOOL(from_gmt)) { seconds = ::timegm(&tm); } else { tzset(); seconds = ::mktime(&tm); } int err = 0; if(seconds == -1) { int utc_p = from_gmt->true_p() ? 1 : 0; seconds = mktime_extended(&tm, utc_p, &err); } if(err) Exception::argument_error(state, "time out of range"); Time* obj = state->new_object<Time>(as<Class>(self)); obj->seconds_ = seconds; obj->nanoseconds_ = nsec->to_native(); obj->is_gmt(state, CBOOL(from_gmt) ? cTrue : cFalse); return obj; }
Tuple* Time::mktime(STATE, Fixnum* sec, Fixnum* min, Fixnum* hour, Fixnum* mday, Fixnum* mon, Fixnum* year, Fixnum* usec, Fixnum* isdst, Object* from_gmt) { struct tm tm; char *old_tz = NULL; char old_tz_buf[128]; tm.tm_sec = sec->to_native(); if(tm.tm_sec < 0 || tm.tm_sec > 60) { Exception::argument_error(state, "sec must be in 0..60"); } tm.tm_min = min->to_native(); if(tm.tm_min < 0 || tm.tm_min > 60) { Exception::argument_error(state, "min must be in 0..60"); } tm.tm_hour = hour->to_native(); if(tm.tm_hour < 0 || tm.tm_hour > 24) { Exception::argument_error(state, "hour must be in 0..24"); } tm.tm_mday = mday->to_native(); if(tm.tm_mday < 1 || tm.tm_mday > 31) { Exception::argument_error(state, "mday must be in 1..31"); } tm.tm_mon = mon->to_native() - 1; if(tm.tm_mon < 0 || tm.tm_mon > 11) { Exception::argument_error(state, "mon must be in 0..11"); } tm.tm_wday = -1; tm.tm_gmtoff = 0; tm.tm_zone = 0; tm.tm_year = year->to_native() - 1900; /* In theory, we'd set the tm_isdst field to isdst->to_native(). * But since that will break on at least FreeBSD, * and I don't see the point of filling in that flag at all, * we're telling the system here to figure the DST stuff * out itmsg->recv. */ tm.tm_isdst = -1; if(from_gmt->true_p()) { old_tz = getenv("TZ"); /* We need to save old_tz to our own buffer here, because e.g. * FreeBSD's setenv() will manipulate that string directly. */ if(old_tz) { strncpy(old_tz_buf, old_tz, sizeof(old_tz_buf)); old_tz_buf[sizeof(old_tz_buf) - 1] = 0; } setenv("TZ", "", 1); } time_t seconds = ::mktime(&tm); if(seconds == -1) { int err = 0; seconds = mktime_extended(&tm, 1, &err); if(err) { seconds = -1; } } if(from_gmt->true_p()) { if(old_tz) { setenv("TZ", old_tz_buf, 1); } else { unsetenv("TZ"); } } return Tuple::from(state, 2, Integer::from(state, seconds), usec); }