diff --git a/ext/mysql2/result.c b/ext/mysql2/result.c index 4f46baf26..a1dea9a01 100644 --- a/ext/mysql2/result.c +++ b/ext/mysql2/result.c @@ -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 @@ -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 VALUE offset = INT2NUM(0); if (db_timezone == intern_local) { offset = rb_funcall(cMysql2Client, intern_local_offset, 0); diff --git a/spec/mysql2/result_spec.rb b/spec/mysql2/result_spec.rb index 11f180b28..cae9035c5 100644 --- a/spec/mysql2/result_spec.rb +++ b/spec/mysql2/result_spec.rb @@ -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