Joda-Time: DateTime, DateMidnight and LocalDate usage - java

Joda-Time library includes different datetime classes
DateTime - Immutable replacement
for JDK Calendar DateMidnight
- Immutable class representing a date where the time is forced to
midnight LocalDateTime -
Immutable class representing a local
date and time (no time zone)
I'm wondering how are you using these classes in your Layered Applications.
I see advantages in having almost all the Interfaces using LocalDateTime (at the Service Layer at least) so that my Application doesn't have to manage Timezones and can safely assume Times always in UTC. My app could then use DateTime to manage Timezones at the very beginning of the Execution's Flow.
I'm also wondering in which scenario can DateMidnight be useful.

I see advantages in having almost all
the Interfaces using LocalDateTime (at
the Service Layer at least) so that my
Application doesn't have to manage
Timezones and can safely assume Times always in UTC.
I'm not sure I understand your line of thinking here. LocalDateTime and DateTime represent two quite different concepts. It's not the case that a LocalDateTime has some implicit UTC timezone: it actually has no timezone (internally it may be represented as a DateTime with UTC timezone, but it's just a implementation detail, it does not matter to the programmer who uses it).
You can see in the API docs that, while a DateTime is a "Instant" (a point in the world time line, a physical concept), a LocalDateTime is NOT such a thing. The LocalDateTime is actually a Partial, (a "civil" concept), in a different class hierarchy. The classes names might -unfortunately- make you think that LocalDateTime is some specialization of DateTime: well, it isn't.
A LocalDateTime should be regarded as a pair {Date (Y/M/D) ; Time (hh:mm:ss.msec)}, a bunch of numbers which corresponds to the "civil" standard representation of time-related data. If we are given a LocalDateTime, we cannot convert it directly to a DateTime, we need to specify a timezone; and that conversion takes we to another kind of entity. (An analogy: Strings and byte streams in Java: to convert between them you must specify a charset encoding, because they are conceptually different things)
When to use one or the other in the application... it's sometimes arguable, but frequently is clear enough, once the Jodatime concepts are understood. And IMO is not much related to "layers", perhaps more to use cases or scenarios.
A non-trivial -borderline- example: You work at Google, programming the Calendar. You must let the user manage (add, see, modify) an event which includes a date-time (lets ignore recurrent events), say "I have an appointement with my doctor on 2019-July-3 at 10:00 am". What is the time-date entity to use in the software layer (for this usecase)? I'd say: a LocalDateTime. Because the user is not really dealing with a physical point in time, but with a civil time: the date and time that displays the clock in his wrist or in his home. He does not even think of timezones (lets ignore the special case of a user who is traveling around the world...) Then, in the bussiness and presentation layer, a LocalDateTime seems the right entity.
But suppose that you must also code a different scenario: a reminder. When the Google internal scheduler detects that the event stored by the user is N minutes in the future from now, it must send him a reminder. Here, "N minutes from now" is a totally "physical" concept of time, so here the "business layer" would deal with a DateTime. There are several alternatives, for example: the event was stored in the DB as a LocalDateTime (ie. just time and date without timezone - one frequently uses a UTC timestamp to represent that, but this an implementation detail). In this scenario (only in this) we must load it as a DateTime, we convert it using a Timezone, probably from the user's profile.

The Answer by leonbloy is correct and vitally important. I am merely translating to the java.time classes that replace the Joda-Time project.
java.time
Specific moment
For a specific moment on the timeline:
Always in UTC is represented by Instant.
Assigned an offset-from-UTC is represented by OffsetDateTime.
Assign a full time zone rather than mere offset is represented by ZonedDateTime.
These all replace the Instant & DateTime class in Joda-Time. These java.time classes all have a resolution of nanoseconds versus the milliseconds used by Joda-Time.
Midnight versus Start-of-day
For midnight, the Joda-Time project concluded “midnight” is a vague and unproductive concept. The midnight-related classes and midnights were all deprecated in later versions of Joda-Time, replaced with the practical concept of “first moment of the day”.
The java.time classes took the same lesson, using a "first moment of the day" approach. Look for atStartOfDay methods on java.time classes such as LocalDate.
Never assume a day starts at 00:00. Anomalies such as Daylight Saving Time (DST) mean the day may start at other times such as 01:00.
ZonedDateTime zdt =
LocalDate.of( 2017 , Month.MARCH , 12 ) // Instantiate a date-only value without time zone.
.atStartOfDay( ZoneId.of( "America/Havana" ) ) ; // Cuba jumps from 00:00 to 01:00 on Spring DST cut-over.
For example, see how Cuba starts the day at 1 AM on their Spring DST cut-over.
zdt: 2017-03-12T01:00-04:00[America/Havana]
Unzoned
For representing the vague idea of possible moments over a range of about 26-27 hours but not an actual moment on the timeline, use LocalDateTime. This class purposely lacks any offset-from-UTC or time zone.
LocalDateTime ldt = LocalDateTime.of( 2017 , Month.JANUARY , 23 , 1 , 2 , 3 , 0 ) ;
If your business context implies a specific time zone, you can apply it to get a ZonedDateTime.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Determine a specific point on timeline by providing the context of a time zone.
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.
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
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.

Related

Timestamps and time zone conversions in Java and MySQL

I'm developing a Java application with a MySQL database on a server located in a different time zone from mine, and I am trying to decide between using DATETIME or TIMESTAMP on my database.
After reading questions like Should I use field 'datetime' or 'timestamp'?, and the MySQL documentation, I decided TIMESTAMP was better for me as it converts values to UTC for storage, and back to the current time zone for retrieval.
Also, as user Jesper explains in this thread, java.util.Date objects are internally only a UTC timestamp (i.e. number of milliseconds since the Epoch), and when you do a toString() it is displayed according to your current time zone.
For me, that looks like a good practice: storing datetimes as UTC timestamps, and then displaying them according to the current time zone.
I was about to do it like that, but then I found this from the Java documentation for Prepared Statements and got very confused:
void setTimestamp(int parameterIndex,
Timestamp x,
Calendar cal)
throws SQLException
Sets the designated parameter to the given java.sql.Timestamp value,
using the given Calendar object. The driver uses the Calendar object
to construct an SQL TIMESTAMP value, which the driver then sends to
the database. With a Calendar object, the driver can calculate the
timestamp taking into account a custom timezone. If no Calendar object
is specified, the driver uses the default timezone, which is that of
the virtual machine running the application.
Before this, I thought timestamps were by convention always in UTC. Why on earth would anyone want a localized timestamp instead of a localized representation of it? Wouldn't that be very confusing for everyone?
How do these conversions work? If Java takes an UTC timestamp and converts it to an arbitrary time zone, how can it tell MySQL in which timezone it is?
Won't MySQL assume that this timestamp is in UTC and then retrieve an incorrect localized value?
Date-Time Handling Is A Mess
The first paragraph in the answer by Teo is quite insightful and correct: Date-time handling in Java is a mess. Ditto for all other languages & development environments that I know of. Date-time work is difficult and tricky, especially error-prone and frustrating because we think it of date-time intuitively. But "intuitively" does not cut it when it comes to data types, databases, serialization, localization, adjusting across time zones, and all the other formalities that come with computer programming.
Unfortunately, the computer industry basically chose to ignore this problem of date-time work. Just as Unicode took too long to be invented given the obvious need, so too has the industry kicked the can down the road on solving the problem of date-time handling.
Do Not Rely On Count-Since-Epoch
But I must disagree with its conclusion. Working with a count-since-epoch is not the best solution. Using count-since-epoch is inherently confusing and error-prone and incompatible.
Humans cannot read a long number and decipher that as a date-time. So verifying data and debugging becomes complicated, to say the least.
What "count" would you use? The milliseconds used by java.util.Date and by Joda-Time? The microseconds used by Postgres, MySQL, and other databases? The nanoseconds used by the new java.time package in Java 8?
Which epoch would you use? The Unix epoch of the beginning of 1970 in UTC is common, but far from singular. Almost two dozen epochs have been used by various computer systems.
We create numeric data types for doing math rather than using bits. We create string classes to handle the nitty-gritty details of handling text rather than bare octets. So too we should create data-types and classes to handle date-time values.
The early Java teams (and IBM & Taligent before them) made an attempt with the java.util.Date and java.util.Calendar and related classes. Unfortunately, the attempt was inadequate. While date-time is inherently confusing, these classes have added even more confusion.
Joda-Time
As far as I know, the Joda-Time project was the first project to take on date-time in a thorough, competent, and successful manner. Even so, the creators of Joda-Time were not entirely satisfied. They went on to create the java.time package in Java 8, and extend that work with the threeten-extra project. Joda-Time and java.time share similar concepts but are distinct, each having some advantages.
Database Problems
Specifically, the java.util.Date & .Calendar classes lack date-only values without time-of-day and time zone. And they lack time-only values without date and time zone. Before Java 8, the Java team added the hacks known as the java.sql.Date and java.sql.Time classes which is a date-time value masquerading as a date-only. Both Joda-Time and java.time rectify that by offering LocalDate and LocalTime classes.
Another specific problem is that java.util.Date has a resolution of milliseconds, but databases frequently use microseconds or nanoseconds. In an ill-advised attempt to bridge this disparity, the early Java team created another hack, the java.sql.Timestamp class. While technically a java.util.Date subclass, it also tracks the fractional seconds to nanosecond resolution. So when converting in and out of this type you may losing or gaining the finer fractional seconds granularity without being conscious of that fact. So that might mean that values you expect to be equal are not.
Another source of confusion is the SQL data type, TIMESTAMP WITH TIME ZONE. That name is a misnomer as the time zone info is not stored. Think of the name as TIMESTAMP WITH RESPECT FOR TIME ZONE as any passed time zone offset info is used in converting the date-time value to UTC.
The java.time package with its nanosecond resolution has some specific features to better communicate date-time data with a database.
I could write much more, but such information can be gleaned from searching StackOverflow for words such as joda, java.time, sql timestamp, and JDBC.
Example using Joda-Time with JDBC with Postgres. Joda-Time uses immutable objects for thread-safety. So rather than alter an instance ("mutate"), we create a fresh instance based on the values of the original.
String sql = "SELECT now();";
…
java.sql.Timestamp now = myResultSet.getTimestamp( 1 );
DateTime dateTimeUtc = new DateTime( now , DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
Focus On UTC
Before this, I thought timestamps were by convention always in UTC. Why on earth would anyone want a localized timestamp instead of a localized representation of it? Wouldn't that be very confusing for everyone?
Indeed. The SQL standard defines a TIMESTAMP WITHOUT TIME ZONE which ignores and strips away any included time zone data. I cannot imagine the usefulness of that. This Postgres expert, David E. Wheeler, says as much in recommending always using TIMESTAMP WITH TIME ZONE. Wheeler cites one narrow technical exception (partitioning) and even then says to convert all the values to UTC yourself before saving to the database.
The best practice is to work and store data in UTC while adjusting to localized time zones for presentation to the user. There may be times when you want to remember the original date-time data in its localized time zone; if so, save that value in addition to converting to UTC.
Guidelines
The first steps to better date-time handling are avoiding java.util.Date & .Calendar, using Joda-Time and/or java.time, focusing on UTC, and learning the behavior of your specific JDBC driver and your specific database (databases vary widely in their date-time handling despite the SQL standard).
MySQL
Caveat: I don’t use MySQL (I'm a Postgres kind of guy).
According to the version 8 documentation, the two types DATETIME and TIMESTAMP differ in that the first one lacks any concept of time zone or offset-from-UTC. The second one uses any indication of time zone or offset-from-UTC accompanying an input to adjust that value to UTC, then stores it, and discards the zone/offset info.
So these two types seem to be akin to the standard SQL types:
MySQL DATETIME ≈ SQL-standard TIMESTAMP WITHOUT TIME ZONE
MySQL TIMESTAMP ≈ SQL-standard TIMESTAMP WITH TIME ZONE
For MySQL DATETIME, use the Java class LocalDateTime. That class, like that data type, purposely lacks any concept of time zone or offset-from-UTC. Use this type and class for either:
When you mean any zone or all zones, such as “Christmas starts on first moment of December 25, 2018”. That translates to different moments in different places as a new day dawns earlier in the east than in the west.
When scheduling appointments or events far enough out in the future that politicians may change the offset of the time zone, for which politicians around the world have shown a proclivity. In this usage, you must at runtime apply a time zone to dynamically calculate, but not store, a moment for display on a calendar. That way, a 15:00 dental appointment in 8 months remains at 15:00 even if politicians redefine the clock to be minutes/hours ahead or behind.
For MySQL TIMESTAMP, use the Java class Instant, as shown above. Use this type and class for moments, specific point on the timeline.
JDBC 4.2
As of JDBC 4.2 and later, we can directly exchange java.time objects with the database. Use getObject & setObject methods.
myPreparedStatement.setObject( … , Instant.now() ) ;
Retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
The JDBC 4.2 specification requires a driver to support OffsetDateTime but strangely does not require support for the more common types Instant and ZonedDateTime. But converting between types is quite easy.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
You can then adjust that UTC value in Instant to a specific time zone for presentation to a user.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.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.
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, Java SE 10, 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.
Your question is spot on a problem which i think is huge these days. Both DB (via SQL) and server side itself (via programming languages such as Java) offer a compendium of ways of dealing with date and time. I would qualify the status-quo as highly non-standardized and a bit chaotic (personal opinion :)
My answer is partial but i'll explain why.
You're correct, Java's Date (and Calendar) store time as milliseconds since the Unix Epoch (which is great). It happens not only in Java but in other programming languages as well. In my opinion the perfect time-keeping architecture emerges naturally from this: the Unix Epoch is January 1st, 1970, midnight, UTC. Therefore if you choose to store time as milliseconds since the Unix Epoch you have a lot of benefits:
architecture clarity: server side works with UTC, client side shows the time through its local timezone
database simplicity: you store a number (milliseconds) rather than complex data structures like DateTimes
programming efficiency: in most programming languages you have date/time objects capable of taking milliseconds since Epoch when constructed (which as you said, allows for automatic conversion to client-side timezone)
I find code and architecture is much simpler and more flexible when using this approach. I stopped trying to understand things like DateTime (or Timestamp) and only deal with them when i have to fix legacy code.

Recommended use for Joda-Time's DateMidnight

The javdoc for LocalDate#toDateMidnight reads as follows:
As from v1.5, you are recommended to avoid DateMidnight and use
toDateTimeAtStartOfDay() instead because of the exception detailed
below.
This method will throw an exception if the default time zone switches
to Daylight Savings Time at midnight and this LocalDate represents
that switchover date. The problem is that there is no such time as
midnight on the required date, and as such an exception is thrown.
The fact that midnight does not exist in certain time zones seems like reason enough to avoid using DateMidnight entirely (assuming your code is not using a fixed time zone that is known not to have this DST situation and will never need to use different time zones in the future).
However, DateMidnight is not deprecated and there is no similar recommendation or warning in the javadoc for the DateMidnight class itself. Furthermore, the DateMidnight constructor happily accepts an instant and time zone such that midnight does not exist on the given day, rather than throwing an IllegalArgumentException like LocalDate#toDateMidnight. The resulting DateMidnight behaves like a DateTime with time at start of day.
When midnight does not exist on a given day, why does LocalDate#toDateMidnight throw an exception while the DateMidnight constructor does not? What is the recommended use case for DateMidnight if any?
There is no good reason to use DateMidnight. LocalDate is the better option. Thats because midnight does not occur once a year in certain time-zones, completely messing up the usability of the class, and creating bugs in applications.
The constructor was fixed to avoid the worst problem, however seeing a DateMidnight object with the internal millisecond value pointing at 01:00 isn't exactly great.
new DateTime().withTimeAtStartOfDay() is recommended.
Or better use the LocalDate method toDateTimeAtStartOfDay directly to bypass creation of DateTime object (in relation to answer above).
new LocalDate().toDateTimeAtStartOfDay( myDateTimeZone )
tl;dr
Use java.time classes, specifically LocalDate::atStartOfDay instead of the slippery idea of “midnight”.
ZoneId z = ZoneId.of( "America/Montreal" ); // A time zone.
ZonedDateTime todayStart = LocalDate.now( z ).atStartOfDay( z ); // Produces a LocalDate (a whole day without time zone), then transforms into a `ZonedDateTime` (a moment on the timeline)
java.time
Since the Joda-Time project is now in maintenance mode, and the team advises migration to the java.time classes, I will add example using java.time.
If you want to represent the entire day as a whole, use the LocalDate class. The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( “America/Montreal” );
LocalDate today = LocalDate.now( z );
As discussed on this page, trying to pinpoint the end of the day is poor practice. For one thing, you have the problem of an infinitely divisible fraction for that last second of the day. Do you resolve to milliseconds, microseconds, nanoseconds, or something else, as all of these are in common use? Instead use the first moment of the new day.
Let java.time determine the wall-clock time of that first moment of the day. Do not assume the time will be 00:00:00 as anomalies such as Daylight Saving Time (DST) may mean the first moment is a time such as 01:00:00. Such DST adjustments are currently use in time zones of multiple countries.
So, to get a moment, an actual point on the timeline, for the start of the day call LocalDate::atStartOfDay. Notice this is a shorter version of the method name than used in Joda-Time’s withTimeAtStartOfDay method. Specify the desired/expected time zone in a ZoneId to produce a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = today.atStartOfDay( z );
Half-Open
So how to represent a span of time? If I want to pinpoint the the beginning and ending of this single day, how do I do that while also following this advice? The solution commonly used in date-time work is the Half-Open approach. In this approach, the beginning of the span is inclusive while the ending is exclusive. So “today” means starting with the first moment of the day and running all the way up to, but not including, the first moment of the following day.
ZonedDateTime zdtStartToday = LocalDate.now( z ).atStartOfDay( z );
ZonedDateTime zdtStartTomorrow = zdtStartToday.plusDays( 1 );
By the way, the ThreeTen-Extra project has a handy Interval class for such spans of time.
Interval todayInterval = Interval.of(
zdtStartToday.toInstant() ,
zdtStartTomorrow.toInstant()
)
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, 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.
Look at the exception i had in my code
Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman)
org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman)
Now i solved it by using
LocalDate currentDate=new LocalDate();
someMethodSetsTheDate(currentDate.toDateTimeAtStartOfDay().toDate());
Instead of
someMethodSetsTheDate(new DateMidnight(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()).toDate());
Now my recommendation is to use
.toDateTimeAtStartOfDay()
to avoid similar exceptions .
Please Feel Free To Edit My Answer Thanks
Here a more simple solution that will check if the dateTime occurs at midnight local time
private boolean isAtMidnight(org.joda.time.DateTime dateTime) {
return dateTime.toLocalDateTime().getMillisOfDay() == 0;
}

Time zone in Java

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

What is the Best Practice for manipulating and storing dates in Java? [duplicate]

This question already has answers here:
Java Best Practice for Date Manipulation/Storage for Geographically Diverse Users
(2 answers)
Closed 1 year ago.
What is the best practice for manipulating and storing Dates e.g. using GregorianCalendar in an enterprise java application?
Looking for feedback and I will consolidate any great answers into a best practice that others can use.
The best practice is usually precisely NOT to think in term of heavy date objects but to store a point in time. This is typically done by storing a value that doesn't suffer from corner cases nor from potential parsing problems. To do this, people usually store the number of milliseconds (or seconds) elapsed since a fixed point that we call the epoch (1970-01-01). This is very common and any Java API will always allow you to convert any kind of date to/from the time expressed in ms since the epoch.
That's for storage. You can also store, for example, the user's preferred timezone, if there's such a need.
Now such a date in milliseconds, like:
System.out.println( System.currentTimeMillis() );
1264875453
ain't very useful when it's displayed to the end user, that's for granted.
Which is why you use, for example, the example Joda time to convert it to some user-friendly format before displaying it to the end-user.
You asked for best practice, here's my take on it: storing "date" objects in a DB instead of the time in milliseconds is right there with using floating point numbers to represent monetary amounts.
It's usually a huge code smell.
So Joda time in Java is the way to manipulate date, yes. But is Joda the way to go to store dates? CERTAINLY NOT.
Joda is the way to go. Why ?
it has a much more powerful and intuitive interface than the standard Date/Time API
there are no threading issues with date/time formatting. java.text.SimpleDateFormat is not thread-safe (not a lot of people know this!)
At some stage the Java Date/Time API is going to be superseded (by JSR-310). I believe this is going to be based upon the work done by those behind Joda, and as such you'll be learning an API that will influence a new standard Java API.
Joda time (100% interoperable with the JDK)
Joda-Time provides a quality replacement for the Java date and time classes. The design allows for multiple calendar systems, while still providing a simple API
UTC
Think, work, and store data in UTC rather than any time zone. Think of UTC as the One True Time, and all other time zones are mere variations. So while coding, forget all about your own time zone. Do your business logic, logging, data storage, and data exchange in UTC. I suggest every programmer keep a second clock on their desk set to UTC.
java.time
The modern way is the java.time classes.
The mentioned Joda-Time project provided the inspiration for the java.time classes, and the project is now in maintenance mode with the team advising migration to java.time classes.
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, & java.text.SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
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.
ISO 8601
When serializing a date-time value to text, use the ISO 8601 standard.
For example, a date-time in UTC is 2016-10-17T01:24:35Z where the Z is short for Zulu and means UTC. For other offset-from-UTC the offset of hours and minutes appears at the end such as 2016-01-23T12:34:56+05:30. The java.time classes extend this standard format to append the name of the time zone (if known) in square brackets, such as 2016-01-23T12:34:56+05:30[Asia/Kolkata].
The standard has many other handy formats as well including for durations, intervals, ordinals, and year-week.
Database
For database storage, use date-time types for date-time values, such as the SQL standard data types which are primarily DATE, TIME, and TIMESTAMP WITH TIME ZONE.
Let your JDBC driver do the heavy lifting. The driver handles the nitty-gritty details about mediating and adapting between the internals of how Java handles the data and how your database handles the data on its side. But be sure to practice with example data to learn the behaviors of your driver and your database. The SQL standard defines very little about date-time handling and so behaviors vary widely, surprisingly so.
If using a JDBC driver compliant with JDBC 4.2 and later, you can fetch and store java.time types directly via the ResultSet::getObject and PreparedStatement::setObject methods.
Instant instant = myResultSet.getObject( … );
myPreparedStatement.setObject( … , instant );
For older drivers, you will need to fall back to converting through the java.sql types. Look for new conversion methods added to the old classes. For example, java.sql.Timestamp.toInstant().
Instant instant = myResultSet.getTimestamp( … ).toInstant();
myPreparedStatement.setObject( … , java.sql.Timestamp.from( instant ) );
Use the java.sql types as briefly as possible. They are a badly designed hack, such as java.sql.Date masquerading as a date-only value but actually as a subclass of java.util.Date it does indeed have a time-of-day set to the 00:00:00 in UTC. And, oh, you are supposed to ignore the fact of that inheritance says the class doc. An ugly mess.
Example code
Get the current moment in UTC.
Instant instant = Instant.now();
Storing and fetching that Instant object to/from a database is shown above.
To generate an ISO 8601 string, merely call toString. The java.time classes all use ISO 8601 formats by default for parsing and generating strings of their various date-time values.
String output = instant.toString();
Adjust into any offset-from-UTC by applying a ZoneOffset to get an OffsetDateTime. Call toString to generate a String in ISO 8601 format.
ZoneOffset offset = ZoneOffset.ofHoursMinutes( 5 , 30 );
OffsetDateTime odt = instant.atOffset( offset );
A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST). When you need to see that same moment through the lens of some region’s own wall-clock time, apply a time zone (ZoneId) to get a ZonedDateTime object.
Specify a proper time zone name in the format of continent/region. 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" );
ZonedDateTime zdt = instant.atZone( z );
Going the other direction, you can extract an Instant from an OffsetDateTime or ZonedDateTime by calling toInstant.
Instant instant = zdt.toInstant();
Formatting
For presentation to the user as strings in formats other than ISO 8601, search Stack Overflow for use of the DateTimeFormatter class.
While you can specify an custom format, usually best to let java.time automatically localize. To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
Example:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );
Conversion
Best to avoid the legacy date-time types whenever possible. But if working with old code not yet updated for the java.time types, you can convert to/from the java.time types. For details, see the Question, Convert java.util.Date to what “java.time” type?.
Use objects
Use objects rather than mere coded primitives and simple strings. For example:
Do not use 1-7 to represent a day-of-week, use the DayOfWeek enum such as DayOfWeek.TUESDAY.
Rather than passing around a string as a date, pass around LocalDate objects.
Rather than pass around a pair of integers for a year-and-month, pass around YearMonth objects.
Instead of 1-12 for a month, use the much more readable Month enum such as Month.JANUARY.
Using such objects makes your code more self-documenting, ensures valid values, and provides type-safety.
To get the discussion started, here's been my experience:
When creating standards for a typical 3-tier Java Enterprise project, I would generally recommend that the project use GregorianCalendar for manipulating dates. Reason is GregorianCalendar is the de facto standard over any other Calendar instance e.g. Julian calendar etc. It's the recognized calendar in most countries and properly handles leap years, etc. On top of that, I would recommend that the application store its dates as UTC so that you can easily perform date calculations such as finding the difference between two dates (if it were stored as EST for example, you'd have to take day light savings time into account). The date can be then be localized to whatever timezone you need it to be displayed to the user as -- such as localizing it to EST if you are an east-coast US company and you want your time information shown in EST.

Grouping Long UTC dates by Day

Is there a sensible way to group Long UTC dates by Day?
I would Mod them by 86400 but that doesn't take leap seconds into account.
Does anyone have any other ideas, I'm using java so I could parse them into Date Objects, but I'm a little worried of the performance overhead of using the date class.
Also is there a more efficient way than comparing the year month and day parts of a Date object?
Does your source data definitely include leap seconds to start with? Some APIs do, and some don't - Joda Time (which I'd recommend over the built-in date/time APIs) doesn't use leap seconds, for example. The Java date and time APIs "sometimes" do - they support 60 and 61 as values of "second in minute" but support depends on the operating system (see below). If you have some good sample values, I'd check that first if I were you. Obviously just dividing is rather simpler than anything else.
If you do need to create Date objects (or DateTime in Joda) I would benchmark it before doing anything else. You may well find that the performance is actually perfectly adequate. There's no point in wasting time optimizing something which is okay for your data. Of course, you'll need to decide data size you need to support, and how quick it needs to be first :)
Even the java.util.Date support for leap seconds is somewhat indeterminate. From the docs:
Although the Date class is intended to
reflect coordinated universal time
(UTC), it may not do so exactly,
depending on the host environment of
the Java Virtual Machine. Nearly all
modern operating systems assume that 1
day = 24 × 60 × 60 = 86400 seconds in
all cases. In UTC, however, about once
every year or two there is an extra
second, called a "leap second." The
leap second is always added as the
last second of the day, and always on
December 31 or June 30. For example,
the last minute of the year 1995 was
61 seconds long, thanks to an added
leap second. Most computer clocks are
not accurate enough to be able to
reflect the leap-second distinction.
There's a rather good blog post about the mess with Java and leap seconds which you may want to read too.
I would Mod them by 86400 but that doesn't take leap seconds into account....
I'm pretty sure that that will be fine. The API documentation for Date really shouldn't include anything about leap seconds, because the fact is that it emulates a standard Unix time ticker which does NOT include leap seconds in its value.
What it does instead is to have a 59th second that lasts for two seconds by setting the ticker value back by 1 second at the start of a leap second (as the link in the previous post describes).
Therefore you can assume that the value you get from Date.getTime() IS made up only of 86400-second days. If you really need to know whether a particular day had a leap second, there are several tables available on the Internet (there have only been 23-24 since 1972, and computer dates before that rarely took them into account anyway).
HIH
Winston
tl;dr
Instant.ofEpochSecond( 1_493_367_302L ) // Convert a count of whole seconds from epoch of 1970 into a date-time value in UTC.
.atZone( ZoneId.of( "Pacific/Auckland" ) ) // Adjust into the time zone as a context for determining a date.
.toLocalDate() // Extract a date-only value by which we can sort/collect/organize our date-time values.
Time zone
The java.util.Date class represents a moment on the timeline in UTC. So asking it for a date gets you a date that only makes sense in UTC. That very same moment may be a date earlier in Québec or a date later in Auckland, New Zealand.
Time zone is crucial in determining a date, and your Question ignores this issue.
Using java.time
The java.util.Date class is part of the troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
As for leap seconds, as the other Answers suggested, most sources of count-from-epoch do not count leap seconds. So verify your source.
If you have a count of whole seconds from epoch of 1970-01-01T00:00:00, then use the static method to create a Instant object.
Instant instant = Instant.ofEpochSecond( 1_493_367_302L ) ;
instant.toString(): 2017-04-28T08:15:02Z
Assign a time zone to create the context in which we can determine a date. For any given moment, the date varies around the world by 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( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
zdt.toString(): 2017-04-28T01:15:02-07:00[America/Los_Angeles]
With of bunch of these ZonedDateDate objects, you can compare by date. You can extract a LocalDate object. The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = zdt.toLocalDate();
ld.toString(): 2017-04-28
So you could make a Map with LocalDate as the key and an List or Set of ZonedDateTime objects as the value. And with the modern lambda syntax, you could use Streams to do that mapping.
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.
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
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.

Categories

Resources