Search code examples
scaladatetimeplayframework-2.0anorm

Play framework - Using anorm with Option[LocalDate] \ Option[LocalDateTime]


I am trying to define a nullable date field in postgres, while using anorm as connection to the database.

I am trying to update an entry:

def update(id: Long, startTime: Option[LocalDate]){
   SQL("""UPDATE my_table
        |SET start_date = {start_date}
        |WHERE id = {id}
      """.stripMargin)
      .on(
        'id ->id,
        'start_date -> startDate,
      ).executeUpdate()
 }

But I get a compilation error, looks like anorm can't handle Option[DateTime], although when I configured a parser it works form me:

val parser: RowParser[Info] = {
  get[Long]("id") ~
  get[Option[DateTime]]("start_date") map {
  case id ~ startTime => Info(id, startDate)
}

}

What am I missing here? Thanks!


Solution

  • I added my own implicit definitions:

    implicit def rowToLocalDate: Column[LocalDate] = Column.nonNull {(value, meta) =>
       val MetaDataItem(qualified, nullable, clazz) = meta
       value match {
          case ts: java.sql.Timestamp => Right(new LocalDate(ts.getTime))
          case d: java.sql.Date => Right(new LocalDate(d.getTime))
          case str: java.lang.String => Right(fmt.parseLocalDate(str))
          case _ => Left(TypeDoesNotMatch("Cannot convert " + value + ":" + value.asInstanceOf[AnyRef].getClass) )
    }
    

    }

    implicit val localDateToStatement = new ToStatement[LocalDate] {
        def set(s: java.sql.PreparedStatement, index: Int, aValue: LocalDate): Unit = {
           s.setTimestamp(index, new java.sql.Timestamp(aValue.toDateTimeAtStartOfDay().getMillis()))
    }
    

    }

    And the relevant ParameterMetaData

    implicit object LocalDateClassMetaData extends  ParameterMetaData[LocalDate] {
       val sqlType = ParameterMetaData.DateParameterMetaData.sqlType
       val jdbcType = ParameterMetaData.DateParameterMetaData.jdbcType
    }
    

    That made the trick