0

I have a string and a format. I want to convert the string to date time using the format. But simple date time format is converting the string to date time even the input string is in a wrong format.

val formatter = new SimpleDateFormat("yyyyMMdd")
val dateInString = "2017042er7"

try {
formatter.setLenient(false)
val date = formatter.parse(dateInString)
System.out.println(date)
System.out.println(formatter.format(date));

} catch  {

 case e:Exception=>println(e)
}

How can I enforce the format?

**UPDATE:: ** using joda time formatter solved the issue. You can also use java time formatter(as one of the answers suggested).

Luniam
  • 463
  • 7
  • 21
  • 1
    FYI, the troublesome old date-time classes such as `java.util.Date`, [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html), and `java.text.SimpleTextFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. Likewise, the [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the java.time classes. – Basil Bourque Aug 15 '17 at 23:31

3 Answers3

2

You should use the new java.time API and its DateTimeFormatter to parse your dates. it allows for much greater control and correctness and is stricter with the format.

Leave the old java.util.Date, and SimpleDateFormatter behind and just convert to them when you need it to interact with a library.

puhlen
  • 8,400
  • 1
  • 16
  • 31
  • 2
    @Luniam yes, but you should actually drop jodatime in favor of the new java.time as well as java.time is the successor to jodatime post java 8. – puhlen Aug 15 '17 at 20:09
0

setLenient doesn't care so much about the String format, rather that the value passed can be converted into a date. For example, should 31-Sept-2017 be treated as 01-Aug-2017.

The library is trying to be helpful by parsing your input (dd is a number, so 2 fulfils that requirement, everything after that can be ignored). If you require the String format to be exact, then you should use a regular expression to validate the input before converting it.

BTW, I'm not necessarily agreeing with the implementation, just trying to explain why it works :)

StuPointerException
  • 7,117
  • 5
  • 29
  • 54
  • It should not parse exactly as the format. Otherwise, what's the point of providing the format. I am getting a wrong value while I was expecting something else. I would say it is a bad implementation. Joda time is better. Using joda time solved the issue I was having. – Luniam Aug 15 '17 at 20:02
  • I don't disagree, just explaining why you're seeing the results you are. – StuPointerException Aug 15 '17 at 20:58
0

tl;dr

LocalDate.parse(                              // Use modern java.time classes.
    "2017042er7".replaceAll( "\\D+" , "" ) ,  // Extract digits from string.
    DateTimeFormatter.BASIC_ISO_DATE          // Use pre-defined formatter for YYYYMMDD input, the “basic” version of standard ISO 8601 format.
).toString()                                  // Generate String in full version of ISO 8601 format (with hyphens as separators). 

2017-04-27

Extract digits

As explained in Extract digits from a string in Java, extract the digits only from the string.

String original = "2017042er7" ;
String input = original.replaceAll( "\\D+" , "" ) ;

Parse as LocalDate

Avoid the troublesome old legacy date-time classes seen in the Question. Supplanted by java.time classes.

The LocalDate class represents a date-only value without time-of-day and without time zone.

The DateTimeFormatter class contains a pre-defined formatting pattern to fit your needs: BASIC_ISO_DATE. That is the “basic” version (minimizing use of separators) of the standard ISO 8601 format.

LocalDate ld = LocalDate.parse( input , DateTimeFormatter.BASIC_ISO_DATE ) ;

See this code run live in IdeOne.com.

original: 2017042er7

ld.toString(): 2017-04-27

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154