All about java.util.Date
codeblog.jonskeet.uk
codeblog.jonskeet.uk
Of course, as the article and other commenters have said, just use jodatime or the Java 8 equivalent.
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.
Don't do java.util.Date.
date.setMonth(date.getMonth() + 1);
and it will do the Right Thing even if the month is December.I've written all of date arithmetic using only long values and I can share the code if anyone is interested
"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)".
> 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.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...
All of which should be hidden behind your API anyway. It was a terrible choice, because it forces the client to deal with weird things just so that you can squeeze a single decrement out of your code.
I didn't know that this is one case where Java copied from C, which means JS copied it from Java and Java copied it from C (which itself seems to have inherited it via POSIX), all in the name of API compatibility but confusing the majority of programmers in each language every time.
A proposal to copy java.time to javascript. Hopefully this will happen eventually!
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."
In the case of such a change, I'd argue the time-instant should change and the timezone representation should be constant.
This is also how the likes of "chron" model scheduling of tasks. I found this so hard to wrap my head around at first precisely because I was used to dealing with time "as a programmer" from the inside out. Of course when you're scheduling a repeating task that you want to happen "at midnight" or "on a Monday morning" it makes more sense to specify in this top-down manner.
I might categorise such things as "a presentation layer" concern, but as you point out, in these cases your moment in time is stored as a calendar reference.
Member of the second camp reporting in. The default toString() behavior of java.util.Date threw me off for a very, very long time.
You can say that a Date doesn't include a time zone, but then a Date no longer actually refers to a concrete time -- it needs to be combined with a time zone first. This differs from how conventional language deals with dates, which is why people don't like it. And also the point of the article -- Java's Date class is misnamed and confusing.
UTC is a universal method to describe time-instant. However, UTC is not a timezone. GMT is a timezone, specifically, it is the timezone GMT+0. Representing a time-instant in GMT for universality is wrong, representing a date (i.e. the kind of thing humans use to denote appointments in their daily life) in UTC is also wrong. Use the construct that matches the domain.
This is why if you've ever submitted a paper to a conference, the deadline will nearly always be given with an hour level of precision and a time zone. Because just saying submissions are due on day X is not well defined in the modern world.
Edited: Not sure why this is getting downvoted. Do you people seriously believe that 4/23 is the same period of time in NYC as it is in London?
Honestly, it sounds like you didn't read the article and/or you misunderstood grandparent comment.
The Date class in Java does not represent a calendar date or period of time like "April 23th 2017". It represents an instant in time. It is precise to the millisecond and it does not depend on a specific time zone -- although it can be represented in different time zones. If you give the same (Java) Date value to a bunch of of people around the world and tell them to hook up to your live chat at that date and time, they will be able to attend at that time with no further information (such as timezone).
Please resist commenting about being downvoted. It never does any good, and it makes boring reading.
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.
http://stackoverflow.com/questions/1969442/whats-wrong-with-...
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.
The Sun-Oracle changeover sort of crippled change in the Java language for almost a decade.
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.
How does using Day Count help?
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.
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.
It was deprecated recently, however.
That's because time is hard. Time feels easy because we use it constantly in every day tasks. And if you just ignore those complexities, you get buggy code that costs your company money.
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.
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.
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.
Except in countries where "Christmas" tends to refer December 24th and December 25th is "Christmas Day".
https://github.com/jonhoo/wp2ghost/pull/8#discussion_r847977...
I think that would explain a lot.
http://grepcode.com/file/repository.grepcode.com/java/root/j...
Edit: I was wrong my bad
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.
JSR-310 was developed in large parts by the author of Joda, more than based on Joda it's also based on lessons learned from Joda.
Some of the back end systems are still on 1.2.
Something about "no money for licenses and upgrades" on items that use Java.
Not too many in-house developers, aka zero, want to touch that core system.