As discussed vividly in the comments, the recommendation is to use the java.time
package. The easy solution:
Instant fourHoursAgo = Instant.now().minus(Duration.ofHours(4));
System.out.println(fourHoursAgo);
This just printed
2018-01-31T14:57:44.667255Z
Since UTC time is now 18:58
, the output is what you asked for. The Instant
itself is offset neutral. Its toString
delivers time in UTC, but there was no mention of UTC in producing the Instant
, so whether it gives you what you want, I am not sure. I will give you a result that is explicitly in UTC later.
But first, if you do need a java.util.Date
, typically for a legacy API that you cannot change, the conversion is easy:
Date oldfashionedDate = Date.from(fourHoursAgo);
System.out.println(oldfashionedDate);
On my computer in Europe/Copenhagen
time zone this printed:
Wed Jan 31 15:57:44 CET 2018
Again, this agrees with the time four hours before running the snippet. And again, a Date
doesn’t have a UTC offset in it. Only its toString
method grabs my JVM’s time zone setting and uses it for generating the string, this does not affect the Date
. See the Stack Overflow question, How to set time zone of a java.util.Date?, and its answers.
As promised, if you do need to represent not only the time but also the offset, use an OffsetDateTime
:
OffsetDateTime fourHoursAgoInUtc = OffsetDateTime.now(ZoneOffset.UTC).minusHours(4);
System.out.println(fourHoursAgoInUtc);
This printed
2018-01-31T14:57:44.724147Z
Z
at the end means offset zero from UTC or “Zulu time zone” (which isn’t a true time zone). The conversion to a Date
is not much more complicated than before, but again, you will lose the offset information in the conversion:
Date oldfashionedDate = Date.from(fourHoursAgoInUtc.toInstant());
System.out.println(oldfashionedDate);
This printed:
Wed Jan 31 15:57:44 CET 2018
Link: Oracle tutorial explaining how to use java.time