Skip to main content

Immutable java.lang.DateTime class

17 replies [Last post]
chandra
Offline
Joined: 2003-06-12

java.util.Date is ugly. It is unsafe for use in maps and sets. It's unlike other simple wrapper classes such as String, Integer. I propose the introduction of a class java.lang.DateTime as an immutable object. For the new APIs around it, java.util.Date could extend java.lang.DateTime. This would provide for all new DateTime APIs to work with existing objects created using java.util.Date.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mthornton
Offline
Joined: 2003-06-10

> What I want is a DateTime object that represents a
> date and optionally time like "Sep. 9th 2005,
> 15:13.21". Period.

But what does that mean? In most cases when a date/time is specified like that it is intended to define a specific instant and has an implicit timezone, which is fine for people (well mostly) but in computing we have to be more explicit.
There is a better case for having a date (without time) without a timezone. Such as when accuracy to the nearest day is adequate, or when the use is as a pattern to match an instant or period.
While it is possible to imagine "Sep. 9th 2005, 15:13.21" as a pattern matching some 30 different instants (24 regular time zones plus a few oddities), I think this is an implausible scenario.

marc_
Offline
Joined: 2003-12-30

> But what does that mean? In most cases when a
> date/time is specified like that it is intended to
> define a specific instant and has an implicit
> timezone, which is fine for people (well mostly) but
> in computing we have to be more explicit.
> There is a better case for having a date (without
> time) without a timezone. Such as when accuracy to
> the nearest day is adequate, or when the use is as a
> pattern to match an instant or period.

I couldn't agree more - in fact I've writen just such a Date class - see http://calendardate.sourceforge.net/

There are also two other implementations of "Date without time or timezone" - see:
http://timeandmoney.sourceforge.net/
http://joda-time.sourceforge.net/

chris_e_brown
Offline
Joined: 2004-09-14

> What I want is a DateTime object that represents a
> date and optionally time like "Sep. 9th 2005,
> 15:13.21". Period.
>
> I do not want that the date and time changes,
> depending on the timezone used to display it.

Have a look at JodaTime, it lets you do just that.

chris_e_brown
Offline
Joined: 2004-09-14

> No matter how good Joda Time is, do you really think
> Sun will include date/time support for the cost of
> half a megabyte?? Maybe if you scaled it down to like
> 50k then it would be in the ball park regarding
> size.
>
> Cheers.

It doesn't seem to be heavily compressed (using a popular ZIP tool I managed to compress it further using standard algorithms), so I managed to get it down to 450K. But then, it includes a LOT of information about timezones, which could replace the information in the JDK if the API were included (the "old" APIs could base such information on these "new" data files from), meaning you'd probably remove as much size as you'd add, making it redundant.

And of course, the classfiles in the JAR aren't compressed using Pack200, so there's more size reduction to be gained. And it's not just about dates, it's also about thread-safe date formatting, so you can also reduce the memory footprint of many applications and probably gain some speed as a result (especially by skipping the expensive creation of Java's currently not-thread-safe formatting classes), so there's more scope for eliminating redundant legacy code by making it delegate to the newer APIs.

Given the scope of Joda-Time, and the above points, I think it would perhaps not be far off your suggested target after all...

mgrev
Offline
Joined: 2003-08-12

No matter how good Joda Time is, do you really think Sun will include date/time support for the cost of half a megabyte?? Maybe if you scaled it down to like 50k then it would be in the ball park regarding size.

Cheers.

bmandl
Offline
Joined: 2004-01-01

A BIG problem with class Date from the point of view of many applications is that it does not represent a "Date" in the common meaning of the word (something like "Sep. 9th 2005"). A "Date" object represents a point in time. This point in time may be "Sep. 9th" in one time zone and "Sep 8th" in another time zone. So if you construct a "Date" object in a PC in one time zone and display it on a PC in another time zone the displayed time will change and the displayed date may change. Aaaarghh!!

What I want is a DateTime object that represents a date and optionally time like "Sep. 9th 2005, 15:13.21". Period.

I do not want that the date and time changes, depending on the timezone used to display it.

tackline
Offline
Joined: 2003-06-19

bmandi, how does that substantially differ from java.util.Calendar?

lucretius2
Offline
Joined: 2004-12-19

Er, if DateTime is immutable and Date extends DateTime, how can Date be mutable?

The ms field (that stores the time) is private so Date can't change it. Therefore Date is not compatible with the Date in Java 1.5.

If you make ms protected, so that Date can change it, Date will not be compatible with DateTime's contract that states that Date is immutable. For instance, a Date object can be stored in a variable of type DateTime, and the DateTime value can then be mutated (by calling one of Date's mutators).

You can't make an immutable DateTime mutable by extending it. At best, a mutable class could convert between itself and DateTime, possibly by wrapping a DateTime (without being a DateTime subclass).

chandra
Offline
Joined: 2003-06-12

I submit to you that private access to ms was an omission from my part. To refine, I suggest more restricted package private access to ms instead of protected access. Since java.* packages are prohibited under normal circumstances, ms is approximately private.
Of course, java.util.Date is mutable which would mutate ms though its setTime() method. However, a type created as DateTime() will be immutable. Yes, it does not provide a way of providing an invariant of an arbitrary API. However, it is still useful for create DateTime object that can be passed around and you can be sure that those objects (not type) are immutable. What is the benefit of DateTime being the super type of java.util.Date. New APIs that anticipate read only DateTime objects can accept old Date objects, at the risk that an object received could still be mutable.
Additionally, IMO, suggestion to implement a static factory method now() is noteworthy.

lucretius2
Offline
Joined: 2004-12-19

> Of course, java.util.Date is mutable which would
> mutate ms though its setTime() method. However, a
> type created as DateTime() will be immutable. Yes, it
> does not provide a way of providing an invariant of
> an arbitrary API. However, it is still useful for
> create DateTime object that can be passed around and
> you can be sure that those objects (not type) are
> immutable.
> New APIs that
> anticipate read only DateTime objects can accept old
> Date objects, at the risk that an object received
> could still be mutable.

The trouble is, if a method is passed a DateTime reference, how can it check it's an actual DateTime object and not a subclass? Even instanceof won't help you here, you have to to use reflection. This isn't a very useful design. Better to have be able to convert a mutable Date into an immutable DateTime: as described above, if Date is just a wrapper for DateTime, this 'conversion' is almost instantaneous.

dog
Offline
Joined: 2003-08-22

I don't understand why we need java.util.Date now.
Today it is nothing more than a container for a long it seems. So why not get rid of java.util.Date and just use longs anyway (with Calendar).

arnaud_roques
Offline
Joined: 2005-09-19

> java.util.Date is ugly. It is unsafe for use in maps
> and sets. It's unlike other simple wrapper classes
> such as String, Integer. I propose the introduction
> of a class java.lang.DateTime as an immutable object.
> For the new APIs around it, java.util.Date could
> extend java.lang.DateTime. This would provide for all
> new DateTime APIs to work with existing objects
> created using java.util.Date.

A lot of people agree that Date *should* be immutable.
We understand that it's not easy to define new classes as DateTime in future release of Java.

[u]But[/u] here idea of what can be easily done:
1) Put [i]@Deprecated[/i] on setTime() of the java.util.Date class

2) Like the java.util.Collections class, having somethink like java.util.Dates class, with:

[b]public static Date unmodifiableDate(Date date)[/b]:

Returns an unmodifiable view of the specified Date. This method allows modules to provide users with "read-only" Date and attempts to modify the returned Date result in an UnsupportedOperationException.

What do you think about it?

chris_e_brown
Offline
Joined: 2004-09-14

> [u]But[/u] here idea of what can be easily done:
> 1) Put [i]@Deprecated[/i] on setTime() of the
> java.util.Date class
>
> 2) Like the java.util.Collections class, having
> something like java.util.Dates class, with:
>
> [b]public static Date unmodifiableDate(Date
> date)[/b]:
>
> Returns an unmodifiable view of the specified Date.
> This method allows modules to provide users with
> "read-only" Date and attempts to modify the returned
> Date result in an UnsupportedOperationException.
>
> What do you think about it?

Not quite so good. From the outset, the collections API defined the idea of "optional operations" (questionable, as it could have been done through subinterfaces), so you can expect that. Any code using the date class may at some point want to modify the values, so code that assumed that dates are always modifiable might crash at runtime.

I personally use http://joda-time.sourceforge.net/ which is an excellent replacement and covers all the points raised above. It's really easy to use in conjunction with "legacy" date/calendar APIs, and trivial in conjunction with things like JDBC ResultSets. It has concepts of formatting, parsing, being read-only or modifiable, multiple calendar systems, as well as "partial" dates (time-day-only or date-without-time-of-day), as well as absolute (28 days) and logical (one month) differential operations.

It's specifically designed to be added to Java at some point. I really hope it is included (hint, hint, anyone?).

cowwoc
Offline
Joined: 2003-08-24

I also agree. The entire concept of "optional operations" was a bad one. It may be understandable in the face of backwards compatibility issues, but we are all better off if a new class is introduced altogether and the old one is deprecated. I also recommend Sun take a look at Joda Time.

lucretius2
Offline
Joined: 2004-12-19

> java.util.Date is ugly. It is unsafe for use in maps
> and sets. It's unlike other simple wrapper classes
> such as String, Integer. I propose the introduction
> of a class java.lang.DateTime as an immutable object.
> For the new APIs around it, java.util.Date could
> extend java.lang.DateTime. This would provide for all
> new DateTime APIs to work with existing objects
> created using java.util.Date.

This is an ingenious idea, but I don't think it would work.

If DateTime is immutable, then Date can't be made to extend it, because then Date wouldn't be mutable. So Date wouldn't be backwards compatible.

Instead, Date could contain a DateTime. It you mutate Date, then it would replace the DateTime object with a new one. There could be a method Date.toDateTime() which would return the wrapped object immediately, without having to construct one.

IMHO, although Sun seem to have ruled out replacing the date/time classes, I do think a new java.time package could be introduced that would interoperate with the old classes painlessly.

chandra
Offline
Joined: 2003-06-12

Of course Date can extend DateTime. Here is what I mean.
[code]
//new shiny proposed immutable DateTime type
class DateTime {
private long ms;

//It's non null to avoid null check in now() method
private static DateTime cache =
new DateTime(System.currentTimeMillis());

//DateTime shall not provide a default constructor

public DateTime(long ms) {
this.ms = ms;
}

/**
* static factory returns the current time
*/
public static DateTime now() {
long t = System.currentTimeMillis();
return t == cache.ms ? cache : (cache = new DateTime(t));
}

public long getTime() {
return ms;
}
}

//mutable, good old java.util.Date, we have come to love

public class Date extends DateTime {
//modify constructor etc
}
[/code]

In this proposal, the old code just works fine. And post DateTime API, let vendor1 writes a new API

public void method(DateTime d) {
}

Now Vendor2's old library (for eample JDBC layer returning java.sql.Date etc) could still call method(DateTime). So, the old library would just work with new type. Note that it's a type system thing not mutability vs immutability. However, it works in this case since immutable DateTime is a strict subset of mutable Date type(s).

forax
Offline
Joined: 2004-10-07

to be truly immutable a class must be final, see
http://www.javalobby.com/articles/immutable/index.jsp

Rémi Forax