How to create a Date object, using UTC, at a speci

2020-04-11 09:33发布

问题:

Is it possible to create a java.util.Date object that is guaranteed to be UTC and at a specific time in the past, like an hour ago or a day ago, and is this a good idea?

I have reviewed the Stack Overflow question get date as of 4 hours ago and its answers. But I want to avoid having to add more dependencies, like jodaTime, and the accepted answer uses System.currentTimeMillis() which would be the local timezone, would it not?

回答1:

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



回答2:

You can achieve this using the java.time package, as follows:

LocalDateTime localDateTime = LocalDateTime.now(ZoneOffset.UTC).minusHours(4);
Date date = Date.from(localDateTime.atZone(ZoneOffset.UTC).toInstant());

Gives the following output:

2018-01-31T14:58:28.908
Wed Jan 31 20:28:28 IST 2018     //20:28:28 IST is 14:58:28 UTC

Which is correctly 4+5:30 hours behind my current time - Asia/Kolkata ZoneId.



标签: java date utc