|
4 | 4 | static rb_encoding *binaryEncoding;
|
5 | 5 | #endif
|
6 | 6 |
|
7 |
| -#if SIZEOF_INT < SIZEOF_LONG |
8 |
| -/** |
9 |
| - * on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07 |
10 |
| - * because of how I'm performing the math below, this will allow a maximum |
11 |
| - * timestamp of 9846-12-12T11:5999:59 |
12 |
| -*/ |
13 |
| -#define MYSQL2_MAX_YEAR 9999 |
| 7 | +#if (SIZEOF_INT < SIZEOF_LONG) || defined(HAVE_RUBY_ENCODING_H) |
| 8 | +/* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07 |
| 9 | + * |
| 10 | + * (9999*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59 |
| 11 | + */ |
| 12 | +#define MYSQL2_MAX_TIME 315578267999ULL |
14 | 13 | #else
|
15 | 14 | /**
|
16 |
| - * on 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07 |
17 |
| - * 2082 = 2038+1+19+3+14+7 |
| 15 | + * On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07 |
| 16 | + * 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds |
| 17 | + * |
| 18 | + * (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7 |
18 | 19 | */
|
19 |
| -#define MYSQL2_MAX_YEAR 2082 |
| 20 | +#define MYSQL2_MAX_TIME 64318634047ULL |
20 | 21 | #endif
|
21 | 22 |
|
22 |
| -#ifdef NEGATIVE_TIME_T |
23 |
| -/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */ |
24 |
| -#define MYSQL2_MIN_YEAR 1902 |
| 23 | +#if defined(HAVE_RUBY_ENCODING_H) |
| 24 | +/* 0000-1-1 00:00:00 UTC |
| 25 | + * |
| 26 | + * (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0 |
| 27 | + */ |
| 28 | +#define MYSQL2_MIN_TIME 2678400ULL |
| 29 | +#elif SIZEOF_INT < SIZEOF_LONG // 64bit Ruby 1.8 |
| 30 | +/* 0139-1-1 00:00:00 UTC |
| 31 | + * |
| 32 | + * (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0 |
| 33 | + */ |
| 34 | +#define MYSQL2_MIN_TIME 4389184800ULL |
| 35 | +#elif defined(NEGATIVE_TIME_T) |
| 36 | +/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. |
| 37 | + * |
| 38 | + * (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52 |
| 39 | + */ |
| 40 | +#define MYSQL2_MIN_TIME 60023299552ULL |
25 | 41 | #else
|
26 |
| -/* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */ |
27 |
| -#define MYSQL2_MIN_YEAR 1970 |
| 42 | +/* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t. |
| 43 | + * |
| 44 | + * (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1 |
| 45 | + */ |
| 46 | +#define MYSQL2_MIN_TIME 62171150401ULL |
28 | 47 | #endif
|
29 | 48 |
|
30 | 49 | static VALUE cMysql2Result;
|
@@ -244,16 +263,20 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
244 | 263 | }
|
245 | 264 | case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
|
246 | 265 | case MYSQL_TYPE_DATETIME: { // DATETIME field
|
247 |
| - int year, month, day, hour, min, sec, tokens; |
| 266 | + unsigned int year, month, day, hour, min, sec, tokens; |
| 267 | + uint64_t seconds; |
| 268 | + |
248 | 269 | tokens = sscanf(row[i], "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
|
249 |
| - if (year+month+day+hour+min+sec == 0) { |
| 270 | + seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec; |
| 271 | + |
| 272 | + if (seconds == 0) { |
250 | 273 | val = Qnil;
|
251 | 274 | } else {
|
252 | 275 | if (month < 1 || day < 1) {
|
253 | 276 | rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
|
254 | 277 | val = Qnil;
|
255 | 278 | } else {
|
256 |
| - if (year < MYSQL2_MIN_YEAR || year+month+day+hour+min+sec > MYSQL2_MAX_YEAR) { // use DateTime instead |
| 279 | + if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { // use DateTime instead |
257 | 280 | VALUE offset = INT2NUM(0);
|
258 | 281 | if (db_timezone == intern_local) {
|
259 | 282 | offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
|
|
0 commit comments