389

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?

Seraphim's
  • 12,559
  • 20
  • 88
  • 129
Marty Pitt
  • 28,822
  • 36
  • 122
  • 195
  • 28
    Joda time: http://joda-time.sourceforge.net/ – R. Martinho Fernandes Sep 10 '09 at 09:16
  • 3
    FYI, the troublesome old date-time classes such as `java.util.Date`, `java.util.Calendar`, and `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. Much of the *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Feb 23 '18 at 00:21
  • 3
    FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project (mentioned in another comment) is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [java.time](http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Feb 23 '18 at 00:21

13 Answers13

385

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.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • 6
    FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Oct 19 '18 at 19:51
66

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.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
dmeister
  • 34,704
  • 19
  • 73
  • 95
  • 7
    I second the suggestion to use joda time. It is easier to use and understand and offers much more functionality you can use. – Jeroen van Bergen Sep 10 '09 at 09:34
  • 31
    For discussion on whether to use Joda Time or stick with standard JDK classes, see http://stackoverflow.com/questions/589870/should-i-use-java-date-and-time-classes-or-go-with-a-3rd-party-library-like-joda – Jonik Sep 10 '09 at 10:20
  • How other frameworks co-exists with that? is it supported out of the box or do you need to write some extra converters? – IAdapter Sep 10 '09 at 10:45
  • 5
    I don't know if it deserves downvotes, but it doesn't answer the question. Might just be better as a comment. – IcedDante Dec 31 '12 at 14:43
  • 7
    Because the question was about using Date and Calendar not using a third party library which adds a single vendor dependency risk to a project. – Archimedes Trajano Nov 15 '13 at 19:22
  • 1
    FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Oct 19 '18 at 19:42
  • 4
    This WAS the "best way" until the [java.time package](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) was made available with Java 8. – DaBlick Nov 16 '18 at 13:58
  • 1
    ["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."](https://github.com/JodaOrg/joda-time) – wonsuc Feb 14 '22 at 06:36
60
  • 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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
  • 1
    Is there a time frame for JSR310 ? It was going to be in Java 7, but I believe that's now not the case. – Brian Agnew Sep 10 '09 at 09:39
  • @Brian - it's certainly gone very quiet on that mailing list! – oxbow_lakes Sep 10 '09 at 09:42
  • Just checking, it's gone Inactive, which means they've not published a milestone draft in 18 months :-( – Brian Agnew Sep 10 '09 at 09:43
  • Most recent comment on the mailing list is from July and by Stephen, so the project is probably still ticking away – oxbow_lakes Sep 10 '09 at 10:11
  • Agreed. If you know how to use Date safely as an immutable object, and Calendar to manipulate Dates, most people should be safe. Be careful when using SimpleDateFormat in multithreaded code. – cwash Nov 22 '10 at 22:53
  • I love the optimism (in late 2009) behind the idea that Joda is "soon to be [superseded] by the JSR-310 date API." – duelin markers Aug 07 '13 at 20:11
  • JSR-310 has been released as part of Java 8. – miguel Nov 10 '15 at 18:36
  • ...and I'd argue that it's not "super complicated" compared to Joda-Time and even Calendar/Date combos. I'd say once you understand the theory behind date/times in computers and how they are calculated (which I believe is the biggest core problem with Dates), then the API makes much more sense (with a few weird edges, but still..). The issue with Java Date/Calendar is that most people (myself included when I first started using them) do not correctly understand how datetimes function and how they are calculated. – Martin Marconcini May 15 '20 at 12:54
37

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)

Table of all date-time types in Java, both modern and legacy

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?

Table of which java.time library to use with which version of Java or Android

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
26

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).

KLE
  • 23,689
  • 4
  • 56
  • 62
17

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);
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
  • Yes, [immutable objects](https://en.wikipedia.org/wiki/Immutable_object) make sense for date-time work. The *java.time* classes that supplanted `Date`/`Calendar` use the immutable objects pattern. – Basil Bourque Oct 19 '18 at 19:48
  • That may be true but not in 2010. – Archimedes Trajano Oct 19 '18 at 21:07
  • Yes. But there are thousands of people reading this page *now*, over 150,000 so far. My comment is a note to them, not a criticism of you. – Basil Bourque Oct 19 '18 at 22:54
  • I know, that's why I upvoted the other answer. However, there's still some people that need to suffer with the older JDKs that need the answer above too. – Archimedes Trajano Oct 19 '18 at 23:06
  • 1
    Actually, for Java 6 & 7, we have the *ThreeTen-Backport* project. This brings most of the *java.time* functionality with virtually the same API. So there is no need to ever use those terrible legacy date-time classes. – Basil Bourque Oct 19 '18 at 23:22
15

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.)

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • Yes, [immutable objects](https://en.wikipedia.org/wiki/Immutable_object) make sense for date-time work. The *java.time* classes that supplanted `Date`/`Calendar` use the immutable objects pattern. Specifically, `Instant` replaces `java.util.Date`, and `ZonedDateTime` replaces `Calendar`/`GregorianCalendar`. – Basil Bourque Oct 19 '18 at 19:50
11

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());
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
  • Good to suggest the java.time classes. But bad to suggest `LocalDateTime`. That class purposely loses any information about offset-from-UTC and time zone. So that class is *not* equivalent as `Date` is in UTC and `Calendar` has an assigned time zone. See [my Answer and nifty diagram](http://stackoverflow.com/a/36639155/642706) to another Question, [Convert java.util.Date to what “java.time” type?](http://stackoverflow.com/q/36639154/642706). – Basil Bourque Feb 28 '17 at 00:10
9

I always advocate Joda-time. Here's why.

  1. the API is consistent and intuitive. Unlike the java.util.Date/Calendar APIs
  2. 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)
  3. 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

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • 3
    The last time I looked, JODA and JSR-310 looked *very* different, even if they are both written by Stephen Colebourne. That said, JODA would introduce you to the complexity of the date-time problems that JSR-310 also solves – oxbow_lakes Sep 10 '09 at 09:39
  • 2
    Because the question was about using Date and Calendar not using a third party library which adds a single vendor dependency risk to a project. – Archimedes Trajano Nov 15 '13 at 19:22
  • 2
    I maintain the best practice is simply not to use those classes – Brian Agnew Nov 20 '13 at 22:10
  • 3
    Given the known problems with the java.util.Date and Calendar classes, suggesting Joda-Time (or JSR 310) seems appropriate and responsible to me. We're not talking about a matter of taste or aesthetic style. If someone asked whether they should take the red car or the silver car, and I knew the red car had a flat tire and the silver car had a busted radiator, should I pick a car or should I suggest calling a taxi? The answer to that question should seem obvious nowadays as even Sun/Oracle decided to leave behind those junkers and buy a new car: JSR 310: Date and Time API. – Basil Bourque Jan 08 '14 at 20:50
  • Update to the answer: JSR 310 is part of Java 8, in the [java.time.* classes](http://download.java.net/jdk8/docs/api/java/time/package-summary.html). – Basil Bourque Jan 08 '14 at 20:51
  • 2
    FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Oct 19 '18 at 19:50
  • Agreed. I'm amending the answer appropriately – Brian Agnew Oct 20 '18 at 12:57
9

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.

Silviu Burcea
  • 5,103
  • 1
  • 29
  • 43
1

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.

  • The fact that you can store the same instant in time, but report different hour/minute/day/week/year/foo based on different calendar systems, is a strength, not a weakness. It reflects the (complex) reality. – ThrawnCA Oct 30 '15 at 05:14
  • Indeed, `Date` has been re-developed; replaced by the `java.time.Instant` class. And `Calendar`/`GregorianCalendar` was replaced by `java.time.ZonedDateTime` class. – Basil Bourque Oct 19 '18 at 19:46
0

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(); )

Community
  • 1
  • 1
xxxvodnikxxx
  • 1,270
  • 2
  • 18
  • 37
0

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!

Brian Nelson
  • 39
  • 1
  • 6
  • FYI, the troublesome `Calendar` & `Date` classes were supplanted years ago by the *java.time* classes. No need to ever use `Date` or `Calendar`. And `Locale` has nothing to do with the meanings of date-time objects. A `Locale` is only used to specify the human language and cultural norms to be used in localizing while generating text to represent the value of a date-time object. – Basil Bourque Jul 02 '18 at 22:30