
All about java.util.Date - D_Guidi
https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/
======
hn_throwaway_99
I think the article gets at this, but the biggest "eureka" I had was when I
realized that java.util.Date is _just_ sugar around a long value (ms since the
epoch). Thus, wherever you use a Date, if you would NOT consider using a long
there, then Date is the wrong choice. E.g. timestamp for log entry records -
yeah, makes sense. Days on a schedule app - definitely wrong choice.

Of course, as the article and other commenters have said, just use jodatime or
the Java 8 equivalent.

~~~
kpil
Or just use a long...

~~~
adrianmsmith
Before Java 8 and Jodatime, it was better to use java.util.Date than a long,
for type-checking and self-documentation.

If a function accepts a java.util.Date and you pass an id of some database
object by mistake, you'll get a compile error. If the function accepts a long
you won't.

If a function accepts a java.util.Date and the parameter is called "start" you
know it accepts an instant in time, if it accepts a long you might think it
could be something else.

Yes, the class is terribly named, but before there was Java 8 and Jodatime, it
was better to use it than a long.

~~~
bluestreak
It is not always a good idea to box primitives so that you can have compiler
point out mistakes. Yes, it is good for developer once or twice, but end user
will suffer performance hog forever.

~~~
nradov
Modern JVMs are pretty good at optimizing away the overhead of boxing
primitives. So don't throw away the advantages of type checking unless you
have hard evidence of an actual performance problem.

------
Clownshoesms
I'll never understand why they thought 0-based months made sense, but then
used 1-based days and 1900-based years. Even if C did it. Almost feel like I
can hear the committee:

"Meh it's only a Date class, no one will really use it, will they? Billy
already committed the code for 0-based months. Who here does _not_ think of
January as month zero?"

 _feet nervously scuffing carpet_

"Right, settled! Moving on, company picnic is on the 1st of 0 next year (96)".

~~~
avar

        > I'll never understand why they thought 0-based
        > months made sense, but then used 1-based days
        > and 1900-based years. Even if C did it[...]
    

Java, Perl etc. all copied this pattern from localtime() in C. In all of these
languages it's idiomatic to write something like:

    
    
        printf("%s %d, %d\n", mnames[mon], mday, year);
    

To print out e.g. "January 6, 78". The reason month days aren't zero based is
obvious, usually when you use them you aren't going to have go through a
lookup table, whereas nobody calls January "0" or "1", so you'll always need a
lookup table.

Indexing months by 1 would mean declaring the "mnames" array would be the un-
idoimatic:

    
    
        char *mname[] = { NULL, "Jan", ... };
    

Instead of:

    
    
        char *mname[] = { "Jan", ... };
    

Or you'd need to use the latter form and do lookups by mnames[mon - 1] instead
of mnames[mon].

The reason you have to add 1900 to the year is that when C was made it was
standard for software to use two-digit years, and if you told some of C's
designers back in the 70s that we'd still be using & discussing these APIs in
2017 they'd probably have laughed at you.

Of course sometimes you need to use month indexes themselves, e.g. if you
wanted to print out 1978-01-06 in a log file:

    
    
        printf("%d-%d-%d...\n", year + 1900, mon + 1, mday, ...);
    

But such are the trade-offs of low-level API design. I guess C's designers
took the inherent idiomaticness of zero-based indexes & expectation that the
common case would to print out month names over such use-cases.

~~~
Sharlin
> whereas nobody calls January "0" or "1"

Eh, in many locales it's idiomatic to refer to months by number, not by name,
especially in the "short form" of a date. So you end up having to add one to
the month number. But of course when they made C they didn't think about
internationalization either...

------
bloat
_How do I convert a Date to a different time zone? You don’t – because a Date
doesn’t have a time zone._

There's something about this, and the way we think about dates, which makes it
very hard for some people to understand. Some people get it immediately,
others never will. Not wanting to sound superior (I think the Date object
seems almost designed to foster this confusion), but I've lost count of the
number of times I've spent a long time explaining this, and then at the end of
it all the person still says something like, "OK, well we'll just use this GMT
Date then."

~~~
rusk
For me, the moment the penny dropped was the realisation that "Timezone" is a
presentation layer issue. _i.e._ it's not something you should concern
yourself with until you're rendering it to be read by a human. Otherwise just
using some well-defined simple convention such as epoch-time is fine
throughout your application. There are exceptions such as doing date-
calculations and such, but I extend my rule of thumb such that these kinds of
things should be converting _from_ epoch time (e.g. to `Calendar`) for the
calculation and then back again.

~~~
distances
I agree, I find it a well working convention to use UTC times for everything
in an app, and convert to local time zone only at the time of display when
formatting the date as a string.

~~~
yen223
Unless you are dealing with recurring events that happen at a specific time of
day, in which case you need to know the local timezone to avoid off-by-one-
hour errors if daylight savings kicks in.

~~~
distances
Yes, I'm sure the use cases I've had to deal with have been very simple to
start with.

------
ddlatham
_So how do computers represent instants? They typically store an amount of
time before or after a particular instant which is effectively an origin. Many
systems use the Unix epoch, which is the instant represented in the Gregorian
calendar in UTC as midnight at the start of January 1st 1970. That doesn’t
mean the epoch is inherently “in” UTC – the Unix epoch could equally well be
defined as “the instant at which it was 7pm on December 31st 1969 in New
York”._

A thousand times yes. I see many developers confused by this. The Unix epoch
is not inherently specific to UTC, it just happens to have a round date when
described in that time zone. Seconds (or milliseconds) since the Unix epoch is
a unit _without timezone_.

~~~
ams6110
You say "it just happens" as if it's a coincidence. It was a deliberate
choice.

~~~
TeMPOraL
And timezones are a completely orthogonal issue if you note that epoch is
defined as "midnight at the start of January 1st 1970" _in UTC_.

------
alblue
Several years ago I answered a question on StackOverflow "what's wrong with
the date and time api in Java"

[http://stackoverflow.com/questions/1969442/whats-wrong-
with-...](http://stackoverflow.com/questions/1969442/whats-wrong-with-java-
date-time-api/1969651#1969651)

Considering how long ago it was answered, it took a /long/ time for the Java 8
replacement to come on board and give some sanity back to Java date
computations.

~~~
douche
It took a long time for Java to fix anything before Java 8.

The Sun-Oracle changeover sort of crippled change in the Java language for
almost a decade.

~~~
MichaelGG
Java 8 was released 5 years after the Sun Oracle acquisition. What do you mean
by decade?

------
RegW
For many years my advice to other java devs has been to avoid using
java.util.Date and Oracle date columns where possible - for all the reasons
given in the article, but generally because they don't always do what you
expect.

The reason is that these dates encapsulates one concept of date (a point in
time), and devs often try to use it for another (the legal date).

A legal date is fixed. It also has no time zone, but in a different way - it
will not look different when viewed from another timezone. I was born on the
opposite side of the world to where I live. The DOB on my passport didn't
change, as I moved around the world.

Too often the user inputs a legal date. Software translates this to a point in
time so it can be stored in one of these dates, the TZ info is lost, and
before you know it the software is displaying a date other than that input. A
bug is filed, a dev investigates and hacks code to add one hour, the bug is
closed, and another opened when we pass into daylight saving.

It doesn't have to be like this - even MS Excel knows to just use a day count.

~~~
Fifer82
I am not using Java but I am right now making a booking system. I am storing
local time (with Offset) and the timezone identifier such as "Europe/London".

How does using Day Count help?

~~~
RegW
Sorry for being oblique.

A day count is just the number of days since some arbitary point. Say today is
42849, tomorrow is 42850, etc.. If the user enters the 24th April 2017, you
store 42849. When you read it back 42849 is always displayed as 24th April
2017.

There is no magic - you could just store 3 integers, or a formatted string say
"20170424". Anything that doesn't involve timezones.

Perhaps, with your programming language you don't get the same issues, but to
use java.util.Date you have to parse this into a number of milliseconds since
1 Jan 1970. You might round it down to midnight at the start of the day - or
the end. You might select midnight according to local time (with or without
daylight saving), you might use UTC, or you might unwittingly leave it to the
machine. To persist this to a DB you might use some ORM mapping like Hibernate
- which without careful configuration may also make some assumptions about
timezone, and Oracle might do the same. By the time the value is read back,
your date may not be the same one entered - and this may not show up until you
pass into daylight saving.

~~~
Fifer82
Not at all, I was genuinely curious. Thanks for the detailed response, I
understand what you were getting at.

------
BurningFrog
The misleading name is the worst misfeature. I've had to explain to at least
half a dozen coworkers that Date is not a date, but a timestamp. Some people
just refuse to believe it, perhaps because they trust the Java designers more
than me, as you normally should.

Often they persist in thinking "it's just a more detailed date, 17:08, April
23 is still April 23".

Then I have to explain that every Date object is on two different real dates.
That's a _big_ struggle for many.

------
pducks32
This confused me with Foundation's Date class as well. I think it's really
important to have abstractions that are really clear. Like for example I had
to represent Open Hours for business and wanted a way to represent 4pm on
Monday. That's surprisingly hard (in Swift and Java) because the APIs want you
to realize the complexity of Time. But I don't care. I want an abstraction
that says "Yup it's Monday at 4pm in Santa Clara". I think better Date and
Time libraries that deal with more user facing things would be great.

~~~
saagarjha
`NSDate` used to support creation from a "natural language" phrase:
[https://developer.apple.com/reference/foundation/nsdate/1415...](https://developer.apple.com/reference/foundation/nsdate/1415776-date)

It was deprecated recently, however.

~~~
chc
Even further back, there was an NSCalendarDate class that was supposed to
represent the human concept of a date. IIRC they got rid of it because they
felt like it muddled presentational concerns with data structure concerns. It
was pretty convenient, though.

~~~
saagarjha
Yep, I had to do a bit of fuddling around with DateComponents and it was
_painful_.

------
TeMPOraL
Tangential, but one of the best sources I've seen on issues with times and
dates is Eric Naggum's "The Long, Painful History of Time".

[http://naggum.no/lugm-time.html](http://naggum.no/lugm-time.html)

Notably, besides outlining the complexity of the domain, the article also
serves as explanation of decisions made by author in implementing local-time,
a popular date/time library for Common Lisp.

------
adrianmonk
_It doesn’t have a calendar system._

Hopefully this won't come off as mere quibbling about terminology, but to me
it makes more sense to say that it _does_ have a calendar system, it's just
that it isn't any of the ones humans use. When I write "April 23, 2017 6:04pm
CDT", the calendar system is Gregorian. If I were to write the integer value
underlying a java.util.Date, I would argue the calendar system is Unix Epoch.

Both are systems that pick out arbitrary points in history (year 1 AD or
midnight January 1, 1970) to base numbers off of. Both have rules on how you
manipulate those numbers and what values mean.

If someone persists in asking what the time zone is for a java.util.Date, I
would probably tell them that, more or less, it has _its own_ time zone. This
isn't quite true, but it's close because time zones are basically parameters
for parameterized calendar types, so a time zone kind of implies a calendar.

Anyway, the point is that thinking of it as its own calendar system hopefully
makes it clear that it stands on its own.

~~~
rtpg
So this isn't super exact in the common usage of calendars, in part because
calendars are usually implicitly fixed to a timezone (hence Google Calendar
asking to change your calendar's timezone).

For example, December 25th might be Christmas, but you cannot define two Dates
that "delineate" Christmas in the world, because the start time is different
dependent on the time zone.

While this is kinda pedantic to Earth calendars, it's also the kind of problem
that most commonly causes issues in our programming.

You can do "if date < christmas", but it most likely won't do what you want it
to do if your program is meant to run in many timezones.

~~~
dagw
_For example, December 25th might be Christmas_

Except in countries where "Christmas" tends to refer December 24th and
December 25th is "Christmas Day".

~~~
rusk
Indeed - in this case you're talking about _locale_ rather than _timezone_.

------
AlexTelon
Javascript seems to have many (if not all) of the same issues. I learnt this
firsthand a while ago when I knew nothing about these issues and just assumed
that getting the Date of a particular time instant would be an easy task. See
rant below:

[https://github.com/jonhoo/wp2ghost/pull/8#discussion_r847977...](https://github.com/jonhoo/wp2ghost/pull/8#discussion_r84797728)

------
funwithjustin
One similar thing that's always bothered me conventionally. Why is it
`System.arraycopy()` and not `System.arrayCopy()`?

~~~
skocznymroczny
actually, why not System.copyArray(). arraycopy() suggests that the method
returns a copy of the array ( sorted() vs sort() )

------
sandGorgon
The discussion around monotonic time in golang is one of the most indepth
discussion around time handling that I ever saw. Not sure if java covers all
these scenarios.

[https://github.com/golang/go/issues/12914](https://github.com/golang/go/issues/12914)

------
nl
The story I've heard was the java.util.Date was written by an intern at Sun.

I think that would explain a lot.

~~~
sixbrx
Actually the First author mentioned in the source is ... James Gosling!

[http://grepcode.com/file/repository.grepcode.com/java/root/j...](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Date.java)

------
lsd5you
A relic of 90s programming. Perhaps we can take a moment to realise we are not
just doomed to reinvent things that were done properly in the 70s. Looking
back there were plenty of things that were just poorly thought out and this
was one of them.

~~~
nl
My very first job out of university involved the Y2K bug. Believe me, things
weren't done properly in the 1970s (note the 4 figure date there. The scars
are real...)

------
nottorp
While the content is spot on, I disagree about the title - it's more of an
introduction than an 'all about'. You understand it best if you already know
how to (not) use java.util.Date...

------
shouldbworking
TLDR: It sucks balls use Jodatime

Edit: I was wrong my bad

~~~
pavel_lishin
> Note that 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.

[http://www.joda.org/joda-time/](http://www.joda.org/joda-time/)

~~~
alkonaut
So basically a joda-like sane api was included as a JSR, making joda obsolete?

Are there any such plans for .NET and NodaTime? They have a more "everything
is a package"-philosophy these days, but sensible dates and times really ought
to be right in the corlib, especially since the _bad_ dates and time apis are
already there.

~~~
jonskeet
I've mentioned a few times to MS folks that I'd be very happy for the mscorlib
team to make Noda Time redundant. They haven't bitten yet though.

