3

I'm using SimpleDateFormat with pattern "MM" and try to parse "0012".

Even with leniency disabled the formatter will successfully parse this to december. I'd like it to throw an exception, this is no 2-digit-month. Does anyone know how to achieve that?

Code

Example code:

SimpleDateFormat df = new SimpleDateFormat( "MM");
df.setLenient( false);
System.out.println( df.parse( "0012"));

Output:

Tue Dec 01 00:00:00 CET 1970

Community
  • 1
  • 1
Roland
  • 18,114
  • 12
  • 62
  • 93

3 Answers3

1

Just move on and use java.time, the modern Java date and time API. DateTimeFormatter.ofPattern("uuuu-MM-dd") will parse 00 as the month and then object because it isn’t followed by a hyphen, - (that is, before even checking to see that 00 isn’t a valid month number).

I think you should want to use java.time anyway. The SimpleDateFormat class you’re using is not only outdated, it is also notoriously troublesome.

Link: Oracle Tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Unfortunately I can't just move on, solving that problem with SimpleDateFormat is less risky than changing the api and being forced to do lots of regression tests. – Roland Feb 06 '18 at 03:05
  • 1
    You don’t have to migrate your code base and regression test everything. You may use `java.time` in just the lines you are writing now. If you need to get an old-fashioned `java.util.Date` object from parsing, convert through the `Instant` class, for example `Date.from(myParsedOffsetDateTime.toInstant())`. – Ole V.V. Feb 06 '18 at 05:33
  • 1
    Yeah, looks like it's either that or nothing. Just dug into the Java code itself. The BigDecimal formatter that is used in SimpleDateFormat has this comment of code `// Ignore leading zeros in integer part of number.` followed by respective code. So there's no solution other than writing the formatter yourself or use your suggestion. I rather use yours. Thanks for your help! – Roland Feb 06 '18 at 06:32
0

This might not be the best solution for this problem, but here it goes. I suggest checking if the value introduced by the user is bigger than 2 digits (I supposed the input is an String) inside of an exception handler and creating an exception if it does:

try{

    if(str.length() > 2){

        int crash = (1/0);

    }

}catch (ArithmeticException e){

    System.out.println("You've introduced a month format larger than MM");

    //introduce the code you'll like to be executed when the Exception is 
    //fired.

}

I understand this is not the best way to solve this issue. However, it works. If someone has any better idea just tell me and I'll edit my answer.

Alex Cuadrón
  • 638
  • 12
  • 19
  • Thanks, but that's more like a hack. I need a proper solution. In the end flexible parsing should be possible. Quick Example: Using list of patterns "MM" and "HHmm" and iterating through all parsing 0012 until successful, the text 0012 should translate to time 00:12 instead of month 12. I can't change the order, unfortunately, other pattern-combinations have similar problems. – Roland Feb 05 '18 at 17:03
  • @Roland Maybe using an if/else statement for comparing the length of the String introduced by the user to determine whether they are a month or not? Or you have to compulsory use patterns? – Alex Cuadrón Feb 05 '18 at 17:11
  • I have to use patterns, any combination of them. So I'm stuck with strict checks. I guess the problem might be the numberformat and I have to write a custom formatter. Gonna dive into the Java source itself. But thanks for your feedback! – Roland Feb 05 '18 at 17:57
0

Assuming that 0012 is month and year with 2 digits each, you can use MMyy as pattern:

SimpleDateFormat df = new SimpleDateFormat("MMyy");
df.setLenient(false);
System.out.println(df.parse("0012"));

This will throw the following exception,

java.text.ParseException: Unparseable date: "0012"
Roshana Pitigala
  • 8,437
  • 8
  • 49
  • 80
daffd
  • 1