Skip to content

Commit

Permalink
more wrestling of valid time ranges for Ruby 1.8 and 32/64bit platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
brianmario committed Jun 16, 2011
1 parent 9001cf5 commit 2b7992f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
21 changes: 17 additions & 4 deletions ext/mysql2/result.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,26 @@
static rb_encoding *binaryEncoding;
#endif

#define MYSQL2_MAX_YEAR 2038
#if SIZEOF_INT < SIZEOF_LONG
/**
* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
* because of how I'm performing the math below, this will allow a maximum
* timestamp of 9846-12-12T11:5999:59
*/
#define MYSQL2_MAX_YEAR 9999
#else
/**
* on 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
* 2082 = 2038+1+19+3+14+7
*/
#define MYSQL2_MAX_YEAR 2082
#endif

#ifdef NEGATIVE_TIME_T
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
#define MYSQL2_MIN_YEAR 1902
#else
/* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */
/* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */
#define MYSQL2_MIN_YEAR 1970
#endif

Expand Down Expand Up @@ -240,7 +253,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
val = Qnil;
} else {
if (year < MYSQL2_MIN_YEAR || year+month+day > MYSQL2_MAX_YEAR) { // use DateTime instead
if (year < MYSQL2_MIN_YEAR || year+month+day+hour+min+sec > MYSQL2_MAX_YEAR) { // use DateTime instead

This comment has been minimized.

Copy link
@leh

leh Jun 16, 2011

This is probably wrong

This comment has been minimized.

Copy link
@brianmario

brianmario Jun 16, 2011

Author Owner
ree-1.8.7-2011.03 :001 > Time.local 2038,1,19,3,14,7
 => Tue Jan 19 03:14:07 +0000 2038 
ree-1.8.7-2011.03 :002 > Time.local 2038,1,19,3,14,8
ArgumentError: time out of range
    from (irb):2:in `local'
    from (irb):2
    from :0
VALUE offset = INT2NUM(0);
if (db_timezone == intern_local) {
offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
Expand Down
15 changes: 12 additions & 3 deletions spec/mysql2/result_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,18 @@
r.first['test'].class.should eql(DateTime)
end

it "should return DateTime when time > year 2038" do
r = @client.query("SELECT CAST('2039-01-01 01:01:01' AS DATETIME) as test")
r.first['test'].class.should eql(DateTime)
if 1.size == 4 # 32bit
it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
# 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
r.first['test'].class.should eql(DateTime)
end
elsif 1.size == 8 # 64bit
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
# 2038-01-19 03:14:07 is the max for 32bit Ruby 1.8
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
r.first['test'].class.should eql(Time)
end
end

it "should return Time for a TIMESTAMP value when within the supported range" do
Expand Down

0 comments on commit 2b7992f

Please sign in to comment.