Skip to content

conversion for TIME '24:00' to LocalTime breaks in binary-mode #3224

@pmenke-de

Description

@pmenke-de

Describe the issue
Retrieving a TIME value of '24:00' via ResultSet#getObject(int, LocalTime.class) results in a java.time.DateTimeException, when the value is transmitted in binary:

Invalid value for NanoOfDay (valid values 0 - 86399999999999): 86400000000000
java.time.DateTimeException: Invalid value for NanoOfDay (valid values 0 - 86399999999999): 86400000000000
	at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:319)
	at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:718)
	at java.base/java.time.LocalTime.ofNanoOfDay(LocalTime.java:400)
	at org.postgresql.jdbc.TimestampUtils.toLocalTimeBin(TimestampUtils.java:1440)

Driver Version?
42.7.3

Java Version?
OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode)

OS Version?
Debian 12

PostgreSQL Version?
PostgreSQL 15.6 (Debian 15.6-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

To Reproduce
Steps to reproduce the behaviour:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class TestLocalDateMax {
    public static void main(String []args) throws Exception {

        // it may be necessary to specify `?prepareThreshold=-1` in the URL to force binary transfer 
        String url = "jdbc:postgresql://localhost:5432/test";

        Properties props = new Properties();
        props.setProperty("user", "test");
        props.setProperty("password", "test");
        try ( Connection conn = DriverManager.getConnection(url, props) ){
            try ( Statement statement = conn.createStatement() ) {
                try (ResultSet rs = statement.executeQuery( "SELECT TIME '24:00'") ){
                    if (rs.next())
                        System.out.println( "Get String: " + rs.getObject(1, LocalTime.class));
                }
            }
        }
    }
}

Expected behaviour
TIME '24:00' should convert to LocalTime.MAX - as it does, when the value is transferred in text-mode

Side note
TIMETZ (time with time zone) values of 24:00 (regardless of the specified offset) also suffer from the same issue (ResultSet#getObject(int, OffsetTime.class)). But the existing/working conversion of text-values seems to be a whole'nother can of worms (if the text-value starts-with 24:00:00, the server-sent offset is discarded and OffsetTime.MAX (offset -18:00) is used.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions