I am using TrueTime library which returns Date at the system time zone. I am having problems converting this Date to UTC Date when converted to milliseconds.
Here is what I did:
// getting true time in GMT [ex : 2020-07-13T18:00:57.192+03:00 [Europe/Istanbul]]
Date now = getTrueNowTimeInGMT();
// I like to use `LocalDateTime`, so I am converting `Date` to `LocalDateTime`:
LocalDateTime ldtOfSystem = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
// Converting system default zone to UTC
ZonedDateTime zdtOfSystem = ldtOfSystem.atZone(ZoneId.systemDefault());
ZonedDateTime zdtOfSystemInUTC = zdtOfSystem.withZoneSameInstant(ZoneId.of("UTC"));
// Making sure that it is in the UTC. It is returning correct UTC time [ex: 2020-07-13T15:00:57.192 [UTC]]
System.out.println(zdtOfSystemInUTC);
// converting zdtOfSystemInUTC to milliseconds - problem is occurring here!
zdtOfSystemInUTC.toInstant().toEpochMilli();
I am losing zone data and it is returning milliseconds based on the local zone (system zone). I am converting these milliseconds to Date again and the result is in GMT+3 [2020-07-13T18:00:57.192+03:00]
Am I missing something? I read in one post that toInstant() method doesn't care about the timezone. How can I get the milliseconds from the specific time zone I pointed out in ZonedDateTime?
EDIT I changed variable names (hopefully, into better ones) thanks to @MenuHochSchild for pointing that out.
Clarification. Why do I have the need for the UTC time?
I cannot control the user's time. He/she can change date and time of his/her device easily and that is creating problems for us. So in order to tackle the problem, we found a library called TrueTime which gives true-time Date object like this:
Tue Jul 14 00:32:46 GMT+03:00 2020
In order to sync with our server and do some time-related operations, I need to convert this Date which is GMT to UTC and convert it to milliseconds.
The Answer by Ole V.V. is correct. I will add a few thoughts and a chart.
java.util.DateYour code:
Date now = getTrueNowTimeInGMT();
See if your library has been updated for java.time. The java.util.Date class was supplanted years ago, with the adoption of JSR 310. The java.time.Instant class should be used instead.
Instant represents a moment in UTCUpon receiving a Date object, immediately convert from the legacy class to the modern class. Use the new conversion methods added to the old classes.
Instant instant = myJavaUtilDate.toInstant() ;
You said:
Am I missing something? I read in one post that toInstant() method doesn't care about the timezone.
The java.time.Instant does not care about time zone in that it always represents a moment in time as seen in UTC, by definition.
Instant.now will always be seen in the perspective of UTC.Instant::plus and Instant::minus will always be in UTC, and involve the generic 24-hour days of UTC time that does not encounter the anomalies of political time such as Daylight Saving Time (DST).Both of these classes, legacy & modern, represent a moment in UTC. Both internally keep a count of time since the first moment of 1970 in UTC, 1970-01-01T00:00Z. Instant uses a finer resolution of nanoseconds in its count, versus milliseconds in Date.
Apparently you want a count of milliseconds since 1970-01-01T00:00Z.
long millisSinceEpoch = instant.toEpochMilli() ;
And back again.
Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;
I do not recommend tracking time as a count. Such a count is inherently ambiguous to the human reader, and subject to error or misinterpretation. I strongly suggest instead using standard ISO 8601 strings to communicate a date-time value.
String output = instant.toString() ;
And back again.
Instant instant = Instant.parse( input ) ;

ZonedDateTimeYou said:
How can I get the milliseconds from the specific time zone I pointed out in ZonedDateTime?
A ZonedDateTime object represents a moment as seen through the wall-clock time used by people of a particular region. Imagine two people talking on a long-distance phone call, one on the west coast of US, and one in Tunis Tunisia.
Capture the moment when their call started.
Instant callStartedUtc = Instant.now() ;
When the person in US glanced at a clock on their wall as they dialed their phone, what time did they see?
ZonedDateTime zdtLosAngeles = callStartedUtc.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
When the person in Tunisia glanced at a clock hanging on their wall as they picked up their phone to answer, what time did they see?
ZonedDateTime zdtTunis = callStartedUtc.atZone( ZoneId.of( "Africa/Tunis" ) ) ;
Three objects all representing the very same simultaneous moment. You can extract a Instant object from both ZonedDateTime objects.
Instant instant = zdtLosAngeles.toInstant() ;
These will all be equal. In this example code, eq will be true.
boolean eq =
callStartedUtc.equals( zdtLosAngeles.toInstant() )
&&
callStartedUtc.equals( zdtTunis.toInstant() )
;
All three internally have the very same count from epoch reference.
Tip: Learn to think in terms of UTC while on the job programming or doing sysadmin work. Think of UTC as the One True Time, with time zones being mere variations.
Do not translate back-and-forth in your head, just stick with UTC. Like learning a foreign language, constant translation in your head will drive you batty.
Exchanging date-time values between programs or systems, logging, debugging, and such should all be done in UTC. I suggest keeping a 2nd clock on your desk set to UTC.
LocalDateTime is not a momentYou said:
// I like to use
LocalDateTime, so I am convertingDatetoLocalDateTime:
LocalDateTime ldtOfSystem = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
You should not "like" LocalDateTime. That class cannot represent a moment. It holds a date and a time-of-day, but lacks the context of a time zone or offse-from-UTC. So it may say "noon on the 23rd of January 2021" but we have no idea if that means noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — all very different moments, several hours apart.
Whenever you are tracking a moment, a specific point on the timeline, you cannot use LocalDateTime. Instead use Instant (for UTC), OffsetDateTime (for an offset-from-UTC, a number hours-minutes-seconds), or ZonedDateTime (for a time zone, in Continent/Region name, such as Europe/Paris).
When in doubt, do not use LocalDateTime. I find most of the time in business apps, we are tracking a specific moment. The big exception is when booking future events, such as appointments, where LocalDateTime is needed.
Search to learn more as this has been covered many many times already on Stack Overflow. For example, What's the difference between Instant and LocalDateTime?.
You said:
Clarification. Why do I have the need for the UTC time?
I assume you really meant to say, "Why do I have the need to obtain the current moment from a trusted remote time server?". If so, I ask that you edit your Question for clarity.
This need is legitimate. If the local clock cannot be trusted, and you must have a value close to the current moment, you should indeed be reaching out to a trusted time server if one is available.
The term UTC is not really relevant here. A time server is most likely to return a value in terms of UTC. But being in UTC has nothing to do with the source of time being local or remote.
You said:
I need to convert this Date which is GMT to UTC
No, you do not, almost certainly.
The exact definitions of GMT and various kinds of UTC is long, complicated, academic, and moot for nearly all programmers.
In terms of regular business apps such as accounting and work flow, you can consider GMT and UTC to be synonyms. The difference is literally less than a second. And the default clock used by Java does indeed ignore that difference.
Unless you work with rocket telemetry, GPS/Galileo satellites, or atomic clocks, you really should not care about GMT vs UTC.
Furthermore, in your case of using a remote time server, GMT versus UTC is even less applicable, as the retrieved value loses significant time in its traversal over the network(s).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With