Why is Java 8 Instant.now() showing the wrong UTC on my local server?

amallard picture amallard · Dec 1, 2018 · Viewed 9.2k times · Source

Java8 Instant.now() gives the current time already formatted in UTC. I created a simple sandbox test on CompileJava.net to verify my intented results:

Timestamp createdDateUtc = Timestamp.from(Instant.now());
System.out.println(createdDateUtc);

LocalDateTime databaseUtcLocal = createdDateUtc.toLocalDateTime();
ZonedDateTime databaseUtcZoned = databaseUtcLocal.atZone(ZoneId.of("UTC"));
ZonedDateTime userTimezoneTime = databaseUtcZoned.withZoneSameInstant(ZoneId.of("Asia/Qatar")); 
System.out.println(userTimezoneTime.format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a")));

Note: it is currently 11:16 AM UTC on 12/01/2018.

When I run this code on the online compiler, I get the output:

2018-12-01 11:17:43.637
12/01/2018 02:17:43 PM

But when I run this code on my local JBOSS server, I get this output instead:

2018-12-01 03:18:07.464
12/01/2018 06:18:07 AM

What could be going wrong here? Is my server UTC clock incorrect? My local server's physical location is in California. While that shouldn't matter, it does seem odd that when I'm trying to display the UTC time using Instant.now() I get Pacific Time instead.

Any help much appreciated!

UPDATE

As pointed out by the accepted answer, the issue was my Timestamp.from() method:

System.out.println(Instant.now());
System.out.println(Timestamp.from(Instant.now()));

Output:

2018-12-01T11:48:33.153Z
2018-12-01 03:48:33.171

So now my issue has changed. If you have a similar issue, I found my answer on this Stack Overflow here. Instead of Timestamp.from(Instant.now()) I used this ugly mess:

Timestamp.valueOf(ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime())

Answer

vlad324 picture vlad324 · Dec 1, 2018

I think there is a problem in Timestamp.toString() method. If you will look inside it you will see:

public String toString () {

    int year = super.getYear() + 1900;
    int month = super.getMonth() + 1;
    int day = super.getDate();
    int hour = super.getHours();
    int minute = super.getMinutes();
    int second = super.getSeconds();
    // other code
}

Methods getHours(), getMinutes() and other are from Date class and based on documentation they interpret it by local timezone Date.getHours().