简体   繁体   中英

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

The Answer by Ruokki is correct, your formatting pattern does not match your input data.

java.time

More importantly, you are using the wrong classes. The date-time classes bundled with the earliest versions of Java are terrible. They were years ago supplanted by the modern java.time classes defined in JSR 310.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu MM dd HH mm ss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

To detect faulty inputs, trap for the DateTimeParseException .

try
{
    LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
}
catch ( DateTimeParseException e ) 
{
    …
}

ResolverStyle

The DateTimeFormatter uses one of three different approaches in parsing: strict, smart and lenient. These are represented by the ResolverStyle enum. SMART is used by default, but you can specify STRICT if that better suits your needs.

ISO 8601

I suggest you educate the publisher of your input data about ISO 8601 . That standard defines formats for exchanging date-time values textually.

The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to define a formatting pattern for compliant inputs.

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);

Hello I think the problem is the date format:

    val dateFormat = "yyyyMMddHHmmss"

And should be

    val dateFormat = "yyyy MM dd HH mm ss"

Because your dateStr contains some space who play a important part in the format

But if you want to fail in case you have space or other thing unwanted in the date maybe a regex is the best answer?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM