When you look at the javadoc of the java.util.Date class, most of the methods are deprecated. Why was this done?
Well, for two related reasons. It was a very poor implementation of the concept of Dates and Times and it was replaced by the Calendar class.
The Calendar class, although an improvement, leaves a lot to be desired as well, so for serious Date/Time work, everyone recommends Joda-Time. Java 8 brings the new java.time.* package, inspired by Joda-Time, defined by JSR-310, and intended to supplant the old Date/Calendar classes.
Edit: In response to the specific question of why the implementation is poor, there are many reasons. The JavaDoc sums it up as follows:
Unfortunately, the API for these functions was not amenable to internationalization.
In addition to this general deficiency (which covers issues like the lack of a Time Zone component as well as the date formatting which is better handled in DateFormat and the inability to have a non-Gregorian calendar representation), there are specific issues which really hurt the Date class, including the fact that year is presented in an offset of 1900 from Common Era year.
Calendar has its own problems, but even as early as JDK 1.1 it was obvious that java.util.Date was not going to cut it. Even though Calendar is arguable the worst JDK API, it has taken until version 7 to attempt to address it.
Date is mutable
Date doesn't have support for time zones
The latter led to it being replaced by Calendar. And the former, combined with the ease-of-use, lead to both being replaced by Joda-Time / JSR-310 (java.time.* package)
They're deprecated because Date was written as fast as possible back in the day when they wanted to rush the JDK out the door.
It turns out the Dates and Calendars are Hard. So, they created the Calendar class, which much more thought, in order to handle the Hard Parts of working with calendars.
They deprecated the Date methods and delegated to Calendar because they didn't want to change the behavior of the existing Date methods, and possibly break existing applications.
Here's a good answer straight from Oracle: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.
For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive.
... java.util.Date represents an instant on the timeline—a wrapper around the number of milli-seconds since the UNIX epoch—but if you call toString(), the result suggests that it has a time zone, causing confusion among developers.
I don't know the official reason why it has been deprecated, but as far as I can tell GregorianCalendarand Joda-Time support operations on dates, meaning that you can add, for instance, a day to a date and have its month and year updated accordingly.
For instance, say you want to compute the day after the current date and today is May 31st; with java.util.Date, you just have getDays() +1, which returns 32, and you have to handle the knowledge that the current month doesn't have 32 days by yourself; with GregorianCalendaror Joda.time, adding a day to May 31st results in an object representing June 1st, hiding the complexity from your sight.
Related
I'm working on some legacy code where java.util.Calendar is used for date related calculations (basically adding months). Now I want to replace java.util.Calendar by java.time.LocalDate in the code but I don't want to change the behavior. So, I've been looking for a source which clarifies that they yield same result for the same calculation for any case but I can't find any.
Especially I want to know if is there a date that makes them yield a different result between:
Calendar#add(Calendar.MONTH, months)
and
LocalDate#plusMonth(months)
I've tested some corner cases (e.g. a leap year related dates) and they seem to yield the same result but I can't be 100% sure with that. Isn't there any official information about that or some known difference between them?
TL;DR
If:
You are sure that your Calendar is really a GregorianCalendar (by far the most commonly used subclass), and…
Your dates don’t go more than 100 years back, then…
…you can safely use LocalDate#plusMonth(months) instead of Calendar#add(Calendar.MONTH, months).
Details
Congratulations on the decision to migrate from the old and poorly designed Calendar class to LocalDate from java.time, the modern Java date and time API. This will be an improvement to your code base.
You are correct, the methods you mention are used for the same purpose and generally work the same. So when you migrate from Calendar to java.time, if you find that LocalDate is the right new class to use, then you will use LocalDate#plusMonth(months) where you used Calendar#add(Calendar.MONTH, months) before.
Differences include:
The Calendar class is an abstract superclass for classes representing dates (and times) in many different calendar systems (Gregorian, Buddhist and more), a LocalDate is always in the proleptic Gregorian calendar. Since each calendar system has its own definition of what a month is, adding a number of months in a calendar other than the Gregorian calendar can give quite different results from what LocalDate.plusMonths gives you.
If your dates go back in history it will also make a minor difference that LocalDate uses the proleptic Gregorian calendar. This means that it doesn’t use the Julian calendar for dates where it was in use centuries ago.
While Calendar.add modifies the Calendar object that you call it on, LocalDate.plusMonths returns a new LocalDate object with the new date.
While for going backward in the calendar you need to pass a negative number of months to Calendar::add, LocalDate has a convenient minusMonths method that you will typically want to use instead of plusMonths (both work, though).
The range of dates that each class can represent is different. I don’t readily remember the minimum and maximum date for each. On Calendar/GregorianCalendar, see their various methods such as getGreatestMinimum & getLeastMaximum. For LocalDate, see the constants: MAX & MIN.
I know there are questions relating to java.util.Date and Joda-Time. But after some digging, I couldn't find a thread about the differences between the java.time API (new in Java 8, defined by JSR 310) and Joda-Time.
I have heard that Java 8’s java.time API is much cleaner and can do much more than Joda-Time. But I cannot find examples comparing the two.
What can java.time do that Joda-Time cannot?
What can java.time do better than Joda-Time?
Is the performance better with java.time?
Common features
a) Both libraries use immutable types. Joda-Time also offers additional mutable types like MutableDateTime.
b) Furthermore: Both libraries are inspired by the design study "TimeAndMoney" from Eric Evans or ideas from Martin Fowler about domain driven style so they strive more or less for a fluent programming style (although not always perfect ;-)).
c) With both libraries we get a real calendar date type (called LocalDate), a real wall time type (called LocalTime) and the composition (called LocalDateTime). That is a very big win compared with old java.util.Calendar and java.util.Date.
d) Both libraries use a method-centric approach meaning they encourage the user to use getDayOfYear() instead of get(DAY_OF_YEAR). This causes a lot of extra methods compared with java.util.Calendar (although latter is not type-safe at all due to excessive use of ints).
Performance
See the other answer by #OO7 pointing to the analysis of Mikhail Vorontsov although point 3 (exception catching) is probably obsolete - see this JDK-bug. The different performance (which is in general favour of JSR-310) is mainly due to the fact that the internal implementation of Joda-Time always use a machine-time-like long-primitive (in milliseconds).
Null
Joda-Time often use NULL as default for system timezone, default locale, current timestamp etc. while JSR-310 almost always rejects NULL values.
Precision
JSR-310 handles nanosecond precision while Joda-Time is limited to millisecond precision.
Supported fields:
An overview about supported fields in Java-8 (JSR-310) is given by some classes in the temporal-package (for example ChronoField and WeekFields) while Joda-Time is rather weak on this area - see DateTimeFieldType. The biggest lack of Joda-Time is here the absence of localized week-related fields. A common feature of both field implementation design is that both are based on values of type long (no other types, not even enums).
Enum
JSR-310 offers enums like DayOfWeek or Month while Joda-Time does not offer this because it was mainly developed in years 2002-2004 before Java 5.
Zone API
a) JSR-310 offers more timezone features than Joda-Time. Latter is not able to yield a programmatical access to the history of timezone offset transitions while JSR-310 is capable to do this.
b) For your information: JSR-310 has moved its internal timezone repository to a new location and a different format. The old library folder lib/zi does not exist any more.
Adjuster vs. Property
JSR-310 has introduced the TemporalAdjuster-interface as a formalized way to externalize temporal calculations and manipulations, especially for library or framework-writers this is a nice and relative easy way to embed new extensions of JSR-310 (a kind of equivalent to static helper classes for former java.util.Date).
For most users however, this feature has very limited value because the burden to write code is still with the user. Built-in solutions based on the new TemporalAdjuster-concept are not so many, there is currently only the helper class TemporalAdjusters with a limited set of manipulations (and the enums Month or other temporal types).
Joda-Time offers a field-package but practice has shown evidence that new field implementations are very hard to code. On the other side Joda-Time offers so-called properties which make some manipulations much easier and more elegant than in JSR-310, for example property.withMaximumValue().
Calendar systems
JSR-310 offers 4 extra calendar systems. The most interesting one is Umalqura (used in Saudi Arabia). The other 3 are: Minguo (Taiwan), Japanese (only the modern calendar since 1871!) and ThaiBuddhist (only correct after 1940).
Joda-Time offers an Islamic calendar based on calculatory base - not a sighting-based calendar like Umalqura. Thai-Buddhist is also offered by Joda-Time in a similar form, Minguo and the japanese one not. Otherwise Joda-Time offers coptic and ethiopic calendar, too (but without any support for internationalization).
More interesting for Europeans: Joda-Time also offers a Gregorian, Julian and mixed-gregorian-julian calendar. However, the practical value for real historical calculations is limited because important features like different year starts in date history are not supported at all (the same criticism is valid for old java.util.GregorianCalendar).
Other calendars like Hebrew or Persian or Hindu are completely missing in both libraries.
Epoch days
JSR-310 has the class JulianFields while Joda-Time (version 2.0) offers some helper methods in the class DateTimeUtils.
Clocks
JSR-310 has no interface (a design mistake) but an abstract class java.time.Clock which can be used for any clock dependency injection. Joda-Time offers the interface MillisProvider and some helper methods in DateTimeUtils instead. So this way Joda-Time is also capable of supporting test-driven models with different clocks (mocking etc.).
Duration arithmetic
Both libraries support the calculation of time distances in one or more temporal units. However, when handling single-unit-durations the JSR-310-style is obviously nicer (and long-based instead of using int):
JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);
Joda-Time => int days = DAYS.daysBetween(date1, date2).getDays();
Handling of multiple-unit-durations are also different. Even the calculation results can differ - see this closed Joda-Time issue. While JSR-310 use a very simple and limited approach to use just the classes Period (duration based on years, months and days) and Duration (based on seconds and nanoseconds), Joda-Time uses a more sophisticated way using the class PeriodType in order to control in which units a duration (Joda-Time call it "Period") shall be expressed. While the PeriodType-API is somehow awkward to use a similar way is not offered by JSR-310 at all. Especially it is not yet possible in JSR-310 to define mixed date and time durations (based on days and hours for example). So be warned if it comes to migration from one library to another. The libraries in discussion are incompatible - despite of partially same class names.
Intervals
JSR-310 does not support this feature while Joda-Time has limited support. See also this SO-answer.
Formatting and Parsing
Best way to compare both libraries is to view the equal-named classes DateTimeFormatterBuilder (JSR-310) and DateTimeFormatterBuilder (Joda-Time). The JSR-310-variant is a little bit more powerful (can also handle any kind of TemporalField provided the field implementor has managed to code some extension points like resolve()). Most important difference is however - in my opinion:
JSR-310 can much better parse timezone names (format pattern symbol z) while Joda-Time could not do this at all in its earlier versions and now only in a very limited way.
Another advantage of JSR-310 is support for standalone month names which is important in languages like Russian or Polish etc. Joda-Time has no access to such resources - not even on Java-8 platforms.
The pattern syntax in JSR-310 is also more flexible than in Joda-Time, allows for optional sections (using square brackets), is more orientated towards CLDR-standard and offers padding (letter symbol p) and more fields.
Otherwise it should be noted that Joda-Time can format durations using PeriodFormatter. JSR-310 cannot do this.
Hope this overview helps. All the gathered information is mainly there due to my efforts and investigations how to design and implement a better date-and-time library (nothing is perfect).
Update from 2015-06-24:
Meanwhile I have found the time to write and publish a tabular overview for different time libraries in Java. The tables also contain a comparison between Joda-Time v2.8.1 and Java-8 (JSR-310). It is more detailed than this post.
Java 8 Date/Time :
Java 8 classes are built around the human time. It makes them fast for human datetime arithmetics/conversion.
Date/time component getters like getDayOfMonth have O(1) complexity in Java 8 implementation.
Parsing of OffsetDateTime/OffsetTime/ZonedDateTime is very slow in Java 8 ea b121 due to exceptions thrown and caught internally in the JDK.
A set of packages: java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*, java.time.zone.*
Instants (timestamps) Date and Time Partial Date and Time Parser and Formatter Time zones Different chronologies (calendars).
Existing classes have issues like Date has no support for I18N or L10N. They are mutable!
Simpler & more robust.
Clocks can be injected.
Clocks can be created with various properties - Static clocks, Mocked clocks, Low-precision clocks (whole seconds, whole minutes, etc).
Clocks can be created with specific time zones. Clock.system(Zone.of("America/Los_Angeles")).
Makes code handling date and time testable.
Makes tests independent of timezone.
Joda-Time :
Joda-Time is using machine time inside. A manual implementation based on int/long values would be much faster.
Joda-Time getters require the computer-to-human time calculation on every getter call, which makes Joda-Time a bottleneck in such scenarios.
It is composed of immutable classes it handles Instants, Date & Time, Partials, and Durations It is flexible It is well designed.
Represents dates as instants. But a date&time may correspond to more than one instant. Overlap hour when daylight savings end. As well as not have any instant that corresponds to it at all. Gap hour when daylight starts. Has to perform complex computations for simple operations.
Accepts nulls as valid values on most of its methods. Leads to subtle bugs.
For more detailed comparision see :-
Java 8 Date/Time library performance (as well as Joda-Time 2.3 and j.u.Calendar). &
New Date & Time API in Java 8
Joda-Time is now in maintenance-mode
Not a direct answer to the question but the Joda-Time project is no longer in active development. The team suggests users migrate to the newer java.time API. See tutorial by Oracle.
From the official GitHub project page:
Joda-time is no longer in active development except to keep timezone
data up to date. From Java SE 8 onwards, users are asked to migrate to
java.time (JSR-310) - a core part of the JDK which replaces this
project. For Android users, java.time is added in API 26+. Projects
needing to support lower API levels can use the ThreeTenABP library.
The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package java.time.
https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html
The documentation for Date.getTimezoneOffset says:
Deprecated. As of JDK version 1.1, replaced by
-(Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000).
Why was it deprecated? Is there a shorter way (Apache Commons?) to get the offset from UTC in hours/minutes? I have a Date object ... should I convert it to JodaDate for this?
And before you ask why I want the UTC offset - it's just to log it, nothing more.
There are 2 questions here.
Why was Date.getTimezoneOffset deprecated?
I think it is because they actually deprecated nearly all methods of Date and moved their logic to calendar. We are expected to use generic set and get with the parameter that says which specific field we need. This approach has some advantages: less number of methods and the ability to run setters in a loop passing a different field each time. I personally used this technique a lot: it makes code shorter and easier to maintain.
Shortcut? But what's wrong with call
Calendar.get(Calendar.DST_OFFSET) comparing to
Calendar.getTimeZoneOffset()
As far as I can see the difference is 6 characters.
Joda is a very strong library and if you really have to write a lot of sophisticated date manipulation code switch to it. I personally use the standard java.util.Calendar and don't see any reason to use external libraries: good old calendar is good enough for me.
All of the date manipulation logic was moved out of Date once the Java implementers realized that it might need to be implemented differently for different types of calendars (hence the need to use a GregorianCalendar to retrieve this info now). A Date is now just a wrapper around a UTC time value.
Take care before you paste code from this page.
Perhaps just me but I believe that in order to get the tz offset in minutes you need to do
int tzOffsetMin = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET))/(1000*60);
rather than what the Javadoc says, which is:
int tzOffsetMin = -(cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET))/(1000*60);
Calendar.ZONE_OFFSET gives you the standard offset (in msecs) from UTC. This doesn't change with DST. For example for US East Coast timezone this field will always be -6 hours regardless of DST.
Calendar.DST_OFFSET gives you the current DST offset (in msecs) - if any. For example during summer in a country that uses DST this field is likely to have the value +1 hour (1000*60*60 msecs).
Previously, when I first design a stock application related software, I decide to use java.util.Date to represent date/time information of a stock.
Later, I realize most of the methods in java.util.Date is deprecated. Hence, very soon, I refactor all my code to make use of java.util.Calendar
However, there is 2 shortcomings I encounter.
Construct java.util.Calendar is comparative slower than java.util.Date
Within the accessors getCalendar method of Stock class, I need to clone a copy, as Calendar is a mutable class
Here is the current source code for Stock.java
Recently, I discover Joda-Time. I do the following benchmarking, by creating 1,000,000 java.util.Date, java.util.Calendar and org.joda.time.DateTime. I found org.joda.time.DateTime performs better than java.util.Calendar, during instantiation.
Here is the benchmarking result.
This instantiation speed is important, especially many instance of Stocks will be created, to represent a long price history of a stock.
Do you think is it worth to migrate from Java Calendar to Joda Date Time, to gain application speed performance? Is there any trap I need to pay attention to?
Note that java.util.Date is mutable too - so if it's a problem now you're using Calendar, it would have been a problem using Date too. That said, using Joda Time is definitely worth doing just because it's a much, much better API.
How certain are you that performance is actually an issue in your particular app? You say there will be "many instances" of Stock created... how many? Have you profiled it? I wouldn't expect it to actually make a significant difference in most situations. It's not obvious from your benchmarking graph what you're actually measuring.
Moving to Joda Time is a good idea in general, but I would measure the performance to see how much difference it really makes for you.
Why do you need a Calendar in your Stock class? I think using a Date to represent a point in time is fine. This seems to be what you want, because you want the Calendar object in the a stock to be immutable, which the Date class should be, if you ignore the deprecated methods.
You can use a temporary Calendar when you need to do time operations on a Date outside the Stock class:
Calendar calendar = Calendar.getInstance();
calendar.setTime(stock.getDate());
System.out.println(calendar.getYear());
Like this you can still store a Date in your Stock class, which should have the best performance when only store and retrieve Stock objects from a data storage. If you do several operations at once you can also reuse the same Calendar object.
If you don't like the Calendar interface you could still use Joda Time to do the time operations. You can probably convert dates to and from Joda Time if needed, to do time operations, and still store Date objects in your Stock class.
If java.util.Calendar instances to be replaced with org.joda.time.DateTime are parsed and/or formatted to a particular pattern, e.g.
String format = "YYYY-MM-dd HH:mm:ss";
Within method signatures for parameter and return types, as well as variable declarations
and instantiations, repace whole word occurrences of the class names Calendar (with
DateTime) and SimpleDateFormat (with DateTimeFormatter), respectively
Replace the formatter instantiation statement, e.g.
formatter = new SimpleDateFormat(format);
with
formatter = DateTimeFormat.forPattern(format);
Replace calls to methods of `SimpleDateFormat', e.g.
String dateStr = formatter.format(Calendar.getInstance().getTime());
with
String dateStr = DateTime.now().toString(formatter);
and
formatter.parse(dateStr);
with
DateTime.parse(dateStr, formatter);
I used Joda in the past, and it is an awesome library.
In terms of performance, you'll have to test it, unfortunately. But refactoring your code seems too much. Personally, I used Date throughout my whole application (including DB store and retrieve), and used Joda only when I needed data manipulation. Joda calculates fields only when needed, so I guess the overhead will be much lower than using Java API classes; furthermore, you won't have object version issues to transfer and handle Date objects in your DB, serialize objects and such. I don't expect Joda to break such compatibility, but it is less likely using Date.
It is always better to move to joda-time in general. But it it is really worth to move to the joda-time for your project is based on your use-cases pertaining to the date usage. Look at slide number 46 in the presentation for performance related numbers for some of the operationslink text
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?
Date is a simpler class and is mainly there for backward compatibility reasons. If you need to set particular dates or do date arithmetic, use a Calendar. Calendars also handle localization. The previous date manipulation functions of Date have since been deprecated.
Personally I tend to use either time in milliseconds as a long (or Long, as appropriate) or Calendar when there is a choice.
Both Date and Calendar are mutable, which tends to present issues when using either in an API.
The best way for new code (if your policy allows third-party code) is to use the Joda Time library.
Both, Date and Calendar, have so many design problems that neither are good solutions for new code.
Date and Calendar are really the same fundamental concept (both represent an instant in time and are wrappers around an underlying long value).
One could argue that Calendar is actually even more broken than Date is, as it seems to offer concrete facts about things like day of the week and time of day, whereas if you change its timeZone property, the concrete turns into blancmange! Neither objects are really useful as a store of year-month-day or time-of-day for this reason.
Use Calendar only as a calculator which, when given Date and TimeZone objects, will do calculations for you. Avoid its use for property typing in an application.
Use SimpleDateFormat together with TimeZone and Date to generate display Strings.
If you're feeling adventurous use Joda-Time, although it is unnecessarily complicated IMHO and is soon to be superceded by the JSR-310 date API in any event.
I have answered before that it is not difficult to roll your own YearMonthDay class, which uses Calendar under the hood for date calculations. I was downvoted for the suggestion but I still believe it is a valid one because Joda-Time (and JSR-310) are really so over-complicated for most use-cases.
tl;dr
advise the current "best practice" around Date and Calendar
is it best to always favour Calendar over Date
Avoid these legacy classes entirely. Use java.time classes instead.
For a moment in UTC, use Instant(the modern equivalent of Date)
For a moment in a particular time zone, use ZonedDateTime(the modern equivalent of GregorianCalendar)
For a moment in a particular offset-from-UTC, use OffsetDateTime(no equivalent in legacy classes)
For a date-time (not a moment) with unknown time zone or offset, use 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. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
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 a ZonedDateTime.
Time zone
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
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.
ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );
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, and LocalTime 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, use ZonedDateTime rather than LocalDateTime. 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?
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.
Date is best for storing a date object. It is the persisted one, the Serialized one ...
Calendar is best for manipulating Dates.
Note: we also sometimes favor java.lang.Long over Date, because Date is mutable and therefore not thread-safe. On a Date object, use setTime() and getTime() to switch between the two. For example, a constant Date in the application (examples: the zero 1970/01/01, or an applicative END_OF_TIME that you set to 2099/12/31 ; those are very useful to replace null values as start time and end time, especially when you persist them in the database, as SQL is so peculiar with nulls).
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
String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String
// immutable date with hard coded format. If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");
// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// mutate the value
cal.add(Calendar.YEAR, 1);
// convert back to Date
Date newDate = cal.getTime();
//
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);
Dates should be used as immutable points in time; Calendars are mutable, and can be passed around and modified if you need to collaborate with other classes to come up with a final date. Consider them analogous to String and StringBuilder and you'll understand how I consider they should be used.
(And yes, I know Date isn't actually technically immutable, but the intention is that it should not be mutable, and if nothing calls the deprecated methods then it is so.)
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 old java.util.Date object like this:
Date date = new Date();
ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
I always advocate Joda-time. Here's why.
the API is consistent and intuitive. Unlike the java.util.Date/Calendar APIs
it doesn't suffer from threading issues, unlike java.text.SimpleDateFormat etc. (I've seen numerous client issues relating to not realising that the standard date/time formatting is not thread-safe)
it's the basis of the new Java date/time APIs (JSR310, scheduled for Java 8. So you'll be using APIs that will become core Java APIs.
EDIT: The Java date/time classes introduced with Java 8 are now the preferred solution, if you can migrate to Java 8
A little bit late at party, but Java has a new Date Time API in JDK 8. You may want to upgrade your JDK version and embrace the standard. No more messy date/calendar, no more 3rd party jars.
Date should be re-developed. Instead of being a long interger, it should hold year, month, date, hour, minute, second, as separate fields. It might be even good to store the calendar and time zone this date is associated with.
In our natural conversation, if setup an appointment at Nov. 1, 2013 1pm NY Time, this is a DateTime. It is NOT a Calendar. So we should be able to converse like this in Java as well.
When Date is stored as a long integer (of mili seconds since Jan 1 1970 or something), calculating its current date depends on the calendar. Different calendars will give different date. This is from the prospective of giving an absolute time (eg 1 trillion seconds after Big Bang). But often we also need a convenient way of conversation, like an object encapsulating year, month etc.
I wonder if there are new advances in Java to reconcile these 2 objectives. Maybe my java knowledge is too old.
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();
)
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!