Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.time.OffsetDateTime value sent to the server should not be affected by the default time zone. #831

Merged
merged 6 commits into from
Dec 28, 2018
Merged
17 changes: 3 additions & 14 deletions src/main/java/com/microsoft/sqlserver/jdbc/dtv.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -630,11 +629,8 @@ private void sendTemporal(DTV dtv, JavaType javaType, Object value) throws SQLSe
* 1000,
"");

// The behavior is similar to microsoft.sql.DateTimeOffset
// In Timestamp format, leading zeros for the fields can be omitted.
String offsetTimeStr = conn.baseYear() + "-01-01" + ' ' + offsetTimeValue.getHour() + ':'
+ offsetTimeValue.getMinute() + ':' + offsetTimeValue.getSecond();
utcMillis = Timestamp.valueOf(offsetTimeStr).getTime();
LocalDate baseDate = LocalDate.of(conn.baseYear(), 1, 1);
utcMillis = offsetTimeValue.atDate(baseDate).toEpochSecond() * 1000;
break;

case OFFSETDATETIME:
Expand Down Expand Up @@ -679,14 +675,7 @@ private void sendTemporal(DTV dtv, JavaType javaType, Object value) throws SQLSe
* 1000,
"");

// The behavior is similar to microsoft.sql.DateTimeOffset
// In Timestamp format, only YEAR needs to have 4 digits. The leading zeros for the rest of the
// fields can be omitted.
String offDateTimeStr = String.format("%04d", offsetDateTimeValue.getYear()) + '-'
+ offsetDateTimeValue.getMonthValue() + '-' + offsetDateTimeValue.getDayOfMonth() + ' '
+ offsetDateTimeValue.getHour() + ':' + offsetDateTimeValue.getMinute() + ':'
+ offsetDateTimeValue.getSecond();
utcMillis = Timestamp.valueOf(offDateTimeStr).getTime();
utcMillis = offsetDateTimeValue.toEpochSecond() * 1000;
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved
break;

case DATETIMEOFFSET: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
* available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc.preparedStatement;

import static org.junit.jupiter.api.Assertions.*;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.OffsetDateTime;
import java.time.OffsetTime;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerConnection;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;


@RunWith(JUnitPlatform.class)
public class SetObjectTest extends AbstractTest {
private static final String tableName = RandomUtil.getIdentifier("SetObjectTestTable");

/**
* Tests setObject(n, java.time.OffsetDateTime.class).
*
* @throws SQLException
*/
@Test
public void testSetObjectWithOffsetDateTime() throws SQLException {
try (Connection con = DriverManager.getConnection(connectionString)) {
final String testValue = "2018-01-02T11:22:33.123456700+12:34";
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " (id INT PRIMARY KEY, dto DATETIMEOFFSET)");
try {
try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO "
+ AbstractSQLGenerator.escapeIdentifier(tableName) + " (id, dto) VALUES (?, ?)")) {
pstmt.setInt(1, 1);
pstmt.setObject(2, OffsetDateTime.parse(testValue));
pstmt.executeUpdate();
}

try (ResultSet rs = stmt
.executeQuery("SELECT COUNT(*) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " WHERE id = 1 AND dto = '" + testValue + "'")) {
rs.next();
assertEquals(1, rs.getInt(1));
}
} finally {
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt);
}
}
}
}

/**
* Tests setObject(n, java.time.OffsetTime.class).
*
* @throws SQLException
*/
@Test
public void testSetObjectWithOffsetTime() throws SQLException {
try (Connection con = DriverManager.getConnection(connectionString)) {
final String testValue = "11:22:33.123456700+12:34";
final String expectedDto = "1970-01-01T" + testValue;
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " (id INT PRIMARY KEY, dto DATETIMEOFFSET)");
try {
try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO "
+ AbstractSQLGenerator.escapeIdentifier(tableName) + " (id, dto) VALUES (?, ?)")) {
pstmt.setInt(1, 1);
pstmt.setObject(2, OffsetTime.parse(testValue));
pstmt.executeUpdate();
}

try (ResultSet rs = stmt
.executeQuery("SELECT COUNT(*) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " WHERE id = 1 AND dto = '" + expectedDto + "'")) {
rs.next();
assertEquals(1, rs.getInt(1));
}
} finally {
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt);
}
}
}
}

/**
* Tests setObject(n, java.time.OffsetTime.class) when 'setSendTimeAsDatetime' connection property is false.
*
* @throws SQLException
*/
@Test
public void testSetObjectWithOffsetTime_sendTimeAsDatetimeDisabled() throws SQLException {
try (Connection con = DriverManager.getConnection(connectionString)) {
((SQLServerConnection) con).setSendTimeAsDatetime(false);
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved
final String testValue = "11:22:33.123456700+12:34";
final String expectedDto = "1900-01-01T" + testValue;
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " (id INT PRIMARY KEY, dto DATETIMEOFFSET)");
try {
try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO "
+ AbstractSQLGenerator.escapeIdentifier(tableName) + " (id, dto) VALUES (?, ?)")) {
pstmt.setInt(1, 1);
pstmt.setObject(2, OffsetTime.parse(testValue));
pstmt.executeUpdate();
}

try (ResultSet rs = stmt
.executeQuery("SELECT COUNT(*) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)
+ " WHERE id = 1 AND dto = '" + expectedDto + "'")) {
rs.next();
assertEquals(1, rs.getInt(1));
}
} finally {
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt);
}
}
}
}
}