Search code examples
javascalasimpledateformat

SimpleDateFormat showing inconsistent results


val dateStr = "2020 10 12 23 12 13"
val dateFormat = "yyyyMMddHHmmss"
import java.util.Date
val sdf = new SimpleDateFormat(dateFormat)
sdf.setLenient(false)
val res = sdf.parse(dateStr)
println("res = "+res)

scala> val res = sdf.parse(dateStr)
java.text.ParseException: Unparseable date: "2020 10 12 23 12 13"
  at java.text.DateFormat.parse(DateFormat.java:366)
  ... 50 elided

The above code block parses and results in an exception, but if i change the "MM" part to "11" instead of "10" then it parses fine, without any exception , but with a wrong date. Any idea why is that ? I want the code to fail or throw an exception if my date String is not in this format "yyyyMMddHHmmss"

/*Note the 11 instead of 10*/
    val dateStr = "2020 11 12 23 12 13"
    val dateFormat = "yyyyMMddHHmmss"
    import java.util.Date
    val sdf = new SimpleDateFormat(dateFormat)
    sdf.setLenient(false)
    val res = sdf.parse(dateStr)
    println("res = "+res)
    
    
    scala> val res = sdf.parse(dateStr)
    res: java.util.Date = Wed Jan 01 01:02:23 PST 2020

Solution

  • SimpleDateFormat is simply too lenient for what you want. It's parsing your date as:

    2020 yyyy
    _1   MM (where _ represents a space)
    1    dd
    _1   HH
    2    mm
    23   seconds
    12 13 ignored
    

    So I think the best way around it for you would be to bite the bullet and forbid spaces.

    So try something like trimming the string and then searching for spaces in the middle. If you find spaces, throw an Exception.

    But ultimately its probably better to drop SimpleDateFormat and use the new stuff. I think the new DateTimeFormatter class will serve you better:

    // In Java
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    LocalDateTime date = LocalDateTime.parse(dateStr, formatter);
    System.out.println("date="+date);
    

    This throws and exception.

    In Scala:

    val formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    val date = LocalDateTime.parse(dateStr, formatter);
    println("date="+date);