Reputation: 19084
I seem to be getting different representations of Java's time stamp as follows:
en_US
2017-06-10 14:34:35.088
2017-06-10T18:34:35.102Z
with following invocations:
System.out.println(Locale.getDefault());
System.out.println(new Timestamp(System.currentTimeMillis()));
System.out.println(Instant.now());
What additional configurations will help to equalize the the 4 hr offset between time representations shown above? Thanks.
Upvotes: 1
Views: 12415
Reputation: 14415
One is your local time and one is UTC. This depends more on the way it is printed than on the actual (internal) value.
To have both shown equal, you can
-Duser.timezone=UTC
to your VM. Format the Instant
to your local time zone:
DateTimeFormatter formatter =
DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
System.out.println(formatter.format(Instant.now()));
Convert the Timestamp
to an Instant
:
new Timestamp(System.currentTimeMillis()).toInstant();
Full code:
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Instant instant = Instant.now();
System.out.println("Timestamp: " + timestamp);
System.out.println("Instant: " + instant);
System.out.println("Instant to local: " + formatter.format(instant));
System.out.println("Timestamp to UTC: " + timestamp.toInstant());
}
Will print out (in my local time zone):
Timestamp: 2017-06-10 21:17:13.935
Instant: 2017-06-10T19:17:13.935Z
Instant to local: 2017-06-10T21:17:13.935
Timestamp to UTC: 2017-06-10T19:17:13.935Z
So there is "some global setting", although it might not do what you want. An Instant
will always be printed in UTC by default.
If you want to work with local dates only and you are not restricted to Instant
, there are two* more options:
Convert the Instant
to ZonedDateTime
:
ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
Or skip the Instant
altogether in favor of ZonedDateTime.now()
*Depending on your needs you can exchange ZonedDateTime
with OffsetDateTime
or LocalDateTime
.
Edit: The magical way.
public static void main(String[] args) throws Exception {
Field field = DateTimeFormatter.class.getField("ISO_INSTANT");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault()));
System.out.println(new Timestamp(System.currentTimeMillis()));
System.out.println(Instant.now());
}
Use reflection to change DateTimeFormatter.ISO_INSTANT
to a formatter that uses your local time. Might not work with a SecurityManager
and might have one or another unwanted side effect. See e.g. Change private static final field using Java reflection for details.
Upvotes: 2