Could someone please advise the current "best practice" around Date
and Calendar
types.
When writing new code, is it best to always favour Calendar
over Date
, or are there circumstances where Date
is the more appropriate datatype?
Could someone please advise the current "best practice" around Date
and Calendar
types.
When writing new code, is it best to always favour Calendar
over Date
, or are there circumstances where Date
is the more appropriate datatype?
I generally use Date if possible. Although it is mutable, the mutators are actually deprecated. In the end it basically wraps a long that would represent the date/time. Conversely, I would use Calendars if I have to manipulate the values.
You can think of it this way: you only use StringBuffer only when you need to have Strings that you can easily manipulate and then convert them into Strings using toString() method. In the same way, I only use Calendar if I need to manipulate temporal data.
For best practice, I tend to use immutable objects as much as possible outside of the domain model. It significantly reduces the chances of any side effects and it is done for you by the compiler, rather than a JUnit test. You use this technique by creating private final fields in your class.
And coming back to the StringBuffer analogy. Here is some code that shows you how to convert between Calendar and Date
With Java 8, the new java.time package should be used.
Objects are immutable, time zones and day light saving are taken into account.
You can create a
ZonedDateTime
object from an oldjava.util.Date
object like this:I always advocate Joda-time. Here's why.
EDIT: The Java date/time classes introduced with Java 8 are now the preferred solution, if you can migrate to Java 8
I use Calendar when I need some specific operations over the dates like moving in time, but Date I find it helpful when you need to format the date to adapt your needs, recently I discovered that Locale has a lot of useful operations and methods.So I'm using Locale right now!
tl;dr
Avoid these legacy classes entirely. Use java.time classes instead.
Instant
(the modern equivalent of
Date
)ZonedDateTime
(the modern equivalent of
GregorianCalendar
)OffsetDateTime
(no equivalent in legacy classes)
LocalDateTime
(no equivalent in legacy classes)
Details
The Answer by Ortomala Lokni is right to suggest using the modern java.time classes rather than the troublesome old legacy date-time classes (
Date
,Calendar
, etc.). But that Answer suggests the wrong class as equivalent (see my comment on that Answer).Using java.time
The java.time classes are a vast improvement over the legacy date-time classes, night-and-day difference. The old classes are poorly-designed, confusing, and troublesome. You should avoid the old classes whenever possible. But when you need to convert to/from the old/new, you can do so by calling new methods add to the old classes.
For much more information on conversion, see my Answer and nifty diagram to another Question, Convert java.util.Date to what “java.time” type?.
Searching Stack Overflow gives many hundreds of example Questions and Answers on using java.time. But here is a quick synopsis.
Instant
Get the current moment with an
Instant
. TheInstant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).ZonedDateTime
To see that same simultaneous moment through the lens of some particular region’s wall-clock time, apply a time zone (
ZoneId
) to get aZonedDateTime
.Time zone
Specify a proper time zone name in the format of
continent/region
, such asAmerica/Montreal
,Africa/Casablanca
, orPacific/Auckland
. Never use the 3-4 letter abbreviation such asEST
orIST
as they are not true time zones, not standardized, and not even unique(!).Offset
A time zone is a region’s history of changes in its offset-from-UTC. But sometimes you are given only an offset without the full zone. In that case, use the
OffsetDateTime
class.Use of a time zone is preferable over use of a mere offset.
LocalDateTime
The “Local” in the
Local…
classes means any locality, not a particular locality. So the name can be counter-intuitive.LocalDateTime
,LocalDate
, andLocalTime
purposely lack any information about offset or time zone. So they do not represent actual moments, they are not points on the timeline. When in doubt or in confusion, useZonedDateTime
rather thanLocalDateTime
. Search Stack Overflow for much more discussion.Strings
Do not conflate date-time objects with strings that represent their value. You can parse a string to get a date-time object, and you can generate a string from a date-time object. But the string is never the date-time itself.
Learn about standard ISO 8601 formats, used by default in the java.time classes.
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?
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.Btw "date" is usually tagged as "obsolete / deprecated" (I dont know exactly why) - something about it is wrote there Java: Why is the Date constructor deprecated, and what do I use instead?
It looks like it's a problem of the constructor only- way via new Date(int year, int month, int day), recommended way is via Calendar and set params separately .. (Calendar cal = Calendar.getInstance(); )