我正在寻找一个干净的解决方案来在Play框架中使用datetime。具体来说,我需要在数据库中保留datetime,将该datetime转换为Scala对象,并将该datetime转换为Json和从Json转换。
例如,我正在制作像eBay这样的竞价服务,所以我希望保持创建项目的时间,以及竞标时间结束的时间。我有一个这样的简单模型:
case class Item(name: String, description: String, start: DateTime, end: DateTime)
由于Slick不支持Joda DateTime,我使用MappedColumnType在java.sql.Timestamp和Joda DateTime之间进行转换。这是微不足道的,但如果有更好的解决方案我会很感激。
我之所以使用Joda DateTime而不是java.sql.Timestamp是因为Play现在知道如何将时间戳写入Json,而我在网上找到的所有解决方案都需要大量修补代码。
随着Joda DateTime到位,我又遇到了另一个问题。播放将DateTime写为长号,这很好,但首选完整格式日期。问题是客户端只能在没有时间和时区的情况下将DateTime提交为“yyyy-MM-dd”。
到目前为止,这是我的尝试:
implicit val itemFormatter = (
(__ \ "ean").format[Long] and
(__ \ "description").format[String] and
(__ \ "start").format[DateTime] and
(__ \ "end").format[DateTime]
)(Item.apply _, unlift(Item.unapply))
val userDateFormatter = "dd/MM/yyyy HH:mm:ss"
implicit val jodaDateTimeReads = Reads.jodaDateReads(userDateFormatter)
implicit val jodaDateTimeWrites = Writes.jodaDateWrites(userDateFormatter)
implicit val jodaDateTimeFormats = Format(jodaDateTimeReads, jodaDateTimeWrites)
尝试使用上述格式发布时间时收到的错误消息是:
error.expected.jodadate.format,WrappedArray(yyyy-MM-dd)
这在Ruby / Rails等其他langs /框架中似乎是一件微不足道的事情,但我觉得Scala严重缺乏日期和时间支持。
答案 0 :(得分:3)
我找到了一个简单的解决方案。基本上我必须覆盖DateTime的默认读取和写入,如下所示:
# If you use Timestamp
implicit val tsreads: Reads[Timestamp] = Reads.of[Long] map (new Timestamp(_))
implicit val tswrites: Writes[Timestamp] = Writes { (ts: Timestamp) => JsString(ts.toString)}
# If you use DateTime
implicit val tsreads: Reads[DateTime] = Reads.of[String] map (new DateTime(_))
implicit val tswrites: Writes[DateTime] = Writes { (dt: DateTime) => JsString(dt.toString)}