简体   繁体   中英

Java Date constructor unexpected behaviour

I am just providing a value of 2160000000 (which is 1000 * 60 * 60 * 24 * 25 - just 25 days) to Date's class constructor. I expected to see that here will be 1970-01-26 00:00:00, but what I received is 1970-01-26 03:00:00 (additional three hours)! I haven't found any points that this constructor also depend on JVM locale settings, and all I have found is info about leap second. But leap second is NOT three hours in bounds of the single month of the same year. But anyway I've changed default locale (to US one. I'm located in Europe) in a test method just for experiment, but nothing changed.

I have received this just by this (what I have explained just ok earlier ya know): Date date = new Date(1000* 60 * 60 * 24 * 25); (this is just for example purposes). I saw actual values just using debugger, that's all:

在此处输入图片说明

You are getting the Date you expected, a Date of 1970-01-26 00:00:00 UTC . This point in time is equivalent to 1970-01-26 03:00:00 at UTC offset +03:00.

In your debugger you are looking into the private fields of the Date object. These are not documented for clients (that's the point), so don't expect any particular values.

I believe that you would find Instant.ofEpochMilli(1000L * 60 * 60 * 24 * 25) less confusing. Or still better, Instant.EPOCH.plus(Duration.ofDays(25)) . java.time, the modern Java date and time API, is much nicer to work with. If you do need a Date for a legacy API that you don't want to change just now, I recommend getting an Instant first and then using Date.from(yourInstant) so you minimize your use of (and dependence on) the outdated and confusing Date class.

Finally, changing locale makes no difference. While time zone and UTC offset are closely connected (to a degree where some think it's the same :-) locale hasn't really got anything to do with them. Instead the locale deals with the language and cultural norms of a group of users — it doesn't even need to be tied to a geographical location.

Link: All about java.util.Date

Do you think the hour difference you're seeing is being equal to your home country's time zone (GMT+3) is a coincidence? I think not.

SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = dateFormat.parse("/*TimeToParse*/");

This would definitely help.

Edit: If you check the zoneOffset and ZoneInfo values in your debug screenshot, you'll understand better.

tl;dr

Instant.ofEpochMilli( 2_160_000_000L )

java.time

The Answer by Acar is likely correct: You are confused by the unfortunate design of Date::toString to dynamically apply your JVM's current default time zone while generating a string. One of many reasons to never use the troublesome Date class, now supplanted by the java.time classes.

To represent a moment on the timeline in UTC with a resolution of nanoseconds, use Instant .

Instant instant = Instant.ofEpochMilli( 2_160_000_000L ) ;

If your real intent is to represent 25 whole days as a span of time unattached to the timeline, use a Period .

LocalDate today = LocalDate.now( ZoneId.of( “Africa/Tunis” ) ) ;

Period p = Period.ofDays( 25 ) ;
LocalDate later = today.plus( p ) ;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM