This is an excerpt from the Scala Cookbook, 2nd Edition. This is Recipe 3.12, How to Parse Scala Strings Into Dates.
Problem
While using Scala (Scala 2 or 3), you need to parse a Scala String
into one of the date/time types introduced in Java 8, and still used in Java 11, 14, 17, etc.
Scala Solution
If your String
is already in the expected format, pass it to the parse
method of the desired class. If the String
is not in the expected (default) format, create a formatter to define the format you want to accept. The following examples demonstrate the expected formats, and other solutions.
Scala and LocalDate
This example shows the default format for java.time.LocalDate:
import java.time.LocalDate
val d = LocalDate.parse("2020-12-10") // LocalDate = 2020-12-10
If you try to pass a string into parse
with the wrong format, you’ll get an exception:
val d = LocalDate.parse("2020/12/10") // java.time.format.DateTimeParseException
To accept a string in a different format, create a formatter for the desired pattern:
import java.time.format.DateTimeFormatter
val df = DateTimeFormatter.ofPattern("yyyy/MM/dd")
val d = LocalDate.parse("2020/12/10", df) // LocalDate = 2020-12-10
Scala and LocalTime
These examples demonstrate the default format for java.time.LocalTime:
import java.time.LocalTime
val t = LocalTime.parse("01:02") //01:02
val t = LocalTime.parse("13:02:03") //13:02:03
Notice that each field requires a leading 0
:
val t = LocalTime.parse("1:02") //java.time.format.DateTimeParseException
val t = LocalTime.parse("1:02:03") //java.time.format.DateTimeParseException
These examples demonstrate several ways of using formatters:
import java.time.format.DateTimeFormatter
LocalTime.parse("00:00", DateTimeFormatter.ISO_TIME)
// 00:00
LocalTime.parse("23:59", DateTimeFormatter.ISO_LOCAL_TIME)
// 23:59
LocalTime.parse("23 59 59", DateTimeFormatter.ofPattern("HH mm ss"))
// 23:59:59
LocalTime.parse("11 59 59 PM", DateTimeFormatter.ofPattern("hh mm ss a"))
// 23:59:59
Scala/LocalDateTime
This example demonstrates the default format for java.time.LocalDateTime:
import java.time.LocalDateTime
val s = "2021-01-01T12:13:14"
val ldt = LocalDateTime.parse(s) // LocalDateTime = 2021-01-01T12:13:14
These examples demonstrate several ways of using formatters:
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
val s = "1999-12-31 23:59"
val f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
val ldt = LocalDateTime.parse(s, f)
// 1999-12-31T23:59
val s = "1999-12-31 11:59:59 PM"
val f = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a")
val ldt = LocalDateTime.parse(s, f)
// 1999-12-31T23:59:59
Scala/Instant
java.time.Instant only has one parse
method that requires a date/time stamp in the proper format:
import java.time.Instant
Instant.parse("1970-01-01T00:01:02.00Z") // 1970-01-01T00:01:02Z
Instant.parse("2021-01-22T23:59:59.00Z") // 2021-01-22T23:59:59Z
Scala/ZonedDateTime
These examples demonstrate the default formats for java.time.ZonedDateTime:
import java.time.ZonedDateTime
ZonedDateTime.parse("2020-12-31T23:59:59-06:00")
// ZonedDateTime = 2020-12-31T23:59:59-06:00
ZonedDateTime.parse("2020-12-31T23:59:59-00:00[US/Mountain]")
// ZonedDateTime = 2020-12-31T16:59:59-07:00[US/Mountain]
These examples demonstrate several ways of using formatters with ZonedDateTime
:
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter._
val zdt = ZonedDateTime.parse("2021-01-01T01:02:03Z", ISO_ZONED_DATE_TIME)
// ZonedDateTime = 2021-01-01T01:02:03Z
ZonedDateTime.parse("2020-12-31T23:59:59+01:00", ISO_DATE_TIME)
// ZonedDateTime = 2020-12-31T23:59:59+01:00
ZonedDateTime.parse("2020-02-29T00:00:00-05:00", ISO_OFFSET_DATE_TIME)
// ZonedDateTime = 2020-02-29T00:00-05:00
ZonedDateTime.parse("Sat, 29 Feb 2020 00:01:02 GMT", RFC_1123_DATE_TIME)
// ZonedDateTime = 2020-02-29T00:01:02Z
Be aware that an improper date (or improperly formatted date) will throw an exception:
ZonedDateTime.parse("2021-02-29T00:00:00-05:00", ISO_OFFSET_DATE_TIME)
// java.time.format.DateTimeParseException: Text '2021-02-29T00:00:00-05:00'
// could not be parsed: Invalid date 'February 29' as '2021' is not a leap year
ZonedDateTime.parse("Fri, 29 Feb 2020 00:01:02 GMT", RFC_1123_DATE_TIME)
// java.time.format.DateTimeParseException: Text
// 'Fri, 29 Feb 2020 00:01:02 GMT' could not be parsed: Conflict found:
// Field DayOfWeek 6 differs from DayOfWeek 5 derived from 2020-02-29
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
In summary, if you’re using Scala 2 or Scala3, and you need to parse a string into one of the date/time types introduced in Java 8, I hope this is helpful.