Java Converting Retrieved TimeStamp to Instant Gives Wrong Day

376 Views Asked by At

I've made a simple method which is used to convert a timestamp retrieved from a database into a LocalDate. However for some reason I keep getting the wrong day in the conversion. I've shared the code below.

    private LocalDate getLocalDateFromTimeStamp(Row row, String key){
        return LocalDate.parse(row.getTimestamp(key).toInstant().atZone(ZoneOffset.UTC).toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}

So the date I'm expecting is 2022-12-21 but what I get is 2022-12-22.

When I debug and check what

row.getTimestamp(key)

gets me a Date object of Wed Dec 21 20:47:46 CST 2022 which is what I expect.

When I check what

row.getTimestamp(key).toInstant()

does, I get "2022-12-22T02:47:46.299Z". And I think this is where the problem is popping up and I'm not sure why it's happening. The LocalDate that's returned by the method is "2022-12-22".

If anyone could shine a light on this I'd really appreciate it as I'm lost as to why this is happening.

2

There are 2 best solutions below

9
WJS On BEST ANSWER

Try it like this. Check out DateTimeFormatter for details on the following arguments.

String date = "Wed Dec 21 20:47:46 CST 2022";
  • EEE three letter day of week
  • MMM three letter month
  • dd integer day
  • HH:mm:ss time using 24 hour clock
  • z time zone name (CST)
  • yyyy year
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
LocalDate dt = LocalDateTime.parse(date, dtf).toLocalDate();
System.out.println(dt);

prints

2022-12-21

Updated

If you actually have an instance of Date you might try the following:

LocalDate ldt = LocalDate.ofInstant(date.toInstant(), 
    ZoneId.systemDefault());
0
Basil Bourque On

tl;dr

Avoid unnecessary string manipulation. Use date-time types for date-time values.

myResultSet
.getObject( … , OffsetDateTime.class )  // For any database column of a data type akin to the SQL standard type of `TIMESTAMP WITH TIME ZONE`.
.toLocalDate()  // Extract the date portion from the returned `OffsetDateTime` object. 
.toString()     // Generate text in standard ISO 8601 format. 

Details

The Timestamp class is part of the terrible date-time classes that are now legacy. Use only their replacements, the modern java.time classes defined in JSR 310.

Instead of Timestamp, use OffsetDateTime with JDBC 4.2 and later. Do this for any database column of a data type akin to the SQL standard type of TIMESTAMP WITH TIME ZONE.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

Your Question is not clear, but you seem to want the date portion of that moment as seen with an offset from UTC of zero hours-minutes-seconds.

The retrieved OffsetDateTime is likely already in UTC. But let’s be sure:

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;

Extract the date portion.

LocalDate localDate = odtUtc.toLocalDate() ;

To generate text in standard ISO 8601 format, call toString.

String output = localDate.toString() ;