Using two LocalDateTime instances to calculate a duration - java

I am trying to calculate the duration between two instances of LocalDateTime. The special thing here is that each instance of LocalDateTime could be from ANYWHERE in the world:
LocalDateTime start could be from Nevada and LocalDateTime end could be from Tokyo. Each "time" associated with the LocalDateTime is, obviously enough, local to that location.
So if I said...
LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00"); and said that start represented Chicago, that would mean 10:00 AM in Chicago time.
Then I could say...
LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00"); and end represents Moscow, so it is 3:00AM in Moscow time.
Can I create a robust enough solution that will allow start and end to represent any cities in the world and still correctly calculate the duration between the two?

"LocalDateTime" Does Not Mean A Particular Locality
I think you misunderstand the purpose of LocalDateTime. The "local" means any locality, not a specific locality. As in "Christmas starts at midnight on December 25, 2015" where we mean any locality’s midnight. Christmas starts in Paris several hours earlier than Montréal, for example.
If you know the date-time is meant to represent a date-time in Nevada, the use a Joda-Time DateTime assigned the proper time zone name of America/Boise. In the new java.time package (Tutorial) built into Java 8 and later, use a ZonedDateTime object with assigned time zone.
Similarly, if you know the date-time is local to Tokyo, do not use LocalDateTime. Use a Joda-Time DateTime with an assigned time zone of Asia/Tokyo.
Elapsed
Elapsed time between a pair of LocalDateTime instances makes no sense. For example, the times may be 14:00 and 18:00 on the same date, but that does not mean four hours difference. If you really meant 14:00 in Paris and 18:00 in Chicago, that would be several hours difference, not two.
I am not discussing calculating elapsed time as that has been handled many many times on StackOverflow. I'm trying to clarify some concepts here. Then you can move on to the existing Questions & Answers for calculating elapsed time.
Databases Store UTC
Generally in SQL databases you should be using the data type TIMESTAMP WITH TIME ZONE (a.k.a. TIMESTAMPZ with a Z for "zulu"). This misnomer actually means "with respect for time zone". Incoming data with an offset from UTC or other time zone information is adjusted to UTC. The data's offset or time zone is not preserved.
The SQL data type TIMESTAMP WITHOUT TIME ZONE (a.k.a. TIMESTAMP) means the same as a LocalDateTime in Java: no time zone at all. Not tied to the timeline. Any offset or time zone information with input data is ignored, no adjustment made.
Postgres doc may help explain.
Stick With UTC
When retrieving such a value from the database, the UTC value may be adjusted to a particular time zone by your admin tool (such as pgAdmin in Postgres) or your database driver or by your app.
In your app it is generally best to keep your date-time values in UTC as much as possible. Do nearly all of your storage, business logic, and data exchange in UTC. Only adjust to a particular time zone when expected by the user.
To Convert A LocalDateTime To A Time Zone
If you do have a LocalDateTime object, and you want to assign it a time zone, here is some example code. We also adjust to get the very same moment as seen in Montréal and in UTC. First the example is shown in Joda-Time, then in java.time.
Joda-Time
Example in Joda-Time 2.8.
LocalDateTime ldt = new LocalDateTime( "2015-07-14T10:00:00" ); // Nowhere in particular.
DateTimeZone zoneChicago = DateTimeZone.forID( "America/Chicago" );
DateTime dateTimeChicago = ldt.toDateTime( zoneChicago );
DateTime dateTimeMontreal = dateTimeChicago.withZone( DateTimeZone.forID( "America/Montreal" ) );
DateTime dateTimeUtc = dateTimeChicago.withZone( DateTimeZone.UTC );
Dump to console.
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + dateTimeChicago );
System.out.println( "Montréal: " + dateTimeMontreal );
System.out.println( "UTC: " + dateTimeUtc);
When run.
LocalDateTime (nowhere): 2015-07-14T10:00:00.000
Chicago: 2015-07-14T10:00:00.000-05:00
Montréal: 2015-07-14T11:00:00.000-04:00
UTC: 2015-07-14T15:00:00.000Z
java.time
Example in java.time of Java 8 Update 51.
LocalDateTime ldt = LocalDateTime.parse( "2015-07-14T10:00:00" ); // Nowhere in particular.
ZoneId zoneChicago = ZoneId.of( "America/Chicago" );
ZonedDateTime zdtChicago = ZonedDateTime.of( ldt, zoneChicago );
ZonedDateTime zdtMontreal = zdtChicago.withZoneSameInstant( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtUtc = zdtChicago.withZoneSameInstant( ZoneOffset.UTC ); // ZoneOffset is a subclass of ZoneId.
Dump to console.
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + zdtChicago );
System.out.println( "Montréal: " + zdtMontreal );
System.out.println( "UTC: " + zdtUtc);
When run.
LocalDateTime (nowhere): 2015-07-14T10:00
Chicago: 2015-07-14T10:00-05:00[America/Chicago]
Montréal: 2015-07-14T11:00-04:00[America/Montreal]
UTC: 2015-07-14T15:00Z

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 get a TimeZone ID from a TimeStamp Value

Is it possible to get a TimeZone ID from a certain TimeStamp ? If it is please explain by a simple code.
private String getDate(long timeStamp) {DateFormat objFormatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
TimeZone timeZone = TimeZone.getTimeZone("GMT+4:30");
//Instead of the Above code I want to get the TimeZone ID from my timeStamp objFormatter.setTimeZone(timeZone);
Calendar objCalendar =
Calendar.getInstance(timeZone);
objCalendar.setTimeInMillis(timeStamp * 1000);
String result = objFormatter.format(objCalendar.getTime());
objCalendar.clear();
return result;
}
tl;dr
Impossible to derive offset/zone from a count-from-epoch-in-UTC. But you can adjust into a zone.
Instant.ofEpochSecond( yourCount )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
Avoid count-from-epoch
Firstly, avoid using a count-from-epoch number to track date-time values. Do you mean a count of whole seconds, milliseconds, microseconds, nanoseconds, or something else? Do you mean the Unix/Java epoch of 1970-01-01T00:00:00Z or one of the couple dozen other epochs in use by many computer systems?
Apparently you have whole seconds, and I'll assume the Unix/Java epoch.
Impossible to get zone from count-from-epoch
You cannot “ get a TimeZone ID from a certain TimeStamp”, that is impossible. Your count-from-epoch was made while accounting for a certain time zone, usually UTC. If must know that intended zone used in creating that count-from-epoch, it cannot be deduced.
Perhaps your goal is actually adjusting this count-from-epoch into a date-time for a particular region’s time zone. Read on.
java.time
Avoid the troublesome old date-time classes such as Date & Calendar now supplanted by the java.time classes.
Convert your count-from-epoch into a point on the timeline in UTC.
Instant instant = Instant.ofEpochSecond( yourCount ) ;
Assign your desired time zone.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Asia/Kabul" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
See this code run live at IdeOne.com.
Notice the 4.5 hour difference, changing from 02:40 to 07:10, appropriate for time in Kabul. This is the same moment, the same point on the time zone, but viewed through the lens of a different region’s wall-clock time.
input: 1500000000
instant: 2017-07-14T02:40:00Z
zdt: 2017-07-14T07:10+04:30[Asia/Kabul]
I would like to answer this question based on the definition of each terminology.
What is timestamp?
Timestamp or Unix Timestamp is the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970,minus the number of leap seconds that have taken place since then. Wikipedia
Wath is Time Zone?
A time zone is a region of the earth where the same standard time is used. Each time zone is described by an identifier and usually has the format region/city (Asia/Tokyo) and an offset from Greenwich/UTC time. For example, the offset for Tokyo is +09:00. Time Zone Oracle Doc
Regarding to both definitions there is no way to get a region of the earth based on a number of seconds (time), it is imperative to know from what region of the earth the time comes from.

Java API and client app - how to handle timezone properly

I'm developing a Java API that is being used by an android app. I have arrived to a point where I need to correctly handle date and time taking into account timezones.
One of the features of the app is to book some sort of service specifying a date and a time. There is the possibility for the user to cancel the booking and if the cancellation occurs 24h before the booking starts, the client gets all the amount refunded.
Now let's say the server is in London(gmt 0) and the user in Spain(gmt +1) and a booking start on 25-02-2015 at 16:00:00.
When the user cancels a booking the server needs to make the difference between NOW() and the booking start date. So if the user (in spain) makes a cancelation the 24-02-2015 at 17:00:00(spain time, 23hours before booking ; therefore he doesn't get full refund)
when the server checks the difference, because the NOW (it is 16:00:00 in UK) the result will be 24h and therefore will refund full amount wrongly.
My question is here. How do I correctly get the RIGHT amount of hours depending on the user timezone ?
I'm not very happy with sending the client time zone in the cancellation request because the value can easily be tricked by the user.
What is a good practice when storing date and time sever side ? Should I store them in the server time and use an extra field to know the client timezone offset's ?
The Answer by Baranauskas is correct.
Work in UTC
Generally all your business logic, data exchange, data storage, and serialization, should be done in UTC. Apply a time zone only where required/expected, such as presentation to a user.
java.time
Definitely use java.time framework built into Java 8 and later.
By default, the java.time classes use standard ISO 8601 formats for parsing/generating textual representations of date-time values. Otherwise use a DateTimeFormatter object.
The Local… types are generic, not applying to any locality, having no time zone or offset-from-UTC. Generally not used in business apps as they are not actual moments on the timeline. Used here for parsing a date string and a time string separately, combining, and then applying the known time zone for Spain. Doing so produces a ZonedDateTime, an actual moment on the timeline.
LocalDate dateBooking = LocalDate.parse ( "2016-02-25" ); // Parses strings in standard ISO 8601 format.
LocalTime timeBooking = LocalTime.parse ( "16:00:00" );
LocalDateTime localBooking = LocalDateTime.of ( dateBooking , timeBooking );
ZoneId zoneId = ZoneId.of ( "Europe/Madrid" );
ZonedDateTime zonedBooking = localBooking.atZone ( zoneId );
From that we can extract an Instant, a moment on the timeline in UTC.
Instant booking = zonedBooking.toInstant ();
Calculate our 24 hours of required notice for cancellations. Note that 24-hours is not the same as “one day” as days vary in length because of anomalies such as Daylight Saving Time (DST).
Instant twentyFourHoursEarlier = booking.minus ( 24 , ChronoUnit.HOURS );
Get the current moment for the user in process of cancelling. Here we simulate by using the date-time specified in the Question. For shorter code, we adjust by an hour because this parse method handles only UTC (Z) strings. The Question stated 17:00 in Spain time; Europe/Madrid is one hour ahead of UTC so we subtract an hour for 16:00Z.
Instant cancellation = Instant.parse ( "2016-02-24T16:00:00Z" ); // 17:00 in Europe/Madrid is 16:00Z.
// Instant cancellation = Instant.now (); // Use this in real code.
Compare Instant objects by calling the isBefore or isAfter methods.
Boolean cancelledEarlyEnough = cancellation.isBefore ( twentyFourHoursEarlier );
A Duration represents a span of time as a total number of seconds plus a fraction of a second in nanoseconds. We use this here to help with the mathematics, verifying we got the expected result of 23 hours. The toString method uses the standard ISO 8601 durations format of PT23H where P marks the beginning, T separates the years-months-days portion from hours-minutes-seconds portion, and H means “hours”.
Duration cancellationNotice = Duration.between ( cancellation , booking );
Dump to console.
System.out.println ( "zonedBooking: " + zonedBooking + " | booking: " + booking + " | twentyFourHoursEarlier: " + twentyFourHoursEarlier + " | cancellation: " + cancellation + " | cancelledEarlyEnough: " + cancelledEarlyEnough + " | cancellationNotice: " + cancellationNotice );
zonedBooking: 2016-02-25T16:00+01:00[Europe/Madrid] | booking: 2016-02-25T15:00:00Z | twentyFourHoursEarlier: 2016-02-24T15:00:00Z | cancellation: 2016-02-24T16:00:00Z | cancelledEarlyEnough: false | cancellationNotice: PT23H
Present to user by applying their desired/expected time zone. Specify an Instant and a ZoneId to get a ZonedDateTime.
ZoneId zoneId_Presentation = ZoneId.of( "Europe/Madrid" );
ZonedDateTime zdtBooking = ZonedDateTime.ofInstant( booking , zoneId_Presentation );
ZonedDateTime zdtCancellationGrace = ZonedDateTime.ofInstant( twentyFourHoursEarlier , zoneId_Presentation );
ZonedDateTime zdtCancellation = ZonedDateTime.ofInstant( cancellation , zoneId_Presentation );
Let java.time localize for you by specifying a short-medium-long flag and a Locale for the human language in which to (a) translate name of day/month, (b) use cultural norms for ordering of the date-time parts, choosing comma versus period, and such.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL );
formatter = formatter.withLocale( new Locale("es", "ES") );
String output = zdtBooking.format( formatter );
jueves 25 de febrero de 2016 16H00' CET
Ignore Server Time Zone
Your Question mentioned the server’s time zone. You should never depend on the server’s time zone as it is out of your control as a programmer, and it is easily changed with little thought by a sysadmin. In addition, your JVM’s current default time zone may be based on the that of the host operating system. But not necessarily. A flag on the command-line launching of the JVM may set the JVM’s default time zone. Even more dangerous: Any code on any thread of any app within the JVM can set the time zone and immediately affect your app -- during runtime!
If you do not specify a time zone, the JVM’s current default is implicitly applied. Always specify your desired/expected time zone explicitly, as seen in code above.
The above also goes for the current default Locale. Always specify the desired/expected Locale rather than depending implicitly on the JVM’s current default.
The plane is leaving at the same moment in time, no matter where in the world you are. This is also known as a timestamp. For such situations, storing a timestamp would be a proper solution. In java, current timestamp may be retrieved via System.currentTimeMillis(). This value does not depend on the time zone of your server and contains amount of millis since 1970 in UTC.
When user books the flight, you will need to convert user's selected time+timezone into the timestamp. When displaying, timestamps should be converted to user's timezone.
Validation with timestamps is a simple operation then: planeTakeOffTs - NOW > 24*60*60*1000
You may also want to use such library as joda-time (which has been included into inspired Java v8 java.time) to handle the dates and time.
Basil Bourque, to answer your last comment, I did the test below.
As you can see, setting the timezone has effect to LocalDateTime and fortunately.
Where you right is this is not the right solution and should be used if we do not have another solution.
public static void main(String[] args) {
Instant instant = Instant.now();
LocalDateTime local = LocalDateTime.now();
ZonedDateTime zone = ZonedDateTime.now();
System.out.println("====== WITHOUT 'UTC' TIME ZONE ======");
System.out.println("instant : " + instant );
System.out.println("local : " + local);
System.out.println("zone : " + zone);
System.out.println("instant converted : " + instant.atZone(ZoneId.of("Europe/Paris")).toLocalDateTime());
System.out.println("====================================");
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Instant instant2 = Instant.now();
LocalDateTime local2 = LocalDateTime.now();
ZonedDateTime zone2 = ZonedDateTime.now();
System.out.println("====== WITH 'UTC' TIME ZONE ======");
System.out.println("instant2 : " + instant2 );
System.out.println("local2 : " + local2);
System.out.println("zone2 : " + zone2);
System.out.println("instant2 converted : " + instant2.atZone(ZoneId.of("Europe/Paris")).toLocalDateTime());
System.out.println("==================================");
}
And the output :
====== WITHOUT 'UTC' TIME ZONE ======
instant : 2019-02-14T17:14:15.598Z
local : 2019-02-14T18:14:15.682
zone : 2019-02-14T18:14:15.692+01:00[Europe/Paris]
instant converted : 2019-02-14T18:14:15.598
====================================
====== WITH 'UTC' TIME ZONE ======
instant2 : 2019-02-14T17:14:15.702Z
local2 : 2019-02-14T17:14:15.702
zone2 : 2019-02-14T17:14:15.702Z[UTC]
instant2 converted : 2019-02-14T18:14:15.702
==================================
Note that as many developers use Hibernate, it provides this property hibernate.jdbc.time_zone which helps a lot when dealing whith date. Setting this property to UTC has effect to LocalDateTime and ZonedDateTime.

Convert json date to date in java

How to convert json date to java.util.Date
{"date":31,"day":4,"hours":0,"minutes":0,"month":11,"seconds":0,"time":2145805200000,"timezoneOffset":-420,"year":137}
Thanks for help
With a quick Google search, I managed to find this webpage: CLICK
The 'parse' method returning a Date shows you how to use the SimpleDateFormat class in Java which is used to parse a String into a Date.Hope this helped!
No JSON Date
No such thing as a JSON date. JSON has very few data types, none of which are date-time related.
Count Since Epoch
That time item with value 2145805200000 is probably a count since epoch. The two questions are: What epoch? and What granularity of count?
Commonly used are milliseconds since the Unix epoch of first moment of 1970 in UTC.
The java.time framework built into Java 8 and later can translate such number. The Instant class represents a moment on the timeline in UTC.
long sinceEpoch = 2145805200000L;
Instant instant = Instant.ofEpochMilli ( sinceEpoch );
Dump to console.
System.out.println ( "instant: " + instant );
instant: 2037-12-30T17:00:00Z
That value may be close to the other fields in your JSON, but is not quite a match.
Your JSON has an field timezoneOffset with value -420. If we interpret that number as an offset-from-UTC in minutes, that would mean 7 hours. We can ask java.time to adjust the Instant into such an offset.
Normally we would want to use a time zone for this adjustment. A time zone is an offset-from-UTC plus a set of historic rules for handling anomalies such as Daylight Saving Time (DST). But in this case we have only the offset-from-UTC. So rather than use a ZoneId we use the subclass ZoneOffset. The result is a ZonedDateTime.
ZoneOffset zoneOffset = ZoneOffset.ofHours ( 7 );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneOffset );
Dump to console.
System.out.println ( "instant: " + instant + " + zoneOffset: " + zoneOffset + " = zdt: " + zdt );
instant: 2037-12-30T17:00:00Z + zoneOffset: +07:00 = zdt: 2037-12-31T00:00+07:00
That gets us to the beginning of the day on the 31st of December in 2037. Still not an exact match to the other JSON fields.
But if that -420 was meant as being 7 hours behind UTC rather than ahead, we need to change that offset from 7 hours to a negative -7 hours. Then the results would be:
instant: 2037-12-30T17:00:00Z + zoneOffset: -07:00 = zdt: 2037-12-30T10:00-07:00
If you knew more about your JSON data, then perhaps a solution could be found.

Date gives one day less than actual date while converting from date to calendar

I am passing date from front end which is IST(date of indian timezone). And in java code i am converting date to calendar using the following code(This is happening in the server which is there in US PST timezone).
Calendar cal = Calendar.getInstance();
int offset = date.getTimezoneOffset();
logger.info("Calendar Instance - " + cal);
cal.setTime(date);
logger.info("Calendar Instance after setting date - " + cal);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
logger.info("Calendar Instance after setting zeros - " + cal);
return cal;
so when i see the last log the day of the month will be one day less than what i passed.eg. if i pass 22/06/2015 IST it shifts to 21/06/2015. so after processing finally it displays 21/06/2015 in the list of data which is in another UI page.
This happens because JVM on server side and JVM on client side use different time zones by default Java TimeZone:
Typically, you get a TimeZone using getDefault which creates a
TimeZone based on the time zone where the program is running. For
example, for a program running in Japan, getDefault creates a TimeZone
object based on Japanese Standard Time.
As we can see, Pacific Time Zone on server has UTC−8:00 and Indian Standard Time on client has UTC+05:30. They differ by 13.30 and Indian date X converts to US as X-13.30 what may yield a day before on server side for certain X.
Several workarounds are possible depending on how you can influence/modify your server and client application. For example, you may work with dates in UTC+00:00 time zone on both server and client sides. If you need to show a date to the user you may convert it to Indian time zone when needed.
// Set default GMT+0:00 time zone
TimeZone timeZone;
timeZone = TimeZone.getTimeZone("GMT+0:00");
TimeZone.setDefault(timeZone);
Instead of simply using Calendar cal = Calendar.getInstance(); you may create "clear" calendar which you will user later on to set day, month and year
public static Calendar createClearedCalendar() {
Calendar cal = Calendar.getInstance();
cal.setTimeZone(timeZone);
cal.set(1970, 0, 1, 0, 0, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MILLISECOND);
return cal;
}
By the way, if you manipulate date-time in Java you may consider Joda Time which has more extended options and optimized performance.
The Answer by Antonio is correct and should be accepted (click the big empty check mark).
This Answer adds some thoughts and example code.
Avoid 3-Letter Time Zone Codes
Avoid using, or even thinking about, those 3 or 4 letter codes such as IST or PST. They are not standardized, they are not unique, and they further confuse issues around Daylight Saving Time (DST). For example, IST means "India Standard Time", "Irish Standard Time", and more.
Use proper time zone names. Most of these are in a "continent" + "/" + "city/region" pattern. The city/region name is not meant specifically for that town, but rather as an easily identifiable name for as wide an area as possible that shares the same set of past, present, and future rules for time zone rules and anomalies (including DST).
Use UTC
Generally you should be using UTC time zone for all your business logic, data storage, and data exchange. Adjust to a particular time zone only for presentation when expected by the user.
Use A Decent Date-Time Framework
The old java.util.Date/.Calendar classes were a bold attempt at handling date-time work, but ultimately they failed. They are notoriously troublesome, flawed in both design and implementation. Avoid them.
The 3rd-party Joda-Time library is one solution. It works in many versions of Java and also in Android. Joda-Time inspired the other solution, the java.time package found in Java 8 and later (Tutorial).
Solution
The Question seems to have a goal of taking a java.util.Date object, assign desired time zone, and produce a java.util.Calendar object.
Fortunately the java.time framework has conversion methods. See this Tutorial page.
Example code follows, using java.time from Java 8 Update 45.
You may want imports such as:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
Let's simulate getting a java.util.Date passed in. We'll instantiate a Date based on "now".
Date inputDate = new Date( ); // Simulate getting a java.util.Date object.
Then we define the desired time zones, using proper time zone names. Let’s throw in Montréal just for fun as well as the pacific United States and India time zones mentioned in the Question.
ZoneId zoneLosAngeles = ZoneId.of( "America/Los_Angeles" );
ZoneId zoneMontréal = ZoneId.of( "America/Montreal" );
ZoneId zoneKolkata = ZoneId.of( "Asia/Kolkata" );
Then we convert that to an Instant, a point on the timeline without regard to time zone.
Instant instant = inputDate.toInstant( );
Then we assign various time zones to create ZonedDateTime instances. See how we can instantiate a ZonedDateTime in either of two ways: [a] from an Instant, or [b] from another ZonedDateTime via the withZoneSameInstant method. Both ways are shown below.
Note that java.time (and Joda-Time) uses immutable objects, a design pattern where we create new instances based on the old instance rather than alter ("mutate") the old instance. Thread-safety is one of the major benefits.
ZonedDateTime zdtLosAngeles = ZonedDateTime.ofInstant( instant, zoneLosAngeles );
ZonedDateTime zdtMontréal = ZonedDateTime.ofInstant( instant, zoneMontréal );
ZonedDateTime zdtKolkata = ZonedDateTime.ofInstant( instant, zoneKolkata );
ZonedDateTime zdtUtc = zdtKolkata.withZoneSameInstant( ZoneOffset.UTC );
Lastly, we convert one of those to a GregorianCalendar object which is a subclass of java.util.Calendar.
GregorianCalendar calendarKolkata = GregorianCalendar.from( zdtKolkata );
Dump to console.
System.out.println( "inputDate: " + inputDate );
System.out.println( "zdtLosAngeles: " + zdtLosAngeles );
System.out.println( "zdtMontréal: " + zdtMontréal );
System.out.println( "zdtKolkata: " + zdtKolkata );
System.out.println( "zdtUtc: " + zdtUtc );
System.out.println( "calendarKolkata: " + calendarKolkata );
When run.
inputDate: Wed Jun 24 15:12:12 PDT 2015
zdtLosAngeles: 2015-06-24T15:12:12.153-07:00[America/Los_Angeles]
zdtMontréal: 2015-06-24T18:12:12.153-04:00[America/Montreal]
zdtKolkata: 2015-06-25T03:42:12.153+05:30[Asia/Kolkata]
zdtUtc: 2015-06-24T22:12:12.153Z
calendarKolkata: java.util.GregorianCalendar[time=1435183932153,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Kolkata",offset=19800000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2015,MONTH=5,WEEK_OF_YEAR=26,WEEK_OF_MONTH=4,DAY_OF_MONTH=25,DAY_OF_YEAR=176,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=3,HOUR_OF_DAY=3,MINUTE=42,SECOND=12,MILLISECOND=153,ZONE_OFFSET=19800000,DST_OFFSET=0]

Categories

Resources