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

Fixing LocalTime rounding (losing precision) #1570

Merged
merged 7 commits into from
Jan 29, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class TimestampUtils {
private static final Duration ONE_MICROSECOND = Duration.ofNanos(1000);
// LocalTime.MAX is 23:59:59.999_999_999, and it wraps to 24:00:00 when nanos exceed 999_999_499
// since PostgreSQL has microsecond resolution only
private static final LocalTime MAX_TIME = LocalTime.MAX.minus(Duration.ofMillis(500));
private static final LocalTime MAX_TIME = LocalTime.MAX.minus(Duration.ofNanos(500));
private static final OffsetDateTime MAX_OFFSET_DATETIME = OffsetDateTime.MAX.minus(Duration.ofMillis(500));
private static final LocalDateTime MAX_LOCAL_DATETIME = LocalDateTime.MAX.minus(Duration.ofMillis(500));
// low value for dates is 4713 BC
Expand Down
74 changes: 74 additions & 0 deletions pgjdbc/src/test/java/org/postgresql/jdbc/TimestampUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2003, PostgreSQL Global Development Group
franetw marked this conversation as resolved.
Show resolved Hide resolved
* See the LICENSE file in the project root for more information.
*/

package org.postgresql.jdbc;

import static org.junit.Assert.assertEquals;

import org.postgresql.core.Provider;

import org.junit.Test;

import java.sql.SQLException;
import java.time.LocalTime;
import java.util.TimeZone;

public class TimestampUtilsTest {

@Test
public void testToStringOfLocalTime() {
TimestampUtils timestampUtils = createTimestampUtils();

assertEquals("00:00:00", timestampUtils.toString(LocalTime.parse("00:00:00")));
assertEquals("00:00:00.1", timestampUtils.toString(LocalTime.parse("00:00:00.1")));
assertEquals("00:00:00.12", timestampUtils.toString(LocalTime.parse("00:00:00.12")));
assertEquals("00:00:00.123", timestampUtils.toString(LocalTime.parse("00:00:00.123")));
assertEquals("00:00:00.1234", timestampUtils.toString(LocalTime.parse("00:00:00.1234")));
assertEquals("00:00:00.12345", timestampUtils.toString(LocalTime.parse("00:00:00.12345")));
assertEquals("00:00:00.123456", timestampUtils.toString(LocalTime.parse("00:00:00.123456")));

assertEquals("00:00:00.999999", timestampUtils.toString(LocalTime.parse("00:00:00.999999")));
assertEquals("00:00:00.999999", timestampUtils.toString(LocalTime.parse("00:00:00.999999499"))); // 499 NanoSeconds
assertEquals("00:00:01", timestampUtils.toString(LocalTime.parse("00:00:00.999999500"))); // 500 NanoSeconds

assertEquals("23:59:59", timestampUtils.toString(LocalTime.parse("23:59:59")));
assertEquals("23:59:59.999999", timestampUtils.toString(LocalTime.parse("23:59:59.999999"))); // 0 NanoSeconds
assertEquals("23:59:59.999999", timestampUtils.toString(LocalTime.parse("23:59:59.999999499"))); // 499 NanoSeconds
assertEquals("24:00:00", timestampUtils.toString(LocalTime.parse("23:59:59.999999500")));// 500 NanoSeconds
assertEquals("24:00:00", timestampUtils.toString(LocalTime.parse("23:59:59.999999999")));// 999 NanoSeconds
}

@Test
public void testToLocalTime() throws SQLException {
TimestampUtils timestampUtils = createTimestampUtils();

assertEquals(LocalTime.parse("00:00:00"), timestampUtils.toLocalTime("00:00:00"));

assertEquals(LocalTime.parse("00:00:00.1"), timestampUtils.toLocalTime("00:00:00.1"));
assertEquals(LocalTime.parse("00:00:00.12"), timestampUtils.toLocalTime("00:00:00.12"));
assertEquals(LocalTime.parse("00:00:00.123"), timestampUtils.toLocalTime("00:00:00.123"));
assertEquals(LocalTime.parse("00:00:00.1234"), timestampUtils.toLocalTime("00:00:00.1234"));
assertEquals(LocalTime.parse("00:00:00.12345"), timestampUtils.toLocalTime("00:00:00.12345"));
assertEquals(LocalTime.parse("00:00:00.123456"), timestampUtils.toLocalTime("00:00:00.123456"));
assertEquals(LocalTime.parse("00:00:00.999999"), timestampUtils.toLocalTime("00:00:00.999999"));

assertEquals(LocalTime.parse("23:59:59"), timestampUtils.toLocalTime("23:59:59"));
assertEquals(LocalTime.parse("23:59:59.999999"), timestampUtils.toLocalTime("23:59:59.999999")); // 0 NanoSeconds
assertEquals(LocalTime.parse("23:59:59.9999999"), timestampUtils.toLocalTime("23:59:59.9999999")); // 900 NanoSeconds
assertEquals(LocalTime.parse("23:59:59.99999999"), timestampUtils.toLocalTime("23:59:59.99999999")); // 990 NanoSeconds
assertEquals(LocalTime.parse("23:59:59.999999998"), timestampUtils.toLocalTime("23:59:59.999999998")); // 998 NanoSeconds
assertEquals(LocalTime.parse("23:59:59.999999999"), timestampUtils.toLocalTime("24:00:00"));
}

private TimestampUtils createTimestampUtils() {
return new TimestampUtils(true, new Provider<TimeZone>() {
@Override
public TimeZone get() {
return TimeZone.getDefault();
}
});
}

}