2

I have this code to parse a big-endian-date String to a Date :

public static final Date fromBigEndian(String dateBigEndian) {
    DateFormat bigEndianFormat = new SimpleDateFormat("yyyy-MM-dd");
    try {
        return bigEndianFormat.parse(dateBigEndian);
    } catch (ParseException e) {
        return null;
    }
}

and this test case:

@Test
public void returnNullIfDoesNotMatchBigEndianFormat() {
    String nonBigEndianDate = "01-06-2016";
    Date parsedDate = DateUtil.fromBigEndian(nonBigEndianDate);    
    assertNull(parsedDate);
}

But it fails. It is returning a Date instead of null, but format of "01-06-2016" doesn't match with the pattern "yyyy-MM-dd". Why doesn't the method throw ParseException?

Héctor
  • 24,444
  • 35
  • 132
  • 243
  • 1
    what does the `Date` object contain? – Krzysztof Krasoń Aug 02 '16 at 11:21
  • 1
    Note the javadoc for `DateFormat.parse()`: source - a String whose **beginning** should be parsed. ... ParseException - if the **beginning** of the specified string cannot be parsed. – Andreas Fester Aug 02 '16 at 11:23
  • @krzyk [demo](http://ideone.com/7fZ00p). It's weird – BackSlash Aug 02 '16 at 11:24
  • @AndreasFester How can the beginning of `01-06-2016` be parsed with that format? – BackSlash Aug 02 '16 at 11:25
  • 1
    Well, there **is** a year "01", isnt it? You need to use `setLenient(false)` to tell the parser to be more strict. – Andreas Fester Aug 02 '16 at 11:27
  • @AndreasFester It is, but the format expects 4 digits for year, not two... – BackSlash Aug 02 '16 at 11:28
  • 2
    And "2016" is a valid amount of days. That is why the output is for year "6", because "2016" days are 5.5 years (+6 months from the June date) – Tom Aug 02 '16 at 11:28
  • 1
    Yes, but the parser seems to stop at the first input character which does not match the pattern, and uses everything up to the last valid character (probably the algorithm is even a bit more complex, as mentioned by @Tom) – Andreas Fester Aug 02 '16 at 11:29
  • @krzyk The result toString returns Tue Dec 07 00:00:00 CET 6 – xenteros Aug 02 '16 at 11:31
  • 1
    @BackSlash *"It is, but the format expects 4 digits for year, not two"* Its more like "up to 4 digits" and it interprets the missing digits as omitted zeros. The default behaviour of `SimpleDateFormat` is _really_ lenient, which often ends up in confusion. – Tom Aug 02 '16 at 11:32

1 Answers1

4

You should use DateFormat.setLenient(false):

public static final Date fromBigEndian(String dateBigEndian) {
    DateFormat bigEndianFormat = new SimpleDateFormat("yyyy-MM-dd");
    bigEndianFormat.setLenient(false);
    try {
        return bigEndianFormat.parse(dateBigEndian);
    } catch (ParseException e) {
        return null;
    }
}

Now it will throw ParseException


From the official documentation:

public void setLenient(boolean lenient)

Specify whether or not date/time parsing is to be lenient. With lenient parsing, the parser may use heuristics to interpret inputs that do not precisely match this object's format. With strict parsing, inputs must match this object's format.

Raman Sahasi
  • 30,180
  • 9
  • 58
  • 71