Created
June 20, 2018 11:02
-
-
Save danslapman/6d98ea29596b57715907fae2ce9cc1fd to your computer and use it in GitHub Desktop.
JSR310 custom formatters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.time._ | |
import java.time.format.{DateTimeFormatter, DateTimeFormatterBuilder} | |
import java.time.temporal.{ChronoField, TemporalAccessor} | |
import java.{time => jt} | |
import scala.util.Try | |
trait ZonedParser { | |
protected val formatter: DateTimeFormatter | |
def apply(date: String): ZonedDateTime = ZonedDateTime.parse(date, formatter) | |
def unapply(date: String): Option[ZonedDateTime] = Try {this(date)}.toOption | |
def unapply(date: Option[String]): Option[ZonedDateTime] = date flatMap unapply | |
} | |
case class ZonedDateTimeParser(pattern: String) extends ZonedParser { | |
protected override val formatter: DateTimeFormatter = new DateTimeFormatterBuilder() | |
.appendPattern(pattern) | |
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0) | |
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) | |
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) | |
.toFormatter | |
.withZone(JSR310.systemDefaultZone) | |
} | |
trait OffsetParser { | |
protected val formatter: DateTimeFormatter | |
def apply(date: String): OffsetDateTime = OffsetDateTime.parse(date, formatter) | |
def unapply(date: String): Option[OffsetDateTime] = Try {this(date)}.toOption | |
def unapply(date: Option[String]): Option[OffsetDateTime] = date flatMap unapply | |
} | |
trait OffsetParserWithDefaults extends OffsetParser { | |
protected val localTime: LocalTime | |
protected val offset: ZoneOffset | |
override def apply(date: String): OffsetDateTime = formatter.parseBest( | |
date, | |
(temporal: TemporalAccessor) => OffsetDateTime.from(temporal), | |
(temporal: TemporalAccessor) => LocalDateTime.from(temporal), | |
(temporal: TemporalAccessor) => LocalDate.from(temporal)) match { | |
case odt: OffsetDateTime => odt | |
case ldt: LocalDateTime => OffsetDateTime.of(ldt, offset) | |
case ld: LocalDate => OffsetDateTime.of(ld, localTime, offset) | |
} | |
} | |
case class OffsetDateTimeParser( | |
pattern: String, | |
protected val localTime: LocalTime = LocalTime.MIDNIGHT, | |
protected val offset: ZoneOffset = ZoneOffset.UTC) extends OffsetParserWithDefaults { | |
protected override val formatter: DateTimeFormatter = new DateTimeFormatterBuilder() | |
.appendPattern(pattern) | |
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0) | |
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) | |
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) | |
.toFormatter | |
} | |
object ISO8601Zoned extends ZonedParser { | |
override protected val formatter: DateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME.withZone(systemDefaultZone) | |
} | |
object ISO8601Offset extends OffsetParserWithDefaults { | |
override protected val localTime: LocalTime = LocalTime.MIDNIGHT | |
override protected val offset: ZoneOffset = ZoneOffset.UTC | |
override protected val formatter: DateTimeFormatter = new DateTimeFormatterBuilder() | |
.parseCaseInsensitive() | |
.append(DateTimeFormatter.ISO_LOCAL_DATE) | |
.optionalStart().appendLiteral("T").append(DateTimeFormatter.ISO_LOCAL_TIME).optionalEnd() | |
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() | |
.optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() | |
.optionalStart().appendOffset("+HH", "Z").optionalEnd() | |
.optionalStart().appendLiteral('[').parseCaseSensitive().appendZoneRegionId().appendLiteral(']') | |
.toFormatter() | |
} | |
val ISO8601UTCLocal: DateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneOffset.UTC) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment