3

私は次の問題で立ち往生しています: json への変換と json からの変換が対称であることを主張する specs2 仕様を書きたいです。ただし、joda 日時の日付でエラーが発生します。

'2012-04-17T00:04:00.000+02:00' is not equal to '2012-04-17T00:04:00.000+02:00'. Values have the same string representation but possibly different types like List[Int] and List[String] (TimeSpecs.scala:18) 

これは、問題を示す最小限の仕様です

import org.joda.time.DateTime
import org.specs2.mutable.Specification

class TimeSpecs extends Specification {
  "joda and specs2" should {
    "play nice" in {
      val date = DateTime.parse("2012-04-17T00:04:00+0200")
      val date2 = DateTime.parse("2012-04-17T00:04:00+0200")
      date === date2
    }
    "play nice through play json transform" in {
      import play.api.libs.json._
      import play.api.libs.json.Json._
      val date = DateTime.parse("2012-04-17T00:04:00+0200")
      val jsDate= toJson(date)
      val date2= jsDate.as[DateTime]

      date === date2
    }
  }
}

2 番目のテストで date と date2 を比較するにはどうすればよいですか? それらは同じですが、specs2はそれを認識していないようです:(

- - 編集

date.getClass.getCanonicalName を使用して実行時に型を「手動で」検査すると、期待どおりに org.joda.time.Datetime が返されます

import org.joda.time.DateTime
import org.specs2.mutable.Specification

class TimeSpecs extends Specification {
  "joda and specs2" should {
    "play nice" in {
      val date = DateTime.parse("2012-04-17T00:04:00+0200")
      val date2 = DateTime.parse("2012-04-17T00:04:00+0200")
      date === date2
    }
    "play nice through play json transform" in {
      import play.api.libs.json._
      import play.api.libs.json.Json._
      val date:DateTime = DateTime.parse("2012-04-17T00:04:00+0200")
      val jsDate= toJson(date)
      val date2:DateTim= jsDate.as[DateTime]
      println(date.getClass.getCanonicalName) //prints org.joda.time.DateTime
      println(date2.getClass.getCanonicalName)//prints org.joda.time.DateTime
      date === date2
    }
  }
}

DateTime#isEqual を使用するとある程度は機能しますが、流暢なマッチャーの利点と、それらがもたらす有用なエラー メッセージを失います。さらに、私が実際に比較しようとしているのは、日付自体ではなく、たまたま日付を含むケース クラス インスタンスです。

使用する

      date should beEqualTo(date2)

と同じエラーが発生します===

4

1 に答える 1

2

問題は、joda time が非常に厳密な equals を定義し、日付の Chronology を等価と見なすことです ( DateTime#getChronology )。Kim Stebel によって提案された isEqual メソッドは Chronology を無視します。

そこから、次の 2 つの可能性があります: 次の例のように、再生用にカスタムの読み取りと書き込みを定義し、同じパターンを使用して日付を作成します。

import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import org.specs2.mutable.Specification

class TimeSpecs extends Specification {
    val pattern = "yyyy-MM-dd'T'HH:mm:ssZZ"
  "joda and specs2" should {
    "play nice" in {
      val date = DateTime.parse("2012-04-17T00:04:00+0200",DateTimeFormat.forPattern(pattern))
      val date2 = DateTime.parse("2012-04-17T00:04:00+0200",DateTimeFormat.forPattern(pattern))
      date === date2
    }
    "play nice through play json transform" in {
      import play.api.libs.json.Json._

      //play2 custom write
      implicit def customJodaWrite = play.api.libs.json.Writes.jodaDateWrites(pattern)
      //play2 custom read
      implicit def customJodaRead = play.api.libs.json.Reads.jodaDateReads(pattern) 


      val date:DateTime = DateTime.parse("2012-04-17T00:04:00+0200",DateTimeFormat.forPattern(pattern)) //make sure you parse the initial date with the same pattern
      val jsDate= toJson(date)
      val date2:DateTime= jsDate.as[DateTime]

      println(date.getClass.getCanonicalName)
      println(date2.getClass.getCanonicalName)
      println(jsDate)
      date should beEqualTo(date2)
    }
  }
}

Play 2.1 はデフォルトで、タイムゾーン情報なしのミリ秒単位の unix タイムスタンプに基づいて解析 (および json への書き込み) を行います。UNIXタイムスタンプから解析するとき、ローカルコンピューターのタイムゾーン(私の場合はヨーロッパ/パリ)で考慮されます。したがって、カスタム パーサー/ライターの必要性

Joda は、パーサー引数なしで parse を呼び出すときに特定のフォーマッターを使用します。パターン文字列のみで同じフォーマッターを作成することはできないようです (パターン文字列を介して DateTimeFormatter#withOffsetParsed メソッドをアクティブにする方法が見つかりませんでした)。

別の可能性として、equals の代わりに isEqual を使用する jodatime のカスタム specs2 マッチャーを定義することもできます。いずれにせよ、json に unix エポックを入れたくないので、カスタム プレイ トランスフォーマーを使い続けます。

于 2012-12-26T15:57:26.523 に答える