doobie
doobie copied to clipboard
doobie.implicits.javatime includes time/date formats that can conflict
I have a class
// This exists in an internal library
case class CustomDateTime(v: ZonedDateTime) {
def someConversion: NewType = ???
}
// This is in my application
object SomewhereInMyApplication {
private def toOffsetDateTime(cdt: CustomDateTime): OffsetDateTime =
OffsetDateTime.ofInstant(cdt.timestamp.toInstant, ZoneId.of("UTC"))
private def fromOffsetDateTime(ofdt: OffsetDateTime): CustomDateTime = {
CustomDateTime(ofdt.toZonedDateTime)
}
implicit val cDateTimePut: Put[CustomDateTime] = Put[OffsetDateTime].tcontramap(toOffsetDateTime)
implicit val cDateTimeGet: Get[CustomDateTime] = Get[OffsetDateTime].map(fromOffsetDateTime)
}
When writing a larger type T
to the DB that includes a parameter of type CustomDateTime
, it's easy to get into tricky implicit scoping scenarios with doobie.implicits.javatime._
, since that includes many different time formats.
It would be useful to ensure that the OffsetDateTime
instance is available to be imported without importing the ZonedDateTime
instance.
Hi do you still get the issue if you put the Put/Get instances into the CustomDateTime
companion object?
(Even if you import it explicitly it should still work fine. A simple repo to demonstrate the issue would help)
Hi do you still get the issue if you put the Put/Get instances into the
CustomDateTime
companion object?(Even if you import it explicitly it should still work fine. A simple repo to demonstrate the issue would help)
This was what my solution was.
So I think this is resolved? I couldn't quite figure out whether there's an actual issue because what you were describing in the opening post doesn't really fit my understanding of how implicit resolution work (which is why I asked for a small reproduction).
If an implicit for a type exists in scope (either through implicit scope from companion object or explicitly imported) it should always be used by the compiler.
Context: https://gitter.im/tpolecat/doobie?at=5fd78c783646a85814ebb046
I think the issue is that if the custom implicit isn't defined on the companion object, but is imported, that it seems to prefer picking the derived instance instead of the custom one. I'm not fully sure.
The wider point is that right now, postgres users can't import the OffsetDateTime
instance without importing the invalid-for-postgres ZonedDateTime
instance, unless they import a single named field. That's pretty awful for UX, especially since the docs and all material you can find will point you to use the wildcard imports