【问题标题】:Need help on comparing DateTime through Slick在通过 Slick 比较 DateTime 时需要帮助
【发布时间】:2016-10-21 14:21:27
【问题描述】:

代码:

 def getDatasetStats(startDate: DateTime, endDate: DateTime) = {
    val query = for(created <- datasets) yield created.createdOn
    db.run(query.filter(d => d >= startDate && d <= endDate).size.result)   
  }

表:

protected class Datasets(tag: Tag) extends Table[SqlDataset](tag, "datasets") {
    // format: OFF
    def id = column[UUID]("id", O.PrimaryKey)

    def name = column[String]("name")

    def createdOn = column[DateTime]("created_on")

    def updatedOn = column[Option[DateTime]]("updated_on")

    def isPublic = column[Boolean]("public")

    def * = (id, name, createdOn, isPublic, updatedOn) <>
      ((SqlDataset.apply _).tupled, SqlDataset.unapply)

    implicit def jodaTimeMapping: BaseColumnType[DateTime] = MappedColumnType.base[DateTime, Timestamp](
      dateTime => new Timestamp(dateTime.getMillis),
      timeStamp => new DateTime(timeStamp.getTime)
    )

    // format: ON
  }

我尝试过的上述解决方案无法正常工作。我也无法使用 isBefore 或 isAfter 因为我从 DB 获取 Rep[DateTime]。我需要有关在结果之上应用日期范围过滤器的帮助。

【问题讨论】:

    标签: scala slick-3.0


    【解决方案1】:

    isBeforeisAfter 不起作用。您必须使用&lt;&lt;=&gt;&gt;=

    Slick 建立在 JDBC 之上。 JDBC 只理解java.sql.Timestamp。因此,为 joda DateTime 提供 implicit 映射列类型。

     implicit def jodaTimeMapping: BaseColumnType[DateTime] = MappedColumnType.base[DateTime, Timestamp](
        dateTime => new Timestamp(dateTime.getMillis),
        timeStamp => new DateTime(timeStamp.getTime)
      )
    

    现在您可以使用&lt;&lt;=&gt;&gt;=

    &gt; 等价于 isAfter,&lt; 等价于 isBefore。

    在与DateTime 打交道的范围内拥有implicit

    表格

    protected class Datasets(tag: Tag) extends Table[SqlDataset](tag, "datasets") {
    
    implicit def jodaTimeMapping: BaseColumnType[DateTime] = MappedColumnType.base[DateTime, Timestamp](
          dateTime => new Timestamp(dateTime.getMillis),
          timeStamp => new DateTime(timeStamp.getTime)
        )
    
    def id = column[UUID]("id", O.PrimaryKey)
    
    def name = column[String]("name")
    
    def createdOn = column[DateTime]("created_on")
    
    def updatedOn = column[Option[DateTime]]("updated_on")
    
    def isPublic = column[Boolean]("public")
    
    def * = (id, name, createdOn, isPublic, updatedOn) <>
      ((SqlDataset.apply _).tupled, SqlDataset.unapply)
    
    }
    

    方法

    def getDatasetStats(startDate: DateTime, endDate: DateTime) = {
    
    implicit def jodaTimeMapping: BaseColumnType[DateTime] = MappedColumnType.base[DateTime, Timestamp](
              dateTime => new Timestamp(dateTime.getMillis),
              timeStamp => new DateTime(timeStamp.getTime)
            )
    
      db.run(datasets.map(_.createdOn).filter(d => d >= startDate && d <= endDate).size.result)   
    }
    

    【讨论】:

    • 我尝试了上面的那个,现在我越来越喜欢 ">=" 或 "
    • @Akan 将隐式粘贴到你的表和你的方法中
    • db.run(query.filter(d =&gt; d &gt;= startDate &amp;&amp; d &lt;= endDate).size.result) d 类型现在说“d: nothing”,以前是“d:Rep[DateTime]”
    • @pamu 非常小心,new DateTime() 将使用代码执行的默认本地时区,时间戳依赖于UTC,你应该有new DateTime(timestamp.getMillis, DateTimeZone.UTC)
    • @Akan 这很简单,我每天都在使用它……我认为你在做一些花哨的事情……你能把表格代码也发布一下吗
    【解决方案2】:

    我的错。我尝试过的解决方案实际上有效。问题在于我用来将字符串转换为 DateTime 的模式转换。

    有问题的代码:

     val dtf = JDateTimeFormat.forPattern("yyyymmdd") 
    

    修改:

     val dtf = JDateTimeFormat.forPattern("yyyyMMdd")
    

    mm -> 分钟

    MM -> 月

    因为我使用小写的 mm 来提及月份,这会产生不正确的结果。现在我在更改后得到了正确的结果。

    【讨论】:

      猜你喜欢
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      相关资源
      最近更新 更多