protected Object getNativeDateTimeValue( int columnIndex, byte[] bits, int offset, int length, Calendar targetCalendar, int jdbcType, int mysqlType, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs) throws SQLException { int year = 0; int month = 0; int day = 0; int hour = 0; int minute = 0; int seconds = 0; int nanos = 0; if (bits == null) { return null; } Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn.getUtcCalendar() : rs.getCalendarInstanceForSessionOrNew(); boolean populatedFromDateTimeValue = false; switch (mysqlType) { case MysqlDefs.FIELD_TYPE_DATETIME: case MysqlDefs.FIELD_TYPE_TIMESTAMP: populatedFromDateTimeValue = true; if (length != 0) { year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8); month = bits[offset + 2]; day = bits[offset + 3]; if (length > 4) { hour = bits[offset + 4]; minute = bits[offset + 5]; seconds = bits[offset + 6]; } if (length > 7) { // MySQL uses microseconds nanos = ((bits[offset + 7] & 0xff) | ((bits[offset + 8] & 0xff) << 8) | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000; } } break; case MysqlDefs.FIELD_TYPE_DATE: populatedFromDateTimeValue = true; if (bits.length != 0) { year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8); month = bits[offset + 2]; day = bits[offset + 3]; } break; case MysqlDefs.FIELD_TYPE_TIME: populatedFromDateTimeValue = true; if (bits.length != 0) { // bits[0] // skip tm->neg // binaryData.readLong(); // skip daysPart hour = bits[offset + 5]; minute = bits[offset + 6]; seconds = bits[offset + 7]; } year = 1970; month = 1; day = 1; break; default: populatedFromDateTimeValue = false; } switch (jdbcType) { case Types.TIME: if (populatedFromDateTimeValue) { if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimeCreate( hour, minute, seconds, targetCalendar, this.exceptionInterceptor); } Time time = TimeUtil.fastTimeCreate( rs.getCalendarInstanceForSessionOrNew(), hour, minute, seconds, this.exceptionInterceptor); Time adjustedTime = TimeUtil.changeTimezone( conn, sessionCalendar, targetCalendar, time, conn.getServerTimezoneTZ(), tz, rollForward); return adjustedTime; } return rs.getNativeTimeViaParseConversion(columnIndex + 1, targetCalendar, tz, rollForward); case Types.DATE: if (populatedFromDateTimeValue) { if ((year == 0) && (month == 0) && (day == 0)) { if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( conn.getZeroDateTimeBehavior())) { return null; } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( conn.getZeroDateTimeBehavior())) { throw new SQLException( "Value '0000-00-00' can not be represented as java.sql.Date", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } year = 1; month = 1; day = 1; } if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastDateCreate(year, month, day, targetCalendar); } return rs.fastDateCreate(rs.getCalendarInstanceForSessionOrNew(), year, month, day); } return rs.getNativeDateViaParseConversion(columnIndex + 1); case Types.TIMESTAMP: if (populatedFromDateTimeValue) { if ((year == 0) && (month == 0) && (day == 0)) { if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( conn.getZeroDateTimeBehavior())) { return null; } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( conn.getZeroDateTimeBehavior())) { throw new SQLException( "Value '0000-00-00' can not be represented as java.sql.Timestamp", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } year = 1; month = 1; day = 1; } if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, minute, seconds, nanos); } Timestamp ts = rs.fastTimestampCreate( rs.getCalendarInstanceForSessionOrNew(), year, month, day, hour, minute, seconds, nanos); Timestamp adjustedTs = TimeUtil.changeTimezone( conn, sessionCalendar, targetCalendar, ts, conn.getServerTimezoneTZ(), tz, rollForward); return adjustedTs; } return rs.getNativeTimestampViaParseConversion( columnIndex + 1, targetCalendar, tz, rollForward); default: throw new SQLException( "Internal error - conversion method doesn't support this type", SQLError.SQL_STATE_GENERAL_ERROR); } }
protected Timestamp getNativeTimestamp( byte[] bits, int offset, int length, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs) throws SQLException { int year = 0; int month = 0; int day = 0; int hour = 0; int minute = 0; int seconds = 0; int nanos = 0; if (length != 0) { year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8); month = bits[offset + 2]; day = bits[offset + 3]; if (length > 4) { hour = bits[offset + 4]; minute = bits[offset + 5]; seconds = bits[offset + 6]; } if (length > 7) { // MySQL uses microseconds nanos = ((bits[offset + 7] & 0xff) | ((bits[offset + 8] & 0xff) << 8) | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000; } } if (length == 0 || ((year == 0) && (month == 0) && (day == 0))) { if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( conn.getZeroDateTimeBehavior())) { return null; } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( conn.getZeroDateTimeBehavior())) { throw SQLError.createSQLException( "Value '0000-00-00' can not be represented as java.sql.Timestamp", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } year = 1; month = 1; day = 1; } if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, minute, seconds, nanos); } Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn.getUtcCalendar() : rs.getCalendarInstanceForSessionOrNew(); synchronized (sessionCalendar) { Timestamp ts = rs.fastTimestampCreate(sessionCalendar, year, month, day, hour, minute, seconds, nanos); Timestamp adjustedTs = TimeUtil.changeTimezone( conn, sessionCalendar, targetCalendar, ts, conn.getServerTimezoneTZ(), tz, rollForward); return adjustedTs; } }
protected Timestamp getTimestampFast( int columnIndex, byte[] timestampAsBytes, int offset, int length, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs) throws SQLException { try { Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn.getUtcCalendar() : rs.getCalendarInstanceForSessionOrNew(); synchronized (sessionCalendar) { boolean allZeroTimestamp = true; boolean onlyTimePresent = false; for (int i = 0; i < length; i++) { if (timestampAsBytes[offset + i] == ':') { onlyTimePresent = true; break; } } for (int i = 0; i < length; i++) { byte b = timestampAsBytes[offset + i]; if (b == ' ' || b == '-' || b == '/') { onlyTimePresent = false; } if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/' && b != '.') { allZeroTimestamp = false; break; } } if (!onlyTimePresent && allZeroTimestamp) { if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( conn.getZeroDateTimeBehavior())) { return null; } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( conn.getZeroDateTimeBehavior())) { throw SQLError.createSQLException( "Value '" + StringUtils.toString(timestampAsBytes) + "' can not be represented as java.sql.Timestamp", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimestampCreate(tz, 1, 1, 1, 0, 0, 0, 0); } // We're left with the case of 'round' to a date Java _can_ // represent, which is '0001-01-01'. return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0); } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimestampCreate( tz, StringUtils.getInt(timestampAsBytes, offset, 4), 1, 1, 0, 0, 0, 0); } return TimeUtil.changeTimezone( conn, sessionCalendar, targetCalendar, rs.fastTimestampCreate( sessionCalendar, StringUtils.getInt(timestampAsBytes, offset, 4), 1, 1, 0, 0, 0, 0), conn.getServerTimezoneTZ(), tz, rollForward); } else { if (timestampAsBytes[offset + length - 1] == '.') { length--; } // Convert from TIMESTAMP or DATE int year = 0; int month = 0; int day = 0; int hour = 0; int minutes = 0; int seconds = 0; int nanos = 0; switch (length) { case 29: case 26: case 25: case 24: case 23: case 22: case 21: case 20: case 19: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 4); month = StringUtils.getInt(timestampAsBytes, offset + 5, offset + 7); day = StringUtils.getInt(timestampAsBytes, offset + 8, offset + 10); hour = StringUtils.getInt(timestampAsBytes, offset + 11, offset + 13); minutes = StringUtils.getInt(timestampAsBytes, offset + 14, offset + 16); seconds = StringUtils.getInt(timestampAsBytes, offset + 17, offset + 19); nanos = 0; if (length > 19) { int decimalIndex = -1; for (int i = 0; i < length; i++) { if (timestampAsBytes[offset + i] == '.') { decimalIndex = i; } } if (decimalIndex != -1) { if ((decimalIndex + 2) <= length) { nanos = StringUtils.getInt( timestampAsBytes, offset + decimalIndex + 1, offset + length); int numDigits = (length) - (decimalIndex + 1); if (numDigits < 9) { int factor = (int) (Math.pow(10, 9 - numDigits)); nanos = nanos * factor; } } else { throw new IllegalArgumentException(); // re-thrown // further // down // with // a // much better error message } } } break; } case 14: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 4); month = StringUtils.getInt(timestampAsBytes, offset + 4, offset + 6); day = StringUtils.getInt(timestampAsBytes, offset + 6, offset + 8); hour = StringUtils.getInt(timestampAsBytes, offset + 8, offset + 10); minutes = StringUtils.getInt(timestampAsBytes, offset + 10, offset + 12); seconds = StringUtils.getInt(timestampAsBytes, offset + 12, offset + 14); break; } case 12: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); if (year <= 69) { year = (year + 100); } year += 1900; month = StringUtils.getInt(timestampAsBytes, offset + 2, offset + 4); day = StringUtils.getInt(timestampAsBytes, offset + 4, offset + 6); hour = StringUtils.getInt(timestampAsBytes, offset + 6, offset + 8); minutes = StringUtils.getInt(timestampAsBytes, offset + 8, offset + 10); seconds = StringUtils.getInt(timestampAsBytes, offset + 10, offset + 12); break; } case 10: { boolean hasDash = false; for (int i = 0; i < length; i++) { if (timestampAsBytes[offset + i] == '-') { hasDash = true; break; } } if ((this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) || hasDash) { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 4); month = StringUtils.getInt(timestampAsBytes, offset + 5, offset + 7); day = StringUtils.getInt(timestampAsBytes, offset + 8, offset + 10); hour = 0; minutes = 0; } else { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); if (year <= 69) { year = (year + 100); } month = StringUtils.getInt(timestampAsBytes, offset + 2, offset + 4); day = StringUtils.getInt(timestampAsBytes, offset + 4, offset + 6); hour = StringUtils.getInt(timestampAsBytes, offset + 6, offset + 8); minutes = StringUtils.getInt(timestampAsBytes, offset + 8, offset + 10); year += 1900; // two-digit year } break; } case 8: { boolean hasColon = false; for (int i = 0; i < length; i++) { if (timestampAsBytes[offset + i] == ':') { hasColon = true; break; } } if (hasColon) { hour = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); minutes = StringUtils.getInt(timestampAsBytes, offset + 3, offset + 5); seconds = StringUtils.getInt(timestampAsBytes, offset + 6, offset + 8); year = 1970; month = 1; day = 1; break; } year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 4); month = StringUtils.getInt(timestampAsBytes, offset + 4, offset + 6); day = StringUtils.getInt(timestampAsBytes, offset + 6, offset + 8); year -= 1900; month--; break; } case 6: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); if (year <= 69) { year = (year + 100); } year += 1900; month = StringUtils.getInt(timestampAsBytes, offset + 2, offset + 4); day = StringUtils.getInt(timestampAsBytes, offset + 4, offset + 6); break; } case 4: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); if (year <= 69) { year = (year + 100); } month = StringUtils.getInt(timestampAsBytes, offset + 2, offset + 4); day = 1; break; } case 2: { year = StringUtils.getInt(timestampAsBytes, offset + 0, offset + 2); if (year <= 69) { year = (year + 100); } year += 1900; month = 1; day = 1; break; } default: throw new java.sql.SQLException( "Bad format for Timestamp '" + StringUtils.toString(timestampAsBytes) + "' in column " + (columnIndex + 1) + ".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } if (!rs.useLegacyDatetimeCode) { return TimeUtil.fastTimestampCreate( tz, year, month, day, hour, minutes, seconds, nanos); } return TimeUtil.changeTimezone( conn, sessionCalendar, targetCalendar, rs.fastTimestampCreate( sessionCalendar, year, month, day, hour, minutes, seconds, nanos), conn.getServerTimezoneTZ(), tz, rollForward); } } } catch (RuntimeException e) { SQLException sqlEx = SQLError.createSQLException( "Cannot convert value '" + getString(columnIndex, "ISO8859_1", conn) + "' from column " + (columnIndex + 1) + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); sqlEx.initCause(e); throw sqlEx; } }