Skip to content

Instantly share code, notes, and snippets.

@fsvehla
Created February 21, 2016 16:39
Show Gist options
  • Save fsvehla/919f238ca77247b2b04f to your computer and use it in GitHub Desktop.
Save fsvehla/919f238ca77247b2b04f to your computer and use it in GitHub Desktop.
package json
import java.time.format.{DateTimeFormatter, DateTimeParseException}
import java.time.{Instant, LocalDateTime, ZoneId, ZonedDateTime}
import cats.data.Xor
import io.circe.{Decoder, DecodingFailure, HCursor}
object JsonInstances {
/** f.ex. 'Europe/Vienna' */
implicit val zoneId: Decoder[ZoneId] = Decoder.instance { cursor ⇒
for {
string ← cursor.as[String]
zoneId ← wrap(Xor.catchOnly[RuntimeException] {
ZoneId.of(string)
}, cursor)
} yield zoneId
}
/** This assume ISO8601 formatted times, so it is not imported automatically */
object alaCarte {
final private val iso8601formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME
implicit val decodeIso8601LocalDateTime: Decoder[LocalDateTime] = Decoder.instance { cursor ⇒
for {
string ← cursor.as[String]
datetime ← wrap(Xor.catchOnly[DateTimeParseException] {
iso8601formatter.parse(string)
}, cursor)
} yield LocalDateTime.from(datetime)
}
implicit val decodeIso8601ZonedDateTime: Decoder[ZonedDateTime] = Decoder.instance { cursor ⇒
for {
string ← cursor.as[String]
datetime ← wrap(Xor.catchOnly[DateTimeParseException] {
iso8601formatter.parse(string)
}, cursor)
} yield ZonedDateTime.from(datetime)
}
implicit val decodeIso8601Instant: Decoder[Instant] = Decoder.instance { cursor ⇒
for {
string ← cursor.as[String]
datetime ← wrap(Xor.catchOnly[DateTimeParseException] {
iso8601formatter.parse(string)
}, cursor)
} yield Instant.from(datetime)
}
}
private def wrap[L <: RuntimeException, R](xor: Xor[L, R], cursor: HCursor) =
xor.leftMap(t ⇒ DecodingFailure(t.getMessage, cursor.history))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment