How to get date in a specific timezone? - java

greetings all
i am using the following method to get the current time in GMT timezone
public static Timestamp getCurrentTimeGMT() {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
long time = c.getTimeInMillis();
long offset = TimeZone.getDefault().getOffset(time);
return new Timestamp(time - offset);
}
but when i try to use the same method with minor changes to get the current time in GMT+3
it gives me the same result of GMT ? i don't know why:
public static Timestamp getCurrentTimeGMT3() {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT+3"));
long time = c.getTimeInMillis();
long offset = TimeZone.getDefault().getOffset(time);
return new Timestamp(time - offset);
}
any ideas why the above code doesn't work properly, and how to do such a method ?

Timestamp extends Date - it doesn't have a time zone, conceptually. It just represents an instant in time.
If you want to display it in a particular calendar with a particular time zone, that's a formatting issue. Create the appropriate calendar with the relevant time zone, and set the timestamp within it accordingly.
(As per normal, I'd like to recommend that you use Joda Time instead of the built-in API where possible. It's much cleaner.)

Why do you subtract the offset from the time in the last line? That is basically resetting your time back to GMT. You retrieve GMT+3 then you subtract 3 hours from that.

What Jon said. A Timestamp does not have a time zone, it's always UTC, and really shouldn't be abused for representing local time. If you really need objects to represent local time, Joda Time has a class for that.
And you should be aware that "GMT+3" is not a real valid time zone. A time zone has not just a base offset, but also a daylight savings time offset, which can be different for time zones with the same base offset, and can even change for the same time zone due to legislation. A real time zone ID is "Europe/Berlin" or "Australia/Darwin".

java.time
In March 2014, the modern Date-Time API supplanted the legacy date-time API and since then it is strongly recommended to switch to java.time, the modern date-time API.
Solution using java.time, the modern Date-Time API: The first important thing to understand is the difference between a timezone and a timezone offset.
A timezone is identified by an ID, typically in the form of a Region/City e.g. Europe/London. Here you can check a list of tz database time zones. The java.time API provides with ZonedDateTime to represent a date-time with timezone.
A timezone offset tells us the amount of time by which the time of a place is offset from the UTC e.g. 2011-12-03T10:15:30+01:00 which tells us that this date-time is offset by 01:00 hours from UTC i.e. we need to subtract 01:00 hours to get the equivalent date-time at UTC. The java.time API provides with OffsetDateTime to represent a date-time with time zone offset.
Some time zones observe DST i.e. America/New_York observes an offset of -05:00 hours in the winter while -04:00 hours in the summer.Here you can check an illustration.
A ZonedDateTime automatically reflects the applicable offset while we create an OffsetDateTime with a fixed offset value. Thus, GMT and GMT+3 mentioned in your question are not time zones, they represent time zone offset. A better and more modern way to write it is Z and +03:00 respectively.
Demo:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
class Main {
public static void main(String[] args) {
ZoneId zone = ZoneId.of("America/New_York");
// Current date-time in America/New_York
System.out.println(ZonedDateTime.now(zone));
// A sample winter date-time in America/New_York
System.out.println(ZonedDateTime.of(LocalDate.of(2023, 01, 14), LocalTime.of(10, 20, 30), zone));
// A sample summer date-time in America/New_York
System.out.println(ZonedDateTime.of(LocalDate.of(2023, 06, 14), LocalTime.of(10, 20, 30), zone));
// Current OffsetDateTime with an offset of 00:00 hours (UTC time)
System.out.println(OffsetDateTime.now(ZoneOffset.UTC));
// Current OffsetDateTime with an offset of 05:30 hours
OffsetDateTime odt = OffsetDateTime.now(ZoneOffset.of("+05:30"));
System.out.println(odt);
// The same OffsetDateTime converted to UTC time (will be 05:30 less)
System.out.println(odt.withOffsetSameInstant(ZoneOffset.UTC));
}
}
Output from a sample run:
2023-01-14T12:40:04.348474-05:00[America/New_York]
2023-01-14T10:20:30-05:00[America/New_York]
2023-06-14T10:20:30-04:00[America/New_York]
2023-01-14T17:40:04.352982Z
2023-01-14T23:10:04.353969+05:30
2023-01-14T17:40:04.353969Z
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.

Sample Code to get Time in Different Time Zone
public class GetZoneDateTime {
public static void main(String[] args) throws Exception {
String reqTzId = "Asia/Singapore";
LocalDateTime now = LocalDateTime.now();
System.out.println("Local Now: " + now + " TimeZone: " + TimeZone.getDefault());
ZoneId zoneId = ZoneId.of(reqTzId);
System.out.println("Req TimeZone : " + zoneId);
LocalDateTime localNow = LocalDateTime.now(zoneId);
System.out.println("tzLocalDateTime: " + localNow);
ZonedDateTime zoneNow = ZonedDateTime.now(zoneId);
System.out.println("tzZonedDateTime: " + zoneNow);
}
}

c.getTimeInMillis() returns the number of milliseconds since January 1st, 1970 0:00 UTC and will return the same value, no matter which time zone is used in the Calendar instance.
If you create a Calendar with a time zone and need access to the time fields, you should access these directly:
int h = c.get(Calendar.HOUR_OF_DAY);
int m = c.get(Calendar.MINUTE);
int s = c.get(Calendar.SECOND);

Use the Timezone static method.
TimeZone default = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("GMT+3"));
Calendar cal = Calendar.getInstance();
cal.setTime(new Date(System.currentTimeMillis()));
Date date = cal.getTime(); // converted date time
System.out.println(date.toString());
// Set Back to System Default
TimeZone.setDefault(default);

Related

Java - convert timestamp to Date and back to timestamp changes the date

I'm creating a string out from current time and I wanted to convert it to timestamp again, but the thing is, that it's subtracts 2 hours while converting.
This is the steps I'm doing -
DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder().append(DateTimeFormatter.ofPattern("uuuu-MM-dd")).appendLiteral(" ")
.append(DateTimeFormatter.ofPattern("HH:mm:ss")).parseLenient();
long ts = Clock.systemUTC().millis();
System.out.println(ts);
Instant instant = Instant.ofEpochMilli(ts);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
String str = zonedDateTime.format(dateTimeFormatterBuilder.toFormatter());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
long timestamp = simpleDateFormat.parse(str).getTime();
System.out.println(timestamp);
} catch (ParseException e) {
e.printStackTrace();
}
output -
1639065502667
1639058302000
(2021-12-09 15:58:22
2021-12-09 13:58:22)
why is the diff of the 2 hours?
how can I parse it so that the outputs will be equal?
tl;dr
Trying to understand Date, Calendar, and SimpleDateFormat is a huge waste of time. Use only their replacements, the java.time classes.
LocalDateTime // Represent a date with time-of-day, but lacking the context of a time zone or offset-from-UTC. So *not* a moment, *not* a point on the timeline.
.parse( // Parse your text string input into a date-time object.
"2021-12-09 15:58:22" // Your input of date with time-of-day but no offset/zone.
.replace( " " , "T" ) // Replace SPACE with a `T` to comply with standard ISO 8601 format.
) // Returns a `LocalDateTime` object.
.atZone( // Place that date-with-time into the context a particular time zone.
ZoneId.of( "America/Montreal" ) // Specify a time zone by its `Continent/Region` name.
) // Returns a `ZonedDateTime` object, a date with time-of-day as seen through the wall-clock time used by the people of a particular region. This *does* represent a moment, *is* a specific point on the timeline.
.toInstant() // Adjust from time zone to UTC (an offset of zero hours-minutes-seconds). This represents the very same moment as the `ZonedDateTime` object above, but as seen through a different wall-clock time.
.toEpochMilli() // Get a count of milliseconds from first moment of 1970 in UTC (1970-01-01T00:00Z) to the moment of our `Instant` object (& `ZonedDateTime` object).
See this code run live at IdeOne.com. There you can click fork to make a copy, alter, and run.
1639083502000
Avoid legacy date-time classes
Regarding your specific question about a two hour difference, the obvious cause would be a time zone difference.
Parsing incomplete information
Your parsing, SimpleDateFormat("yyyy-MM-dd HH:mm:ss") is something of a wild card. The result will be a java.util.Date object, which represents a moment, a date with time-of-day as seen with an offset of zero. But your input lacks an indicator of offset or zone. As commented by Sotirios Delimanolis, you are parsing with partial input, with incomplete information.
So some default zone/offset will be applied. I do not know what zone or offset in particular, because I do not care. That terrible class is tragically flawed, and should be avoided.
Also, yet another problem with the Date class is that its toString method has the anti-feature of applying the JVM’s current default time zone to adjust away from the UTC value represented by that class. Very confusing, as this creates the illusion of that zone being a part of Date object but it is not. As I said, a terrible class, tragically flawed.
Use only java.time classes instead.
java.time
Understand that a date with time-of-day is inherently ambiguous, is not a moment.
If you are tracking 4 PM on the 9th, we do not know if that means 4 PM in Tokyo Japan, 4 PM in Toulouse France, or 4 PM in Toledo Ohio US — three very different moments that happen several hours apart.
LocalDateTime ldt = LocalDateTime.parse( "2021-12-09 16:00:00" ) ;
To track a moment, a point on the timeline, you must place ne date-with-time in the context of an offset from UTC or of a time zone.
An offset is merely a number of hours-minutes-seconds ahead or behind the baseline of modern timekeeping, the prime meridian at Royal Observatory, Greenwich.
A time zone is much more. A time zone is a named history of the past, present, and future changes to the offset used by the people of a particular region. Each zone has a name in format of Continent/Region such as Europe/Berlin or Asia/Tokyo.
To track moments as seen in UTC, with an offset of zero, use Instant.
Instant instant = Instant.now() ;
To see that same moment through the wall-clock time used by people in a region, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
As for your use of SimpleDateFormat, Date, and Calendar, don’t. Avoid these legacy date-time classes. Hey were designed by people who did not understand date-time handling. They were supplanted years ago by the modern java.time classes defined in JSR 310. Sun, Oracle, and the JCP community all gave up on those classes. I suggest you do the same.
In your code:
long ts = Clock.systemUTC().millis();
Instant instant = Instant.ofEpochMilli(ts);
That is the same as doing this:
Instant.now().truncatedTo( ChronoUnit.MILLISECONDS )
In your code:
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
(A) When working with mere offsets rather than time zones, use OffsetDateTime class. The ZonedDateTime class is for working with time zones.
(B) A briefer way to adjust from Instant to a zoned moment was shown above:
myInstant.atZone( z )
The answer was only setting the timezone to UTC -
DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder().append(DateTimeFormatter.ofPattern("uuuu-MM-dd")).appendLiteral(" ")
.append(DateTimeFormatter.ofPattern("HH:mm:ss")).parseLenient();
long ts = Clock.systemUTC().millis();
System.out.println(ts);
Instant instant = Instant.ofEpochMilli(ts);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
String str = zonedDateTime.format(dateTimeFormatterBuilder.toFormatter());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
*******
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
*******
long timestamp = simpleDateFormat.parse(str).getTime();
System.out.println(timestamp);
} catch (ParseException e) {
e.printStackTrace();
}
The dateTimeFomatter builder uses format without milliseconds and without timezone.
That's why the str value contain no information about them.
Then simpleDateFormat.parse(str) uses timezone of JVM which is UTC+02:00 in this case.
Trace what is going on:
Instant instant = Instant.now();
// => 2021-12-09 15:58:22.798 +00:00
String str = zonedDateTime.format(dateTimeFormatterBuilder.toFormatter());
// => "2021-12-09 15:58:22"
simpleDateFormat.parse(str);
// => 2021-12-09 15:58:22.000 +02:00
You just need to fix the pattern (add millis .SSS and timezone XXX parts) to make the results consistent as expected:
DateTimeFormatter.ofPattern("HH:mm:ss.SSSXXX")
// and something similar for SimpleDateFormat if needed
Parsing Instant from a custom formatted string.
This example shows how to parse Instant from serialized time assuming that there is a fixed timezone for all cases.
var serializedDateTime = "2020-01-01 10:20:30";
var zoneId = ZoneOffset.UTC; // may be any other zone
var format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
var instant = LocalDateTime
.parse(serializedDateTime, format)
// LocalDateTime is unzoned, just representation of (date + time) numbers in a single object
.atZone(zoneId)
// apply a zone to get ZonedDateTime (point in space-time on Earth)
.toInstant();
// convert to Instant (the same point adjusted to UTC+00:00)
Let me guess, your timezone is UTC+2?
simpleDateFormat.parse(str) assume that your date in current system timezone, but it is in UTC.

How to convert UTC Time to LocalDateTime by using ZonedDateTime

I have found many way to convert localDateTime to LocalDateTime in UTC.
But I could not find any way to convert UTC time at localDateTime by using ZonedDateTime. Do you know a way to convert it ?
This is what I used to convert it to UTC. I need a vice versa method .
ZonedDateTime zonedDate = ZonedDateTime.of(localDateTime,
ZoneId.systemDefault());
localDateTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC)
Don’t use LocalDateTime for a date and time for which you know the UTC offset or time zone. For a date and time in your time zone or another known time zone, use ZonedDateTime. For a date and time for which you know an offset (and here UTC counts as an offset) use OFfsetDateTime.
Why? LocalDateTime (confusing class name) is a date and time without time zone or offset. Not storing the known offset or time zone is throwing away vital data and is an error waiting to happen.
One exception: For a date and time in a known time zone in a further future, do store a LocalDateTime and make sure to store the time zone as a separate ZoneId object. This will allow the offset and/or summer time rules (DST rules) for the time zone to be changed between now and that time (which happens more often than we like to think). Only when time draws near and our Java installation may have been updated with the latest zone rules, can we correctly combine the date-time and the zone and obtain the correct moment in time.
Convert UTC date and time to your time zone
OffsetDateTime utcDateTime = OffsetDateTime.of(2019, 9, 10, 12, 0, 0, 0, ZoneOffset.UTC);
System.out.println("UTC date and time: " + utcDateTime);
ZonedDateTime myDateTime = utcDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("Date and time in the default time zone: " + myDateTime);
After I set my time zone to Asia/Istanbul, this snippet output:
UTC date and time: 2019-09-10T12:00Z
Date and time in the default time zone: 2019-09-10T15:00+03:00[Asia/Istanbul]
Convert from your time zone to UTC
For the opposite conversion I prefer:
OffsetDateTime convertedBackToUtc = myDateTime.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("UTC date and time again: " + convertedBackToUtc);
UTC date and time again: 2019-09-10T12:00Z
Still not using any LocalDateTime.

Date from ZonedDateTime instant not in utc

I am creating date like this:
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
Date.from(now.toInstant());
I need Date object have current time in utc, but when I print date it gives me my local time and not utc time.
I also tried with:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
Date date = Date.from(now.toInstant());
But when I print Date again time is not in utc. Am I doing something wrong when creating Date object. Why above 2 approaches not give me Date that have current time in utc.
Two points:
Avoid the long outdated Date class, in particular when you are already using classes from java.time, the modern Java date and time API.
A Date object hasn’t got and cannot have a time zone in it.
To print offset or time zone
If you need your offset, you need to hold on to your OffsetDateTime (or ZonedDateTime) object:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(now);
On my computer this just printed
2017-11-21T11:53:11.519Z
The Z in the end indicates Zulu time zone, another name for UTC (you may also informally think of it as Zero offset from UTC).
If you would like a more human-readable format, you are right, use a formatter:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(now.format(formatter));
Depending on your locale and the time, this prints something like
Tuesday, November 21, 2017 11:53:11 AM Z
Again the Z means Zulu time zone, UTC.
Date is not going to help you
A Date is just a point in time. So is the Instant that you use for initializing the date. None of them has got a time zone or offset. The difference here is their toString methods: The Instant is always printed in UTC, the Date usually (always?) in the JVM’s default time zone. The latter confuses many into thinking the Date has a time zone when it hasn’t. See All about java.util.Date.
As I have demonstrated, a formatter may put a time zone or offset into a string when formatting the date-time. This does not in any way modify the date-time object, whether OffsetDateTime, ZonedDateTime, Instant or Date. The long outdated DateFormat class may do the same when formatting a Date. It cannot and will not set a time zone in the Date object since (and I repeat) a Date object cannot have a time zone in it.
Long story short, you have no need for the outdated Date class that I can see.

Android date with added milliseconds not at the correct time

What I am trying to do is store a date, represented by a long of milliseconds, that is the next midnight from the current time. So, posting this at 10:11 PM, I would want a date representing 12:00 AM tomorrow morning. For this task, I wrote this line of code (knowing that there are 86400000 milliseconds in one day):
long time = System.currentTimeMillis() + (86400000 - (System.currentTimeMillis() % 86400000));
The line is designed to calculate the extra milliseconds from the last midnight, substract that from one whole day to find the time until the next midnight, then add that to the current time so that the new value is the value of the next midnight. For whatever reason though, the date object I am using to debug spits out "Wed Apr 20 20:00:00 EDT 2016" when calling the #toString() method. The current time is said to be "Tue Apr 19 22:08:34 EDT 2016" at the same time as the other date is being calculated.
This means that the long of milliseconds is actually representing 8:00 PM the next day, while I want it to represent 12:00 AM. Can anyone help me spot the flaw in my logic?
I most likely am missing something obvious, so bear with me.
NOTE: I also tried calculating the time like this:
long time = System.currentTimeMillis() - (System.currentTimeMillis() % 86400000) + 86400000;
But this resulted in the same Date object.
You are forgetting to adjust for your timezone. Here is a simple way to achieve this.
TimeZone tz = TimeZone.getDefault();
long time = System.currentTimeMillis() + (86400000 - (System.currentTimeMillis() % 86400000));
time -= tz.getOffset(time);
System.out.println(new Date(time));
java.time
You are using flawed troublesome date-time classes that have long been supplanted, first by the Joda-Time library and now it's successor, the java.time framework built into Java 8 and later. Much of java.time has been back-ported to Java 6 & 7 and then adapted to Android by the ThreeTenABP project.
An Instant is a moment on the timeline in UTC, with a resolution in nanoseconds.
Instant instant = Instant.now();
Apply a time zone to get a ZonedDateTime. Time zone is crucial to determining a date. It may already be “tomorrow” to the east of you or “yesterday” to the west.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( zoneId );
To get the first moment of the day, do not assume that time is 00:00:00.0. Anomalies such as Daylight Saving Time may result in a different time. Let java.time determine that time-of-day. To do that we must go through the LocalDate class.
LocalDate today = zdt.toLocalDate();
Days are not always 24 hours long, which is an incorrect assumption in you question and code. Again, let java.time determine the following day with a call to plusDays.
LocalDate tomorrow = LocalDate.plusDays( 1 );
ZonedDateTime zdtTomorrowStart = tomorrow.atStartOfDay( zoneId );
I suggest you avoid tracking date-time values as a count from epoch. That is prone to error, and is terribly difficult to debug. And you will be losing data as you go from nanosecond resolution to milliseconds. But if you insist.
long millis = zdtTomorrowStart.toInstant().toEpochMilli();
Direct time calculation can be tricky, there are quite a few corner cases. I think the simplest solution to avoid it is :
// now, with current timezone and locale
Calendar calendar = new GregorianCalendar();
// tomorrow
calendar.add(Calendar.DAY_OF_MONTH, 1);
// midnight
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// get the resulting date
Date date = calendar.getTime();

JSR 310 :: System.currentTimeMillis() vs Instant.toEpochMilli() :: TimeZone

Could you please shed some light on how to obtain correct epoch time in milliseconds for a default system timezone and given timezone.
Given
1. TimeZone: GMT+3
2. The following code snippet:
import java.time.*;
public class Main {
public static void main(String[] args) {
System.out.println(LocalDateTime
.now()
.atZone(ZoneOffset.UTC)
.toInstant()
.toEpochMilli()
);
System.out.println(LocalDateTime
.now()
.atZone(ZoneOffset.of("+3"))
.toInstant()
.toEpochMilli()
);
System.out.println(System.currentTimeMillis());
}
}
3. Output:
1444158955508
1444148155508
1444148155508
4. JavaDoc for System.currentTimeMillis() that tells that returned value will be the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
So, why
the output of the LocalDateTime at GMT+3 is the same as of System.currentTimeMillis(), although the docs for the System.currentTimeMillis() mention UTC?
the output of the LocalDateTime at UTC differs from System.currentTimeMillis(), although the docs for the System.currentTimeMillis() mention UTC?
Both System.currentTimeMillis() and Instant.toEpochMilli() return the number of milliseconds since the Unix epoch. That isn't "in" any particular time zone, although the Unix epoch is normally expressed as "midnight on January 1st 1970, UTC". But an instant is just an instant in time, and is the same whichever time zone you're in - but it will reflect a different local time.
The output of LocalDateTime.atZone(UTC) differs because you're saying "Take the local date and time, and convert it to an instant as if it were in the UTC time zone" - even though when you created that LocalDateTime you did so implicitly in the UTC+3 time zone... that's why it's "wrong".
LocalDateTime.now() takes the local date and time in the system default time zone. So if your time zone is UTC+3, the current instant in time is 2015-10-06T16:57:00Z, then LocalDateTime.now() will return .2015-10-06T19:57:00. Let's call that localNow...
So localNow.atZone(ZoneOffset.of("+3")) will return a ZonedDateTime representing 2015-10-06T19:57:00+03 - in other words, the same local date/time, but "knowing" that it's 3 hours ahead of UTC... so toInstant() will return an Instant representing 2015-10-06T16:57:00Z. Great - we still have the current date/time.
But localNow.atZone(ZoneOffset.UTC) will return a ZonedDateTime representing 2015-10-06T19:57:00Z - in other words, the same local date/time, but "thinking" that it's already in UTC... so toInstant() will return an Instant representing 2015-10-06T19:57:00Z.. which isn't the current time at all (it's in three hours).
Short version:
There is no way to compute LocalDateTime -> Instant, you need to specify a timezone.
With a timezone you get a ZonedDateTime and can compute ZonedDateTime -> Instant
Instant == System.currentTimeMillis() if the timezone of the ZonedDateTime equals the system default time zone.
Long version:
LocalDateTime is the time on your clock(plus date information). Which is not enough if you don't tell us which timezone your are in. 13:00 o'clock in Tokyo is not the same Instant as 13:00 o'clock in Paris.
Once you add a timezone to your LocalDateTime you get a ZonedDateTime and we can know in which Instant of time you actually are. E.g. are you 13:00 o'clock in Tokyo or in Paris?
To get the correct Instant the timezone of the ZonedDateTime needs to be correct. If it is 13:00 o'clock in Tokyo but you claim that you are 13:00 o'clock in Paris you will get a wrong Instant.
LocalDateTime:
It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
ZonedDateTime:
This class handles conversion from the local time-line of LocalDateTime to the instant time-line of Instant. The difference between the two time-lines is the offset from UTC/Greenwich, represented by a ZoneOffset.
To get an Instant you need to convert LocalDateTime to ZonedDateTime first. If you did this correctly(by stating the correct timezone) your Instant will agree with System.currentTimeMillis().
System.currentTimeMillis():
the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
the output of the LocalDateTime at GMT+3 is the same as of System.currentTimeMillis(), although the docs for the System.currentTimeMillis() mention UTC?
If your timezone is GMT+3 then ZonedDateTime.toInstant() will give you the correct Instant and therefore agree with System.currentTimeMillis()
the output of the LocalDateTime at UTC differs from System.currentTimeMillis(), although the docs for the System.currentTimeMillis() mention UTC?
If your timezone is not UTC then ZonedDateTime.toInstant() will give you an incorrect Instant.
System.out.println("Output 1 : " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("Output 2 : " + System.currentTimeMillis());
Output 1 : 1576047664910
Output 2 : 1576047664911

Categories

Resources