Skip to content

Commit 62a8145

Browse files
nyaxtjustincase
authored andcommitted
DateTime conversion is consistent with Client#query results / all test pass on 1.8.7
1 parent 1a0a124 commit 62a8145

File tree

1 file changed

+39
-18
lines changed

1 file changed

+39
-18
lines changed

ext/mysql2/result.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -408,33 +408,54 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
408408
val = rb_float_new((double)(*((double*)result_buffer->buffer)));
409409
break;
410410
case MYSQL_TYPE_DATE: // MYSQL_TIME
411+
case MYSQL_TYPE_NEWDATE: // MYSQL_TIME
411412
ts = (MYSQL_TIME*)result_buffer->buffer;
412413
val = rb_funcall(cDate, rb_intern("new"), 3, INT2NUM(ts->year), INT2NUM(ts->month), INT2NUM(ts->day));
413414
break;
414415
case MYSQL_TYPE_TIME: // MYSQL_TIME
415416
ts = (MYSQL_TIME*)result_buffer->buffer;
416-
val = rb_funcall(rb_cTime,
417-
rb_intern("mktime"), 6,
418-
opt_time_year,
419-
opt_time_month,
420-
opt_time_month,
421-
UINT2NUM(ts->hour),
422-
UINT2NUM(ts->minute),
423-
UINT2NUM(ts->second));
417+
val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second));
418+
if (!NIL_P(app_timezone)) {
419+
if (app_timezone == intern_local) {
420+
val = rb_funcall(val, intern_localtime, 0);
421+
} else { // utc
422+
val = rb_funcall(val, intern_utc, 0);
423+
}
424+
}
424425
break;
425-
case MYSQL_TYPE_NEWDATE: // MYSQL_TIME
426426
case MYSQL_TYPE_DATETIME: // MYSQL_TIME
427-
case MYSQL_TYPE_TIMESTAMP: // MYSQL_TIME
427+
case MYSQL_TYPE_TIMESTAMP: { // MYSQL_TIME
428+
uint64_t seconds;
429+
428430
ts = (MYSQL_TIME*)result_buffer->buffer;
429-
val = rb_funcall(rb_cTime,
430-
rb_intern("mktime"), 6,
431-
UINT2NUM(ts->year),
432-
UINT2NUM(ts->month),
433-
UINT2NUM(ts->day),
434-
UINT2NUM(ts->hour),
435-
UINT2NUM(ts->minute),
436-
UINT2NUM(ts->second));
431+
seconds = (ts->year*31557600ULL) + (ts->month*2592000ULL) + (ts->day*86400ULL) + (ts->hour*3600ULL) + (ts->minute*60ULL) + ts->second;
432+
433+
if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { // use DateTime instead
434+
VALUE offset = INT2NUM(0);
435+
if (db_timezone == intern_local) {
436+
offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
437+
}
438+
val = rb_funcall(cDateTime, intern_civil, 7, UINT2NUM(ts->year), UINT2NUM(ts->month), UINT2NUM(ts->day), UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second), offset);
439+
if (!NIL_P(app_timezone)) {
440+
if (app_timezone == intern_local) {
441+
offset = rb_funcall(cMysql2Client, intern_local_offset, 0);
442+
val = rb_funcall(val, intern_new_offset, 1, offset);
443+
} else { // utc
444+
val = rb_funcall(val, intern_new_offset, 1, opt_utc_offset);
445+
}
446+
}
447+
} else {
448+
val = rb_funcall(rb_cTime, db_timezone, 6, UINT2NUM(ts->year), UINT2NUM(ts->month), UINT2NUM(ts->day), UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second));
449+
if (!NIL_P(app_timezone)) {
450+
if (app_timezone == intern_local) {
451+
val = rb_funcall(val, intern_localtime, 0);
452+
} else { // utc
453+
val = rb_funcall(val, intern_utc, 0);
454+
}
455+
}
456+
}
437457
break;
458+
}
438459
case MYSQL_TYPE_DECIMAL: // char[]
439460
case MYSQL_TYPE_NEWDECIMAL: // char[]
440461
val = rb_funcall(cBigDecimal, rb_intern("new"), 1, rb_str_new(result_buffer->buffer, *(result_buffer->length)));

0 commit comments

Comments
 (0)