views:

85

answers:

3

Try this:

DateFormat df = new SimpleDateFormat("y");
System.out.println(df.format(new Date()));

Without reading the javadoc for SimpleDateFormat, what would you expect this to output? My expectation was "0". That is to say, the last digit of the current year, which is 2010.

Instead it pads it out to 2 digits, just as if the format string had been "yy".

Why? Seems rather bizarre. If I had wanted 2 digits then I'd have used "yy".

A: 

If you want only a digit you can:

System.out.println(df.format(new Date()).substring(1));

:)

onof
That's basically what I ended up doing. It was annoying because I wanted to create a DateFormat and use it in an agnostic way, e.g. have it injected from somewhere else and only call "format()". In order to do that and still get one-digit-year functionality I have to subclass SimpleDateFormat.
+5  A: 

"Without reading the javadoc" is a dangerous attitude more often than not. Joshua Bloch wrote a book on this strange behaviours in Java.

Alberto Zaccagni
True. If there are doubts, consult the documentation. Especially when it is as well written as Java's. It's fine to _expect_ things at first but once it doesn't work a look at the documentation should immediately follow.
musiKk
+3  A: 

That's why you need to check the documentation:

For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century.

"y" is an abbreviation, so this is expected behavior.

Bill the Lizard
I read the documentation after it failed to do what I expected. I saw that line. So, yes, it is working as documented. My question was more, "Why the hell was it designed this way?"
@user190758: I guess the designers of the API thought that one digit of the year wasn't informative or was too ambiguous, so they made that a shortcut. I'm used to thinking of years in 2 or 4 digits, so I don't know what most people would expect the single digit to be. FWIW, I think your doc usage of `1. Try it in code. 2. Observe the result. 3. Check the doc if needed.` is pretty typical. That's normally what I do too.
Bill the Lizard
@Bill - I agree that development pattern is typical, and necessary at times, but it can be harmful. When step 2 succeeds due to sheer coincidence, lesser programmers often don't bother consulting the docs to learn that their method will fail on weekends, or with multiple threads, or on Linux, or when the library is updated, etc. There's obviously a judgment call (you don't want to read the whole docs of every method) but if in doubt, it's probably better to err on the cautious side and produce more robust code a little slower.
Andrzej Doyle
@Andrzej: Yes, I agree with that too. The trick is for library designers and implementers to produce APIs that never succeed due to sheer coincidence, but always have a very clear expected behavior. (Far easier said than done, I know.)
Bill the Lizard
@Bill: Exactly. Instead of "y" producing "10" I would rather have the docs specify that "y" isn't supported, and have the constructor fail when it is handed format string that contains "y" by itself.The use case, by the way, is in formatting data for ISO 8583 payment network messages. Data Element 37, at least in Visa's implementation, is supposed to have as its first 6 digits the current time in "yDDDHH" format.