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

Allow constructing a microsoft.sql.DateTimeOffset instance from a java.time.OffsetDateTime value #2339

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/main/java/microsoft/sql/DateTimeOffset.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ private DateTimeOffset(java.sql.Timestamp timestamp, int minutesOffset) {
assert 0 == this.utcMillis % 1000L : "utcMillis: " + this.utcMillis;
}

/**
* Constructs a DateTimeOffset from an existing java.time.OffsetDateTime
*
* @param offsetDateTime A java.time.OffsetDateTime value
* @apiNote DateTimeOffset represents values to 100ns precision. If the java.time.OffsetDateTime instance represents
* a value that is more precise, values in excess of the 100ns precision are rounded to the nearest
* multiple of 100ns. Values within 50 nanoseconds of the next second are rounded up to the next second.
*/
private DateTimeOffset(java.time.OffsetDateTime offsetDateTime) {
int hundredNanos = ((offsetDateTime.getNano() + 50) / 100);
this.utcMillis = (offsetDateTime.toEpochSecond() * 1000) + (hundredNanos / HUNDRED_NANOS_PER_SECOND * 1000);
this.nanos = 100 * (hundredNanos % HUNDRED_NANOS_PER_SECOND);
this.minutesOffset = offsetDateTime.getOffset().getTotalSeconds() / 60;
}

/**
* Converts a java.sql.Timestamp value with an integer offset to the equivalent DateTimeOffset value
*
Expand Down Expand Up @@ -105,6 +120,19 @@ public static DateTimeOffset valueOf(java.sql.Timestamp timestamp, Calendar cale
(calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET)) / (60 * 1000));
}

/**
* Directly converts a {@link java.time.OffsetDateTime} value to an equivalent {@link DateTimeOffset} value
*
* @param offsetDateTime A java.time.OffsetDateTime value
* @return The DateTimeOffset value of the input java.time.OffsetDateTime
* @apiNote DateTimeOffset represents values to 100ns precision. If the java.time.OffsetDateTime instance represents
* a value that is more precise, values in excess of the 100ns precision are rounded to the nearest
* multiple of 100ns. Values within 50 nanoseconds of the next second are rounded up to the next second.
*/
public static DateTimeOffset valueOf(java.time.OffsetDateTime offsetDateTime) {
return new DateTimeOffset(offsetDateTime);
}

/** formatted value */
private String formattedValue = null;

Expand Down
51 changes: 51 additions & 0 deletions src/test/java/microsoft/sql/DateTimeOffsetTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 microsoft.sql;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.OffsetDateTime;
import java.time.ZoneOffset;

public class DateTimeOffsetTest {

@Test
@DisplayName("DateTimeOffset.valueOf(offsetDateTime) instantiates correct DateTimeOffset instances.")
void valueOfOffsetDateTime() {
int nanos = 123456789;
int hundredNanos = 1234568; // DateTimeOffset has a precision of 100 nanos of second
OffsetDateTime offsetDateTime = OffsetDateTime.of(
2024,
2,
25,
23,
55,
6,
nanos,
ZoneOffset.ofHoursMinutes(1, 30)
);
Assertions
.assertEquals(
offsetDateTime.withNano(hundredNanos * 100),
DateTimeOffset.valueOf(offsetDateTime).getOffsetDateTime()
);
}

@Test
@DisplayName("DateTimeOffset.valueOf(offsetDateTime) correctly rounds up values within 50 nanoseconds of the next second.")
void valueOfOffsetDateTimeRounding() {
OffsetDateTime offsetDateTime = OffsetDateTime.now().withNano(999999950);
Assertions
.assertEquals(
offsetDateTime
.withSecond(offsetDateTime.getSecond() + 1)
.withNano(0),
DateTimeOffset.valueOf(offsetDateTime).getOffsetDateTime()
);
}
}
Loading