I know that:
Instant is rather a "technical" timestamp representation (nanoseconds) for computing.
LocalDateTime is rather date/clock representation including time-zones for humans.
Still in the end IMO both can be taken as types for most application use cases. As an example: currently, I am running a batch job where I need to calculate the next run based on dates and I am struggling to find pros/cons between these two types (apart from the nanosecond precision advantage of Instant and the time-zone part of LocalDateTime).
Can you name some application examples where only Instant or LocalDateTime should be used?
Edit: Beware of misread documentations for LocalDateTime regarding precision and time-zone.
tl;dr
Instant and LocalDateTime are two entirely different animals: One represents a moment, the other does not.
Instant represents a moment, a specific point in the timeline.
LocalDateTime represents a date and a time-of-day. But lacking a time zone or offset-from-UTC, this class cannot represent a moment. It represents potential moments along a range of about 26 to 27 hours, the range of all time zones around the globe. A LocalDateTime value is inherently ambiguous.
Incorrect Presumption
LocalDateTime is rather date/clock representation including time-zones for humans.
Your statement is incorrect: A LocalDateTime has no time zone. Having no time zone is the entire point of that class.
To quote that class’ doc:
This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
So Local… means “not zoned, no offset”.
Instant
An Instant is a moment on the timeline in UTC, a count of nanoseconds since the epoch of the first moment of 1970 UTC (basically, see class doc for nitty-gritty details). Since most of your business logic, data storage, and data exchange should be in UTC, this is a handy class to be used often.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
The class OffsetDateTime class represents a moment as a date and time with a context of some number of hours-minutes-seconds ahead of, or behind, UTC. The amount of offset, the number of hours-minutes-seconds, is represented by the ZoneOffset class.
If the number of hours-minutes-seconds is zero, an OffsetDateTime represents a moment in UTC the same as an Instant.
ZoneOffset
The ZoneOffset class represents an offset-from-UTC, a number of hours-minutes-seconds ahead of UTC or behind UTC.
A ZoneOffset is merely a number of hours-minutes-seconds, nothing more. A zone is much more, having a name and a history of changes to offset. So using a zone is always preferable to using a mere offset.
ZoneId
A time zone is represented by the ZoneId class.
A new day dawns earlier in Paris than in Montréal, for example. So we need to move the clock’s hands to better reflect noon (when the Sun is directly overhead) for a given region. The further away eastward/westward from the UTC line in west Europe/Africa the larger the offset.
A time zone is a set of rules for handling adjustments and anomalies as practiced by a local community or region. The most common anomaly is the all-too-popular lunacy known as Daylight Saving Time (DST).
A time zone has the history of past rules, present rules, and rules confirmed for the near future.
These rules change more often than you might expect. Be sure to keep your date-time library's rules, usually a copy of the 'tz' database, up to date. Keeping up-to-date is easier than ever now in Java 8 with Oracle releasing a Timezone Updater Tool.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
Time Zone = Offset + Rules of Adjustments
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
Think of ZonedDateTime conceptually as an Instant with an assigned ZoneId.
ZonedDateTime = ( Instant + ZoneId )
To capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone):
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`.
Nearly all of your backend, database, business logic, data persistence, data exchange should all be in UTC. But for presentation to users you need to adjust into a time zone expected by the user. This is the purpose of the ZonedDateTime class and the formatter classes used to generate String representations of those date-time values.
ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ; // Standard ISO 8601 format.
You can generate text in localized format using DateTimeFormatter.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String outputFormatted = zdt.format( f ) ;
mardi 30 avril 2019 à 23 h 22 min 55 s heure de l’Inde
LocalDate, LocalTime, LocalDateTime
The "local" date time classes, LocalDateTime, LocalDate, LocalTime, are a different kind of critter. The are not tied to any one locality or time zone. They are not tied to the timeline. They have no real meaning until you apply them to a locality to find a point on the timeline.
The word “Local” in these class names may be counter-intuitive to the uninitiated. The word means any locality, or every locality, but not a particular locality.
So for business apps, the "Local" types are not often used as they represent just the general idea of a possible date or time not a specific moment on the timeline. Business apps tend to care about the exact moment an invoice arrived, a product shipped for transport, an employee was hired, or the taxi left the garage. So business app developers use Instant and ZonedDateTime classes most commonly.
So when would we use LocalDateTime? In three situations:
We want to apply a certain date and time-of-day across multiple locations.
We are booking appointments.
We have an intended yet undetermined time zone.
Notice that none of these three cases involve a single certain specific point on the timeline, none of these are a moment.
One time-of-day, multiple moments
Sometimes we want to represent a certain time-of-day on a certain date, but want to apply that into multiple localities across time zones.
For example, "Christmas starts at midnight on the 25th of December 2015" is a LocalDateTime. Midnight strikes at different moments in Paris than in Montréal, and different again in Seattle and in Auckland.
LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ; // 00:00:00
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ; // Christmas morning anywhere.
Another example, "Acme Company has a policy that lunchtime starts at 12:30 PM at each of its factories worldwide" is a LocalTime. To have real meaning you need to apply it to the timeline to figure the moment of 12:30 at the Stuttgart factory or 12:30 at the Rabat factory or 12:30 at the Sydney factory.
Booking appointments
Another situation to use LocalDateTime is for booking future events (ex: Dentist appointments). These appointments may be far enough out in the future that you risk politicians redefining the time zone. Politicians often give little forewarning, or even no warning at all. If you mean "3 PM next January 23rd" regardless of how the politicians may play with the clock, then you cannot record a moment – that would see 3 PM turn into 2 PM or 4 PM if that region adopted or dropped Daylight Saving Time, for example.
For appointments, store a LocalDateTime and a ZoneId, kept separately. Later, when generating a schedule, on-the-fly determine a moment by calling LocalDateTime::atZone( ZoneId ) to generate a ZonedDateTime object.
ZonedDateTime zdt = ldt.atZone( z ) ; // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
If needed, you can adjust to UTC. Extract an Instant from the ZonedDateTime.
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
Unknown zone
Some people might use LocalDateTime in a situation where the time zone or offset is unknown.
I consider this case inappropriate and unwise. If a zone or offset is intended but undetermined, you have bad data. That would be like storing a price of a product without knowing the intended currency (dollars, pounds, euros, etc.). Not a good idea.
All date-time types
For completeness, here is a table of all the possible date-time types, both modern and legacy in Java, as well as those defined by the SQL standard. This might help to place the Instant & LocalDateTime classes in a larger context.
Notice the odd choices made by the Java team in designing JDBC 4.2. They chose to support all the java.time times… except for the two most commonly used classes: Instant & ZonedDateTime.
But not to worry. We can easily convert back and forth.
Converting Instant.
// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
Converting ZonedDateTime.
// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
One main difference is the "Local" part of LocalDateTime. If you live in Germany and create a LocalDateTime instance and someone else lives in the USA and creates another instance at the very same moment (provided the clocks are properly set) - the value of those objects would actually be different. This does not apply to Instant, which is calculated independently from a time zone.
LocalDateTime stores date and time without a timezone, but its initial value is timezone-dependent. Instant's is not.
Moreover, LocalDateTime provides methods for manipulating date components like days, hours, and months. An Instant does not.
apart from the nanosecond precision advantage of Instant and the
time-zone part of LocalDateTime
Both classes have the same precision. LocalDateTime does not store the timezone. Read Javadocs thoroughly, because you may make a big mistake with such invalid assumptions: Instant and LocalDateTime.
You are wrong about LocalDateTime: it does not store any time-zone information and it has nanosecond precision. Quoting the Javadoc (emphasis mine):
A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.
LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second. Other date and time fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. Time is represented to nanosecond precision. For example, the value "2nd October 2007 at 13:45.30.123456789" can be stored in a LocalDateTime.
The difference between the two is that Instant represents an offset from the Epoch (01-01-1970) and, as such, represents a particular instant on the time-line. Two Instant objects created at the same moment in two different places on the Earth will have exactly the same value.
LocalDateTime has no time-zone information: one LocalDateTime may represent different instants for different machines around the world. So you should not try to use it with an implicit time-zone (the system's default one). You should use it for what it represents, for instance "New-year is January 1st, at 0:00": this means a different time at all points on the globe but it's wanted in this case.
Instant is a point in time at the Greenwich time-zone. Use it in addition to the user's time-zone to show him/her the start of a meeting in his/her time-zone, for instance.
If these two classes do not represent what you wanted to store/exchange, then maybe ZonedDateTime or another class may do a better job.
Here is a simple synthetic schema to get the big-picture of the classes in the java.time package and their relation to the ISO-8601 standard used to reliably and effortlessly exchange dates and times between Java and other languages or frameworks:
The schema is explained in details here: http://slaout.linux62.org/java-date-time/
Related
Let's say that we have an appointment in Milan Italy happening on 01/23/2021 21:00 "Europe/Rome". This appointment is saved to the database in UTC in a column of a type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE.
Now a user living in New York US needs to understand when this appointment will take place. We can show that user the date-time converted to "America/New_York" time zone, or instead, in "Europe/Rome" TZ. Once the user will fly from New York to Milan, he will find both info useful.
The point is to store everything converted into the same TZ reference (UTC), and the manipulate the date-time depending on the goal you have using the java.time framework bundled with modern Java.
Makes sense or there is something wrong/missing?
Makes sense or there is something wrong/missing?
It depends on the kind of appointment.
There are two kinds of appointments:
A moment, a specific point on the timeline, ignoring any changes to time zone rules.Example: Rocket launch.
A date and time-of-day that should adjust for changes to time zone rules.Example: Medical/Dental visit.
Moment
If we are booking the launch of a rocket, for example, we do not care about the date and the time-of-day. We only care about the moment when (a) the heavens align, and (b) we expect favorable weather.
If in the intervening time the politicians change the rules of the time zone in use at our launch site or at our offices, that has no effect on our launch appointment. If politicians governing our launch site adopt Daylight Saving Time (DST), the moment of our launch remains the same. If the politicians governing our offices decide to change the clock a half-hour earlier because of diplomatic relations with a neighboring country, the moment of our launch remains the same.
For such an appointment, yes, your approach would be correct. You would record the appointment in UTC using a column of type TIMESTAMP WITH TIME ZONE. Upon retrieval, adjust into any time zone the user prefers.
Databases such as Postgres use any time zone info accompanying an input to adjust into UTC, and then disposes of that time zone info. When you retrieve the value from Postgres, it will always represent a date with time-of-day as seen in UTC. Beware, some tooling or middleware may have the anti-feature of applying some default time zone between retrieval from database and delivery to you the programmer. But be clear: Postgres always saves and retrieves values of type TIMESTAMP WITH TIME ZONE in UTC, always UTC, and offset-from-UTC of zero hours-minutes-seconds.
Here is some example Java code.
LocalDate launchDateAsSeenInRome = LocalDate.of( 2021 , 1 , 23 ) ;
LocalTime launchTimeAsSeenInRome = LocalTime.of( 21 , 0 ) ;
ZoneId zoneEuropeRome = ZoneId.of( "Europe/Rome" ) ;
// Assemble those three parts to determine a moment.
ZonedDateTime launchMomentAsSeenInRome = ZonedDateTime.of( launchDateAsSeenInRome , launchTimeAsSeenInRome , zoneEuropeRome ) ;
launchMomentAsSeenInRome.toString(): 2021-01-23T21:00+01:00[Europe/Rome]
To see the same moment in UTC, convert to an Instant. An Instant object always represents a moment as seen in UTC.
Instant launchInstant = launchMomentAsSeenInRome.toInstant() ; // Adjust from Rome time zone to UTC.
launchInstant.toString(): 2021-01-23T20:00:00Z
The Z on the end of the above string example is standard notation for UTC, and is pronounced “Zulu”.
Unfortunately the JDBC 4.2 team neglected to require support for either Instant or ZonedDateTime types. So your JDBC driver may or may not be able to read/write such objects to your database. If not, simply convert to OffsetDateTime. All three types represent a moment, a specific point on the timeline. But OffsetDateTime has support required by JDBC 4.2 for reasons that escape me.
OffsetDateTime odtLaunchAsSeenInRome = launchMomentAsSeenInRome.toOffsetDateTime() ;
Writing to database.
myPreparedStatement.setObject( … , odtLaunchAsSeenInRome ) ;
Retrieval from database.
OffsetDateTime launchMoment = myResultSet.getObject( … , OffsetDateTime.class ) ;
Adjust to the New York time zone desired by your user.
ZoneId zoneAmericaNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime launchAsSeenInNewYork = launchMoment.atZoneSameInstant( zoneAmericaNewYork ) ;
launchAsSeenInNewYork.toString(): 2021-01-23T15:00-05:00[America/New_York]
You can see all of the above code run live at IdeOne.com.
By the way, tracking past events are also treated as a moment. When did the patient actually arrive for appointment, when did the customer pay the invoice, when did a new hire sign their documents, when did the server crash… all these are tracked as a moment in UTC. As discussed above, usually that would be an Instant, though ZonedDateTime & OffsetDateTime also represent a moment. For the database use TIMESTAMP WITH TIME ZONE (not WITHOUT).
Time-of-day
I expect most business-oriented apps are focused on appointments of the other type, where we aim at a date with a time-of-day rather than a specific moment.
If the user makes an appointment with their health care provider to review the results of a test, they do so for a particular time-of-day on that date. If in the meantime the politicians change the rules of their time zone, moving the clock ahead or behind an hour or half-hour or any other amount of time, the date and time-of-day of that medical appointment remain the same. In actuality, the point of the timeline of the original appointment will be changed after the politicians change the time zone, shifting to an earlier/later point on the timeline.
For such appointmentss, we do not store the date and time-of-day as seen in UTC. We do not use the database column type TIMESTAMP WITH TIME ZONE.
For such appointments, we store the date with time-of-day without any regard to time zone. We use a database column of type TIMESTAMP WITHOUT TIME ZONE (notice WITHOUT rather than WITH). The matching type in Java is LocalDateTime.
LocalDate medicalApptDate = LocalDate.of( 2021 , 1 , 23 ) ;
LocalTime medicalApptTime = LocalTime.of( 21 , 0 ) ;
LocalDateTime medicalApptDateTime = LocalDateTime.of( medicalApptDate , medicalApptTime ) ;
Write that to the database.
myPreparedStatement.setObject( … , medicalApptDateTime ) ;
Be clear on this: a LocalDateTime object does not represent a moment, is not a specific point on the timeline. A LocalDateTime object represents a range of possible moments along about 26-27 hours of the timeline (the range of time zones around the globe). To give real meaning to a LocalDateTime, we must associate an intended time zone.
For that intended time zone, use a second column to store the zone identifier. For example, the strings Europe/Rome or America/New_York. See list of zone names.
ZoneId zoneEuropeRome = ZoneId.of( "Europe/Rome" ) ;
Write that to the database as text.
myPreparedStatement.setString( … , zoneEuropeRome ) ;
Retrieval. Retrieve the zone name as text, and instantiate a ZoneId object.
LocalDateTime medicalApptDateTime = myResultSet.getObject( … , LocalDateTime.class ) ;
ZoneId medicalApptZone = ZoneId.of( myResultSet.getString( … ) ) ;
Put those two pieces together to determine a moment represented as a ZonedDateTime object. Do this dynamically when you need to schedule a calendar. But do not store the moment. If the politicians redefine the time zone(s) in the future, a different moment must be calculated then.
ZonedDateTime medicalApptAsSeenInCareProviderZone = ZonedDateTime.of( medicalApptDateTime , medicalApptZone ) ;
The user is traveling to New York US. They need to know when to call the health care provider in Milan Italy according to the clocks on the wall in their temporary location of New York. So adjust from one time zone to another. Same moment, different wall-clock time.
ZoneId zoneAmericaNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime medicalApptAsSeenInNewYork = medicalApptAsSeenInCareProviderZone.withZoneSameInstant( zoneAmericaNewYork ) ;
tzdata
Be aware that if the rules of your desired time zones may be changing, you must update the copy of time zone definitions on your computers.
Java contains its own copy of the tzdata, as does the Postgres database engine. And your host operating system as well. This particular code shown here requires only Java to be up-to-date. If you use Postgres to make time zone adjustments, its tzdata must also be up-to-date. And for logging and such, your host OS should be kept up-to-date. For proper clock-watching by the user, their client machine's OS must also be up-to-date.
Beware: Politicians around the world have shown a penchant for changing their time zones with surprising frequency, and often with little forewarning.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
A very simple solution would be to leave the conversion to PostgreSQL. If you set the timezone parameter correctly for each session and use timestamp with time zone PostgreSQL will automatically show the timestamp to the New York user in New York time.
I have string of the pattern "yyyy-MM-dd'T'HH:mm:ssZ" which I want to convert to ZonedDateTime format using Java.
Input String Example: "2019-11-23T10:32:15+12:24"
Output: ZonedDateTime
Edit: I have tried this but it does not work.
ZonedDateTime convertToZonedDateTime(final String source) {
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = dateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
I have this solution which works for string "2018-04-05 19:58:55" produces output 2018-04-05T19:58:55+05:30[Asia/Kolkata] but when I change the pattern in function to "yyyy-MM-dd'T'HH:mm:ssZ" and input string to 2019-11-23T10:32:15+12:24 it does not work due to ParseException: Unparsable data.
I need ZonedDateTime format for an API which expects the input time in that format.
tl;dr
OffsetDateTime // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse( // Parse text into a date-time object.
"2019-11-23T10:32:15+12:24" // The offset of +12:24 looks suspicious, likely an error.
) // Returns an `OffsetDateTime` object.
Semantically, we are done at this point with a OffsetDateTime object in hand.
But you claim to be using an API that demands a ZoneDateTime object. We have no known time zone to apply, so let’s apply UTC (an offset of zero hours-minutes-seconds).
OffsetDateTime // Represent a moment as a date with time-of-day in the context of an offset-from-UTC (a number of hours-minutes-seconds).
.parse( // Parse text into a date-time object.
"2019-11-23T10:32:15+12:24" // The offset of +12:24 looks suspicious, likely an error.
) // Returns an `OffsetDateTime` object.
.atZoneSameInstant( // Convert from `OffsetDateTime` to `ZonedDateTime` by applying a time zone.
ZoneOffset.UTC // This constant is a `ZoneOffset` object, whose class extends from `ZoneId`. So we can use it as a time zone, though semantically we are making a mess.
) // Returns a `ZonedDateTime` object.
.toString() // Generate text in standard ISO 8601 format.
See this code run live at IdeOne.com.
2019-11-22T22:08:15Z
Caveat: The offset on your example input string looks wrong to me.
Details
You need to understand some concepts for date-time handling.
Offset
A offset-from-UTC is merely a number of hours-minutes-seconds ahead of, or behind, the meridian line drawn at the Greenwich Royal Observatory.
In Java, we represent an offset with the ZoneOffset class. A date and time-of-day in the context of an offset is represented with the OffsetDateTime class. Such an object represents a moment, a specific point on the timeline.
Time zone
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. These changes are determined by politicians. So these changes can be arbitrary and capricious, and happen surprisingly often, often with little or no warning. In North America, for example, most regions have adopted Daylight Saving Time (DST) nonsense, resulting in the offset changing twice a year. Currently there is a fad amongst politicians to quit DST changes while staying permanently year-round on “summer time”, one hour ahead of standard time.
There is a database cataloging these changes. The tZ data is a file maintained by IANA listing changes worldwide. You’ll likely find copies of this data in your host OS, in enterprise-quality database management systems such as Postgres, and in your Java Virtual Machine. Be sure to keep these up-to-date with changes in zones you care about.
Time zones have names in the format of Continent/Region. For example, Africa/Tunis, Europe/Paris, and Asia/Kolkata.
OffsetDateTime
So an input string like "2019-11-23T10:32:15+12:24" has no indicator of time zone, only an offset. So we must parse it an a OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.parse( "2019-11-23T10:32:15+12:24" ) ;
Asking for that as a ZonedDateTime makes no sense. We cannot reliably determine a time zone merely from an offset. Many time zones may share an offset for some pints in time.
Also, that particular input string 2019-11-23T10:32:15+12:24 is suspect. That offset of twelve hours and twenty-four minutes does not map to any current time zone. Are you sure it is correct?
You can convert your OffsetDateTime to a ZonedDateTime by specifying a time zone to use in adjustment. I suggest using UTC. While this works technically, semantically it is confusing. Moments in UTC are best represented by OffsetDateTime rather than ZonedDateTime. But apparently you are interoperating with code that demands a ZonedDateTime specifically, so c’est la vie.
ZonedDateTime zdt = odt.atZoneSameInstant( ZoneOffset.UTC ) ;
Instant
Tip: Generally, APIs should be written to hand off moments as an Instant object, which is always in UTC by definition.
LocalDateTime
You present another string input, "2018-04-05 19:58:55". This input lacks any indicator of time zone or offset-from-UTC. So we cannot know if this means almost-8PM in Tokyo Japan, or almost-8PM in Toulouse France, or almost-8PM in Toledo Ohio US — which are all events happening several hours apart, different points on the time zone.
Such a value must be parsed as a LocalDateTime. Replace the SPACE in the middle with a T to comply with ISO 8601 standard formatting.
LocalDateTime ldt = LocalDateTime.parse( "2018-04-05 19:58:55".replace( " " , "T" ) ) ;
The resulting object does not represent a moment, is not a point in the timeline. Such an object represents potential moments along a spectrum of about 26-27 hours, the range of time zones around the globe.
ZonedDateTime
If you are certain that input string was intended for a particular time zone, apply a ZoneId to get a ZonedDateTime. Then you have determined a moment, a specific point on the timeline.
ZoneId z = ZonedId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You can parse the input date time string into OffsetDateTime and then convert it into ZonedDateTime
String inputDate = "2019-11-23T10:32:15+12:24";
OffsetDateTime offset = OffsetDateTime.parse(inputDate);
ZonedDateTime dateTime = offset.toZonedDateTime();
If you just need ZonedDateTime at same local time with ZoneId then use atZoneSimilarLocal
ZonedDateTime dateTime = offset.atZoneSimilarLocal(ZoneId.systemDefault());
It’s unclear why you think you want a ZonedDateTime, and if you do, in which time zone. A bit of the following has been said already, but I would like to give you three suggestions to choose from:
You don’t need a ZonedDateTime. An OffsetDateTime fits your string better.
If you want a ZonedDateTime in your default time zone, which makes sense, use OffsetDateTime.atZoneSameInstant() (as in the answer by Basil Bourque).
If you just want a ZonedDateTime representation of your string, the one-arg ZonedDateTime.parse() parses it directly.
Use OffsetDateTime
Your string contains an offset, +12:34, and not a time zone, like Pacific/Galapagos. So OffsetDateTime is more correct to represent its content.
String inputStringExample = "2019-11-23T10:32:15+12:24";
OffsetDateTime dateTime = OffsetDateTime.parse(inputStringExample);
System.out.println(dateTime);
Output from this snippet is:
2019-11-23T10:32:15+12:24
I agree with the comment by Basil Bourque, the offset of +12:24 doesn’t look like a real-world UTC offset, but it’s fine for a Stack Overflow example. In 2019 most offsets are on a whole hour and the rest generally on a whole quarter of an hour, so 24 minutes is not used. Historic offsets include many with both minutes and seconds.
I am exploiting the fact that your string is in ISO 8601 format. The classes of java.time parse the most common ISO 8601 variants as their default, that is, without any explicit formatter. Which is good because writing a format pattern string is always error-prone.
Use OffsetDateTime.atZoneSameInstant()
Your call to ZoneId.systemDefault() in the code in the question seems to suggest that you want a ZonedDateTime in your default time zone. On one hand this use of ZonedDateTime seems reasonable and sound. On the other hand relying on ZoneId.systemDefault() is shaky since the default time zone of your JVM can be changed at any time by another part of your program or any ther program running in the same JVM.
ZonedDateTime dateTime = OffsetDateTime.parse(inputStringExample)
.atZoneSameInstant(ZoneId.systemDefault());
System.out.println(dateTime);
Output in my time zone:
2019-11-22T23:08:15+01:00[Europe/Copenhagen]
Parse directly
If you just need a ZonedDateTIme for an API that requires one (for most purposes a poor design), just parse your string into one:
ZonedDateTime dateTime = ZonedDateTime.parse(inputStringExample);
2019-11-23T10:32:15+12:24
Output is indistinguishable from the one we got from OffsetDateTime, but you have got the required type now.
Stay far away from SimpleDateFormat and Date
In the code in your question you tried to use SimpleDateFormat for parsing your string. Since you can use java.time, the modern Java date and time API, stick to it and forget everything about the old date and time classes. The modern API gives you all the functionality you need. In case we had needed a formatter for parsing, the modern DateTimeFormatter would have been the class to use.
What went wrong in your code?
… it does not work due to ParseException: Unparsable data.
Z in your format pattern string is for RFC 822 time zone offset. This is without colon and would have parsed +1224, but not +12:24.
Link
Wikipedia article: ISO 8601
Other system send for us Timestamp in their time zone.If we run that in cloud in other system is +2 hours. Local is good because the server is the same time zone. How can I be sure that the time will always be right?
String TIME_STAMP_FORMAT = "yyyy-MM-dd-HH.mm.ss.SSSSSS";
DateTimeFormatter TIME_STAMP_FORMATTER = DateTimeFormatter.ofPattern(TIME_STAMP_FORMAT, Locale.getDefault());
private static Timestamp parseTimestamp(String dateString) {
try {
return Timestamp.valueOf(LocalDateTime.parse(dateString, TIME_STAMP_FORMATTER));
} catch (DateTimeParseException e) {
log.error("Not able to parse timestamp", e);
}
return null;
}
Date afterParse = parseTimestamp('2018-12-31-12.30.50.000200')
tl;dr
How can I be sure that the time will always be right?
Include an indicator of time zone or offset-from-UTC with your date-time input string.
Use standard ISO 8601 formats when exchanging date-time values.
Use only java.time classes in Java. Never use Date, Timestamp, Calendar, etc.
Tip: Adjust values from other zones to UTC before sending (generally speaking).
If not possible, then here is a workaround. This assumes you know the time zone intended by the sender of this poor data.
LocalDateTime // Represent a date and time-of-day without the context of a time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline. A meaningless value until you assign a zone/offset.
.parse(
"2018-12-31-12.30.50.000200" , // Avoid such custom formats. Use only ISO 8601 when exchanging date-time values textually.
DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) // Define formatting pattern to match youre input.
) // Returns a `LocalDateTime` object.
.atZone( // Give meaning to the `LocalDateTime` object by applying a time zone.
ZoneId.of( "Africa/Tunis" ) // Always specify a time zone with `Continent/Region` name, never the 2-4 character pseudo-zones popularly seen in the media.
) // Returns a `ZonedDateTime` object.
.toInstant() // Adjust from a time zone to UTC by extracting an `Instant` object. Same moment, same point on the timeline, different wall-clock time.
See this code run live at IdeOne.com.
Best to avoid java.util.Date class. But if you must interoperate with old code not yet updated to java.time, you can convert. Call on the new methods added to the old classes such as Date.from( Instant ).
Avoid legacy classes
Never use java.sql.Timestamp nor java.util.Date. All of the date-time classes bundled with the earliest versions of Java are now legacy, per the adoption of JSR 310. Use only the modern java.time classes.
Wrong data type
You are using the wrong data type. To track a moment, a specific point on the timeline, you must have a time zone or offset-from-UTC. The LocalDateTime class exactly the wrong class to use here. That class purposely lacks any concept of zone or offset. So it is the opposite of what you want.
To track a moment, use Instant, OffsetDateTime, or ZonedDateTime.
Where the java.time classes have methods with an optional time zone (ZoneId) or offset-from-UTC (ZoneOffset) argument, consider the argument required. Always pass a zone/offset. Then you never need worry about how the sysadmin is setting the JVM’s current default time zone at runtime.
ZonedDateTime.now( // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Pacific/Auckland" )
)
Or, use Instant which is always in UTC, by definition.
Instant.now() // Capture the current moment in UTC.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ISO 8601
Your question is not clear, but it seems you are receiving an input string for a date-time in a custom format. I suggest you educate the people publishing that data about the ISO 8601 standard. This standard defines practical formats for date-time values being exchanged between systems textually.
The java.time classes use the ISO 8601 formats by default when parsing/generating strings.
Workaround
If the data publisher is sending you values such as 2018-12-31-12.30.50.000200 in order to communicate a moment, they have failed. A date and time-of-day without a zone or offset is useless, like communicating an amount of money without indicating a currency.
Do you know for certain the time zone that was implicitly assumed by the sender of this faulty data input? If so, apply it, as a clumsy stop-gap measure for their poor practice.
First parse your input as a LocalDateTime given that it lacks any indicator of zone/offset.
String input = "2018-12-31-12.30.50.000200" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd-HH.mm.ss.SSSSSS" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Apply a ZoneId to get a ZonedDateTime object, thereby adjusting to view the moment through the wall-clock time used by the people of that particular region.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( ldt ) ;
Generally best to work with moments in UTC, unless you have a specific reason to use a time zone (such as presentation to user). So extract an Instant from your ZonedDateTime.
Instant instant = zdt.toInstant() ;
The Z at the end of an ISO 8601 compliant string means UTC, and is pronounced “Zulu”.
See this code run live at IdeOne.com.
input: 2018-12-31-12.30.50.000200
ldt: 2018-12-31T12:30:50.000200
zdt: 2018-12-31T12:30:50.000200+09:00[Asia/Tokyo]
instant: 2018-12-31T03:30:50.000200Z
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Just a small supplement to Basil Bourque’s clever and very informative answer.
I know the date is in CET timezone.
I am sorry, this is not enough. Central European Time (CET) is the common term for quite many European and African(!) time zones the details of which differ. The European ones are generally at offset +01:00 during standard time and at +02:00 during summer (known as Central European Summer Time or CEST). The African ones are at +01:00 all year. For past dates, just a few decades back, some zones used summer time (DST), others didn’t, some were at +00:00, +01:00 or +02:00, and further back in history many other offsets were used, generally not whole hours.
The future is even worse! It has been suggested that the European Union abandons summer time and leaves it to each member state whether they will use permanent standard time or permanent summer time, avoiding the time adjustments in spring and autumn. There is a power struggle going on about this, so we don’t know whether it will happen, nor what each member state chooses. So even if you could tell me the exact time zone of your string from the other system (for example, Europe/Sarajevo), no one knows yet whether 2019-11-01-00.30.50.000200 — less than 7 months from now — will be at offset +01:00 or +02:00.
Link: European MPs vote to end summer time clock changes on BBC News.
I'm sending date from the Angular app as String to server and converting to java Date object to store in the database.
Also sending timeZoneOffset from UI to use the client's time zone while converting. (After googling I found this approach to get the proper result based on the user location)
Written the following code to convert:
public static void main(String args[]) throws ParseException {
String inputDate = "04/05/2018"; // This date coming from UI
int timeZoneOffset = -330; // This offset coming from UI
// (new Date().getTimeZoneOffset())
getDate(inputDate, timeZoneOffset);
}
public static Date getDate(String inputDate, int timeZoneOffset)
throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(-timeZoneOffset * 60);
System.out.println("Default time zone: " + TimeZone.getDefault().getID());
TimeZone timeZone = TimeZone.getTimeZone(zoneOffset);
System.out.println("Time zone from offset: " + timeZone.getID());
dateFormat.setTimeZone(timeZone);
Date date = dateFormat.parse(inputDate);
System.out.println("Converted date: " + date);
return date;
}
Expected output:
Default time zone: America/New_York
Time zone from offset: GMT+05:30
Converted date: Thu April 5 00:00:00 IST 2018
Actual result in server:
Default time zone: America/New_York
Time zone from offset: GMT+05:30
Converted date: Wed April 4 14:30:00 EDT 2018
Why is the date decreasing to one day even I set the users time zone? I'm new to Date and Time related concepts and I googled a couple of times didn't find answer, could someone please help on this.
Thanks in advance
The Answer by Godfrey is correct.
tl;dr
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toString()
2018-04-05T00:00+05:30[Asia/Kolkata]
For storage in your database, use UTC.
When a new day starts in India, the date at UTC is still “yesterday”, so April 4th rather than April 5th. Same moment, same point on the timeline, different wall-clock time.
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toInstant()
2018-04-04T18:30:00Z
java.time
You are using terrible old date-time classes that have proven to be poorly designed, confusing, and troublesome. They are now supplanted by the java.time classes.
Avoid legacy date-time classes entirely
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(-timeZoneOffset * 60);
…
TimeZone timeZone = TimeZone.getTimeZone(zoneOffset);
You are mixing the modern classes (ZoneOffset) with the troublesome legacy classes (TimeZone). Do not mix the modern classes with the legacy classes. Forget all about the old classes including Date, Calendar, and SimpleDateFormat. The java.time classes are designed to entirely supplant the legacy classes.
Instead of TimeZone, use ZoneId (and ZoneOffset).
LocalDate
Parse your input string as a LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone.
String input = "04/05/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;
Offset versus Time Zone
int timeZoneOffset = -330;
An offset-from-UTC is not a time zone. An offset is simply a number of hours, minutes, and seconds of displacement from UTC. Your choice of variable name indicates possible confusion on this point.
ZoneOffset offset = ZoneOffset.of( -3 , 30 ) ;
A time zone is a history of past, present, and future changes in offset used by the people of a particular region. So a time zone is always preferable to an offset.
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/Kolkata" ) ; // India time zone. Currently uses offset of +05:30 (five and a half hours ahead of UTC).
First moment of the day
You seem to be aiming for the first moment of that date in that zone. Let java.time determine that first-moment-of-the-day. Do not assume that time is 00:00:00. In some zones on some dates, the day may start at another time such as 01:00:00.
ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Determine the first moment of the day on this date in this zone. Not always 00:00:00.
As an example of why you should be using time zones rather than mere offset-from-UTC, look at your example data of -330 which I might easily misinterpret to be three and a half hours behind UTC. This offset is currently only used in the zone America/St_Johns, and only used there for part of the year. So if you applied an offset of -03:30 to a date in the wrong part of the year, your results would be invalid yet go undetected.
Using offset (not recommended)
But your example lacks time zone, so let’s go with offset-from-UTC rather than zone.
Your use of an int integer number to represent an offset-from-UTC is a poor choice of types. First of all, it is ambiguous. That -330 might be interpreted to be a clumsy attempt at -03:30 offset of three and a half hours behind schedule. Secondly, it makes parsing trickier than need be. Thirdly, as a number of minutes, it ignores the possibility of an offset with seconds. Fourthly, you use a negative number for an offset ahead of UTC (apparently) despite common usage and standard usage being the opposite. Lastly, it ignores the clear standard set by ISO 8601 for representing offsets as text: ±HH:MM:SS (and variations). By the way, the padding zero is optional in the standard, but I recommend always including because various libraries and protocols expect it.
Your intent appears to be a number of minutes intended by the integer number.
long seconds =( TimeUnit.MINUTES.toSeconds( - 330 ) * -1 ); // Multiply by negative one to flip the sign to standard ISO 8601 usage, where `+` means “ahead* of UTC and `-` means *behind* UTC.
seconds: 19800
ZoneOffset offset = ZoneOffset.ofTotalSeconds( ( int ) seconds );
offset.toString(): +05:30
Last step: get the first moment of the day in this offset. Caveat: We do not know for certain if this offset is valid on this date, as we lack a time zone.
Convert from the returned ZonedDateTime to an OffsetDateTime. As discussed above, determining first moment of day should always be done with a time zone, and thereby get a ZonedDateTime. We are violating that sensible practice to use an offset, but using the returned ZonedDateTime object would be misleading as ours would lack a true time zone, and have only a mere offset. So the OffsetDateTime class makes our intentions clear and our code more self-documenting.
OffsetDateTime odt = ld.atStartOfDay( offset ).toOffsetDateTime();
Again, this approach using offset is not recommending, as you should be instead gathering a time zone name from the user as input rather than an offset.
UTC
Generally best to store moments in UTC.
Extract a Instant from your OffsetDateTime or ZonedDateTime to get the same moment as UTC.
Instant instant = zdt.toInstant() ;
2018-04-04T18:30:00Z
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
It's not decreasing by one day, it is decreasing by 11.5 hours. That happens to be the time difference between GMT+05:30 and "America/New_York", which is GMT-04:30 or GMT-05:30 (depending on time of year).
GMT+05:30 is somewhere in India, I think, since that is about the only place to use a 30 minute offset rather than a whole hour. When it is April 5th in India, it is still April 4th in New York.
The problem may be you aren't getting a time from the client, so it will assume midnight. If you are doing time zone conversion, it is best to include the actual time.
This may be a very basic question, but i could'nt find any satisfactory answers.Hope my doubts gets clear on stackoverflow.
Q 1. Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
Q 2. Is there any way to get timezone using JavaScript?
Q 3. A timezone is just the representation of time in a particular zone, but actually every zone is at the same time,just representation wise it may be different depending on geographical conditions. - Is this understanding Correct?
possible duplicate link
Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
Create a formatter and set the timezone in there.
Internally, java.util.Date just stores milliseconds since the Epoch in the UTC timezone.
When you use Date.toString() or new SimpleDateFormat() without a timezone, then the default timezone of your VM is used.
So in a sense, Java always converts to your current/default timezone (unless you happen to be in UTC).
Is there any way to get timezone using Java Script?
It depends. You can use getTimezoneOffset() but that gives you only the offset. There is no API to get the client's OSs timezone ID (like UTC, Europe/Berlin, etc.)
A timezone is just the representation of time...
Not really. See above.
Q 1. Suppose i have time in a different timezone and i want to convert it to a different timezone, what is the way to do it in Java?
The modern way is with the java.time classes.
Firstly, do much of your work in UTC. Apply a time zone only where necessary, such as presentation to a user.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = Instant.now();
If you have only an offset-from-UTC rather than a time zone, apply a ZoneOffset to get a OffsetDateTime.
ZoneOffset offset = ZoneOffset.ofHours( -4 );
OffsetDateTime odt = instant.atOffset( offset );
A time zone is an offset-from-UTC (a specific number of hours, minutes, and seconds) plus a set of rules for handling anomalies such as Daylight Saving Time (DST). Represent a time zone with a ZoneId object. Specify a proper time zone name. 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(!).
Apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
You can apply other time zones to either the Instant or the ZonedDateTime.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );
Q 2. Is there any way to get timezone using JavaScript?
The issue of determining a time zone from a web browser has been handled countless times on Stack Overflow already.
So I'll skip this, except to say the upshot: No, not really in a reliable way; When important to know the time zone precisely you must ask the user herself.
Q 3. A timezone is just the representation of time in a particular zone, but actually every zone is at the same time,just representation wise it may be different depending on geographical conditions. - Is this understanding Correct?
No, a time zone is not a date-time moment.
A time zone adds meaningful context to a date-time in the same way that a currency designation adds meaningful context to an amount of money. A date-time without a time zone is just a rough idea of possible moments, not a precise point on the timeline. Noon at Auckland is earlier than noon in Kolkata which is earlier than noon in Paris which is earlier than noon in Montréal Québec.
You can think of it as pseudo-math statement:
Time Zone = ( Offset-from-UTC + set-of-rules-for-anomalies )
An example of an imaginary time zone:
An offset might be “one hour ahead of UTC”, plus
This set of rules: “On this date we will engage DST, on this date we will disengage DST, on this date during World War II we did shift ahead one hour, on this date after World War II we shifted back one hour, on this date our government shifted clocks forward a half-hour to make us distinct from our arch-rival neighbor country, …”.
You can apply a time zone to a point on the timeline. Like looking at art through a lens, it changes your perception but not the artifact itself. Looking at a point on the timeline through the lens of a time zone distorts the time-of-day and possibly the date into that of a particular community’s wall-clock time.
Another pseudo-math equation as a way of thinking about the class representations of a time zone and a moment on the timeline:
ZonedDateTime = Instant + ZoneId
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I can answer to your second question and correct the Aaron Digulla very complete response
Is there any way to get timezone using Java Script?
try to use this library, it will return a TimeZone ID with particular limitation (menthioned in the developer's page):
https://bitbucket.org/pellepim/jstimezonedetect