0

I am trying to write a parsing method that will take several date patterns and will try to parse string into java.sql.date using one of them. I managed to make it work for several patterns but I struggling to make it work for 'ddMMMyyyy' pattern. This is my method:

  def parseDateFromString(
    dateString: String,
    patterns: Seq[String] = Seq("yyyy-MM-dd HH:mm:ss.nnnnnn", "yyyy-MM-dd HH:mm:ss[.SSS]", "ddMMMyyyy")
   ): Option[java.sql.Date] = {
    import java.time.format.{DateTimeFormatter, DateTimeFormatterBuilder}
    import java.time.LocalDate

    def appendPatternsToFormatter(dateTimeFormatterBuilder: DateTimeFormatterBuilder, patterns: Seq[String]): DateTimeFormatterBuilder = {
      patterns match {
        case head :: tail =>
          appendPatternsToFormatter(dateTimeFormatterBuilder.appendOptional(DateTimeFormatter.ofPattern(head)), tail)
        case Nil =>
          dateTimeFormatterBuilder
      }
    }

    if (dateString.isEmpty) return None

    val formatter = appendPatternsToFormatter(new DateTimeFormatterBuilder(), patterns).toFormatter

    val localDate = LocalDate.parse(dateString, formatter)
    Some(java.sql.Date.valueOf(localDate.toString))
  }

It properly parse values like: "2019-06-17 23:31:19.673", "2019-06-17 23:31:19.673123", "2019-06-17 23:31:19" but it fails for "01JAN2020". I am not sure why. Previously when I used joda.time it worked fine (but I had to port it over to java.time because joda.time didn't allow to parse "yyyy-MM-dd HH:mm:ss.nnnnnn"). Any ideas? Is my pattern good or am I missing something?

Test case:

 "ParseDateFromString" should "parse date string if date is in right format" in {
    val dateString = "01JAN2020"
    val expected = Some(java.sql.Date.valueOf("2020-01-01"))

    val result = parseDateFromString(dateString)

    result shouldBe expected
  }

Exception I am getting:

- should parse date string if date is in right format *** FAILED *** (140 milliseconds)
  java.time.format.DateTimeParseException: Text '01JAN2020' could not be parsed, unparsed text found at index 0
  at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
  at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
  at java.time.LocalDate.parse(LocalDate.java:400)
  at com.company.ProjectParsingUtils$.parseDateFromString(ProjectParsingUtils.scala:42)
  at com.company.ProjectParsingUtilsTest$$anonfun$1.apply(ProjectParsingUtilsTest.scala:16)
  at com.company.ProjectParsingUtilsTest$$anonfun$1.apply(ProjectParsingUtilsTest.scala:12)
  at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
  at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
  at org.scalatest.Transformer.apply(Transformer.scala:22)
  at org.scalatest.Transformer.apply(Transformer.scala:20)

Solution: By default dateTimeFormatter is case sensitive and it allows only to parse values like 01Jan2020. You can add .parseCaseInsensitive to change this behavior.

  def parseDateFromString(
    dateString: String,
    patterns: Seq[String] = Seq("yyyy-MM-dd HH:mm:ss.nnnnnn","yyyy-MM-dd HH:mm:ss.nnnnn", "yyyy-MM-dd HH:mm:ss.nnnn", "yyyy-MM-dd HH:mm:ss[.SSS]", "ddMMMyyyy", "''ddMMMyyyy''", "ddMMMyyyy:HH:mm:ss.nnnnnnnnn", "''ddMMMyyyy:HH:mm:ss.nnnnnnnnn''")
   ): Option[java.sql.Date] = {
    import java.time.format.{DateTimeFormatter, DateTimeFormatterBuilder}
    import java.time.LocalDate

    def appendPatternsToFormatter(dateTimeFormatterBuilder: DateTimeFormatterBuilder, patterns: Seq[String]): DateTimeFormatterBuilder = {
      patterns match {
        case head :: tail =>
          appendPatternsToFormatter(dateTimeFormatterBuilder.appendOptional(DateTimeFormatter.ofPattern(head)), tail)
        case Nil =>
          dateTimeFormatterBuilder
      }
    }

    if (dateString.isEmpty) return None

    val formatter = appendPatternsToFormatter(new DateTimeFormatterBuilder().parseCaseInsensitive, patterns).toFormatter
    val localDate = LocalDate.parse(dateString, formatter)
    Some(java.sql.Date.valueOf(localDate.toString))
  }
Leesrus
  • 1,095
  • 2
  • 11
  • 19
Pan Wolodyjowsky
  • 388
  • 6
  • 26
  • 2
    Have you tried to parse `"01Jan2020"`? In my IDE (Java, eclipse) it works, but the capitalized one doesn't. I think it is not a valid (parseable) format for a date. The pattern should be ok. – deHaar Mar 03 '20 at 12:46
  • 1
    Yep it works. Also as mentioned in https://stackoverflow.com/questions/36102897/java-time-format-datetimeparseexception-for-dd-mmm-yyyy-format adding .parseCaseInsensitive allows to parse 01JAN2020. val formatter = appendPatternsToFormatter(new DateTimeFormatterBuilder().parseCaseInsensitive, patterns).toFormatter – Pan Wolodyjowsky Mar 03 '20 at 12:58

0 Answers0