ZonedDateTime with timezone added to print format - java

I'm using https://github.com/JakeWharton/ThreeTenABP in my project.
I have org.threeten.bp
ZonedDateTime: 2019-07-25T14:30:57+05:30[Asia/Calcutta]
How can I get this printed with addition of the timezone hours? ie the result should have 2019-07-25T20:00:57

Get the offset in the form of seconds from ZonedDateTime
ZonedDateTime time = ZonedDateTime.parse("2019-07-25T14:30:57+05:30");
long seconds = time.getOffset().getTotalSeconds();
Now get the LocalDateTime part from ZonedDateTime
LocalDateTime local = time.toLocalDateTime().plusSeconds(seconds); //2019-07-25T20:00:57
toLocalDateTime
Gets the LocalDateTime part of this date-time.
If you want to get the local date time in UTC use toInstant()
This returns an Instant representing the same point on the time-line as this date-time. The calculation combines the local date-time and offset.
Instant i = time.toInstant(); //2019-07-25T09:00:57Z

You misunderstood. The offset of +05:30 in your string means that 5 hours 30 minutes have already been added to the time compared to UTC. So adding them once more will not make any sense.
If you want to compensate for the offset, simply convert your date-time to UTC. For example:
ZonedDateTime zdt = ZonedDateTime.parse("2019-07-25T14:30:57+05:30[Asia/Calcutta]");
OffsetDateTime utcDateTime = zdt.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(utcDateTime);
Output:
2019-07-25T09:00:57Z

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.

Java LocalDateTime remove the milliseconds from UTC timezone

I am trying to truncate milliseconds from a UTC time zone.
I have the code below where I am able to remove milliseconds but I still get the Z at the end.
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC );
OffsetDateTime eventDateTime=now.minus(4, ChronoUnit.MINUTES);
System.out.println("====Event date Time before truncate===");
System.out.println(eventDateTime);
System.out.println("====Event date Time after truncate===");
System.out.println(eventDateTime.truncatedTo(ChronoUnit.SECONDS));
This outputs the following:
====Event date Time before truncate===
2021-03-09T20:46:24.081Z
====Event date Time after truncate===
2021-03-09T20:46:24Z
tl;dr
To represent a moment in UTC, use Instant class rather than LocalDateTime or OffsetDateTime.
Instant
.now() // Returns a `Instant` representing the current moment including a fractional second.
.truncatedTo(
ChronoUnit.SECONDS // Granularity of what you want chopped off. In this case, we lop off any fractional second.
) // Returns another `Instant` object. Per immutable objects, a new object is instantiated rather than altering ("mutating") the original.
.minus( // Go backwards on the timeline.
Duration.ofMinutes( 4 ) // Amount of time to go backwards.
) // Returns another `Instant` object.
.toString() // Generate text in standard ISO 8601 format, with `Z` on the end meaning an offset of zero hours-minutes-seconds from the UTC temporal prime meridian.
Zulu time
The Z at the end represents vital information: the date-time represents a moment as seen with an offset from UTC of zero hours-minutes-seconds. This letter is defined as part of the standard formats in ISO 8601. The letter is pronounced “Zulu” per aviation/military tradition.
If you do not care about offset or time zone in your problem domain, then you are using the wrong type.
The types Instant, OffsetDateTime, and ZonedDateTime all represent a moment, a specific point on the timeline. All three involve an offset or time zone.
LocalDateTime
If you want only a date with time-of-day but lacking the context of an offset/zone, then use LocalDateTime. No Z will appear in text representing the value of a LocalDateTime because no offset is involved.
Just be aware that a LocalDateTime object is inherently ambiguous, and does not represent a moment. In other words, calling LocalDateTime.now is almost never the right thing to do. But if you insist:
LocalDateTime ldt = LocalDateTime.now( ZoneOffset.UTC ) ;
The Z is the timezone information. You can convert the OffsetDateTime instance to a LocalDateTime like this:
eventDateTime.truncatedTo(ChronoUnit.SECONDS).toLocalDateTime()
There can be two ways:
Preferred way: Use DateTimeFormatter
Use OffsetDateTime#toLocalDateTime: The problem with this approach is that the output string is automatically truncated to minutes if the seconds part is zero.
Demo:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtfWithoutSecFraction = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss");
DateTimeFormatter dtfWithSecFraction = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSS");
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
OffsetDateTime eventDateTime = now.minusMinutes(4);
System.out.println("====Event date Time before truncate===");
System.out.println(eventDateTime);
System.out.println(eventDateTime.toLocalDateTime());
System.out.println(dtfWithSecFraction.format(eventDateTime));
System.out.println("====Event date Time after truncate===");
System.out.println(eventDateTime.truncatedTo(ChronoUnit.SECONDS));
System.out.println(eventDateTime.truncatedTo(ChronoUnit.SECONDS).toLocalDateTime());
System.out.println(dtfWithoutSecFraction.format(eventDateTime.truncatedTo(ChronoUnit.SECONDS)));
}
}
Output:
====Event date Time before truncate===
2021-03-09T21:17:17.589016Z
2021-03-09T21:17:17.589016
2021-03-09T21:17:17.589016
====Event date Time after truncate===
2021-03-09T21:17:17Z
2021-03-09T21:17:17
2021-03-09T21:17:17
Note that Z stands for Zulu which specifies date-time in UTC (i.e. a timezone offset of +00:00 hours).
The following table gives you an overview of java.time types:
As you can see, OffsetDateTime, ZonedDateTime etc. carry timezone information and you can get just the date-time part using the techniques mentioned in the solution above.
Learn more about the modern date-time API from Trail: Date Time.

how to get timezone offset for current date in java

correct date format i am looking for:- "2017-07-06T18:03:39.195+0530"
how to get the +0530 for the current date in java ?
when i am using SimpleDateFormat it is giving +0000 , while it should give +0530 .
=================================================
i have tried using below :-
SimpleDateFormat format = new SimpleDateFormat("enter code hereyyy-MM-dd HH:mm:ss.SSS Z");
String dateString = format.format(new Date());
System.out.println("value of dateString is :"+dateString);
the above code will output :-
value of dateString is :2017-07-10 06:51:27.250 +0000
while it should output : +0530
can you please tell me how can i get the +0530 offset for the above date or current date ?
tl;dr
ZonedDateTime.now( ZoneId.of( "Asia/Kolkata" ) ).toOffsetDateTime().toString()
OffsetDateTime
To directly address the Question, use the modern OffsetDateTime class.
OffsetDateTime.now().toString()
See this code run live at IdeOne.com.
odt.toString(): 2019-08-22T17:44:00.219684Z
That will generate a string representing the current moment in the offset used by the JVM’s current default time zone using standard ISO 8601 format. One difference: This method will include the optional COLON : character between hours and minutes of the offset. I suggest never omitting that character as I have seen multiple libraries break on such input, expecting the COLON to be there.
When capturing the current moment, the result may resolve to microseconds. If you prefer milliseconds, truncate, lopping off the micros.
OffsetDateTime.now().truncatedTo( ChronoUnit.MILLIS )
odtTruncated.toString(): 2019-08-22T17:44:00.219Z
That code running at IdeOne.com is in a JVM where the offset is set to zero, for UTC itself. So we see a Z at the end, a common and standard alternative to +00:00, pronounced “Zulu”.
You may want to specify your offset explicitly.
Instant instant = Instant.now() ; // Current moment in UTC.
ZoneOffset offset = ZoneId.of( "Asia/Kolkata" ).getRules().getOffset( instant ) ; // We must pass a moment. India is currently at five and a half hours ahead of UTC. But it has not always been so in the past, and may not always be so in the future.
OffsetDateTime odt = instant.atOffset( offset ) ;
odt.toString(): 2019-08-22T23:00:06.925139+05:30
I think a cleaner syntax is to use ZonedDateTime.
String output = ZonedDateTime.now( ZoneId.of( "Asia/Kolkata" ) ).toOffsetDateTime().toString() ;
2019-08-22T23:03:19.072681+05:30
ZonedDateTime
More likely you should be getting the current moment in a time zone rather than a mere offset. If so, see the Answer by RaT.
Be clear on the difference between offset and zone:
An offset-from-UTC is merely a number of hours-minutes-seconds ahead of UTC or behind UTC.
A time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. A zone has a name in Continent/Region format, such as America/Montreal or Africa/Tunis.
Converting
Normally, you should avoid using the terrible date-time classes such as java.util.Date and SimpleDateFormat that are now legacy. Always use Instant, OffsetDateTime, and ZonedDateTime. Never use Date & Calendar.
But if you must you must use the legacy classes when interoperating with old code not yet updated for the java.time classes, you can convert back-and-forth. This is shown in the Answer by RaT.
You can Use Java 8 DateTime API for another solution
ZoneId zone = ZoneId.systemDefault(); //It will give current System's timezone (IST for you)
Date date = new Date(); // Any date
DateTimeFormatter formatter= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS Z", Locale.ENGLISH);
ZonedDateTime zonedTime = ZonedDateTime.ofInstant(date.toInstant(), zone);
System.out.println(zonedTime.format(formatter));
Above code will give you Date with correct Zone Offset
After a lot of searching I found that the timezone problem can be solved with Joda time API. You can use below code to achieve what I want in my question:
DateTime dateTime = DateTime.now();
System.out.println(dateTime.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
It outputs the current date with proper timezone:
2017-07-10T15:01:48.319+0530
Set the timezone you need. Your code would looke like:
SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS Z");
format.setTimeZone(TimeZone.getTimeZone("IST"));
String dateString = format.format(new Date());
System.out.println("value of dateString is :"+dateString);

how to get the start date of the day from specific time stamp in java

sample:
Long timeStamp = 1466058808;
Time time = new Time(timeStamp );
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(format.format(time));
print is: 2016-05-31 08:19:07
How can I get expected results is : 2016-05-31 00:00:00
Thanks!
And finally get the time stamp of 2016-05-31 00:00:00 This is what i want
So anyone know how to make it?
Simple, use:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
Or if you want a long (and have java 8):
LocalDateTime.ofEpochSecond(1466058808, 0, ZoneOffset.UTC).toLocalDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC)
java.time
The Answer by krzyk is close but ignores the crucial issue of time zone. Let's try that again using the java.time framework built into Java 8 and later. Much of java.time functionality is back-ported to Java 6 & 7 (ThreeTen-Backport) and further adapted to Android (ThreeTenABP).
Count of seconds from epoch
You do not say so in the Question, but we assume the Long of 1466058808 is a number of whole seconds from the epoch of first moment of 1970 in UTC.
Instant
First we convert that to an Instant, a moment on the timeline in UTC.
Instant instant = Instant.ofEpochSecond( 1466058808L );
Time Zone
Determining a date, and the start of the day, depends on a time zone. For any given moment, the date can vary around the world by time zone. A few moments after midnight in Paris is still “yesterday” in Montréal.
ZonedDateTime
You can make wide use of Instant in your code. Generally best practice is to perform business logic, data storage, logging, and so on in UTC. Apply a time zone only where required such as display to a user. Apply a ZoneId to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Using LocalDate for start-of-day
To get the start of the day we need to go through the LocalDate class. Note that we should always pass the optional time zone argument. If omitted, the JVM’s current default time zone is implicitly applied. That default can change at any time, even during runtime, as any code in any app of the JVM can make a call to TimeZone.setDefault. Better to be specific.
LocalDate localDate = zdt.toLocalDate();
ZonedDateTime startOfDay = localDate.atStartOfDay( zoneId );
Note that you should not assume the day starts at 00:00:00.0. Daylight Saving Time (DST) may mean the day starts at a different wall-clock time.
One-liner
I do not recommend doing so, but you can combine all this into a single line.
ZonedDateTime startOfDay = ZonedDateTime.ofInstant( Instant.ofEpochSecond( 1466058808L ) , ZoneId.of( "America/Montreal" ) ).toLocalDate().atStartOfDay( ZoneId.of( "America/Montreal" ) );
use a Calendar, so you can extract date properties:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(millis);
//getting the desired properties
cal.get(Calendar.YEAR);
cal.get(Calendar.MONTH);
cal.get(Calendar.DAY_OF_MONTH);

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