Java.time.LocalDate
とJava.time.LocalDateTime
を暗黙のOrdered
で使用したい:
val date1 = Java.time.LocalDate.of(2000, 1, 1)
val date2 = Java.time.LocalDate.of(2010, 10, 10)
if (date1 < date2) ...
LocalDate
はimport scala.math.Ordering.Implicits._
ではなくComparable<ChronoLocalDate>
を継承するため、Comparable<LocalDate>
は機能しません。 <、<=、>、> =演算子/メソッドを使用してLocalDate
を比較する独自の暗黙のOrderdを作成するにはどうすればよいですか?
編集:
暗黙のクラスを使用する方法を見つけました:
import Java.time.{LocalDate}
object MyDateTimeUtils {
implicit class MyLocalDateImprovements(val ld: LocalDate)
extends Ordered[LocalDate] {
def compare(that: LocalDate): Int = ld.compareTo(that)
}
}
// Test
import MyDateTimeUtils._
val d1 = LocalDate.of(2016, 1, 1)
val d2 = LocalDate.of(2017, 2, 3)
if (d1 < d2) println("d1 is less than d2")
しかし、私はScalaがすべてのJava Comparable<T>
を実装するクラスに対して行うことです。あなたはimport scala.math.Ordering.Implicits._
あなたのコードScalaは次のように実装します:
implicit def ordered[A <% Comparable[A]]: Ordering[A] = new Ordering[A] {
def compare(x: A, y: A): Int = x compareTo y
}
ただし、残念ながらLocalDate
はComparable<ChronoLocalDate>
ではなくComparable<LocalDate>
を実装しています。上記の暗黙の順序付けされたメソッドをLocalDate
/Comparable<ChronoLocalDate>
に合うように変更する方法が見つかりませんでした。何か案が?
Ordering.by
を使用して、任意の型の順序を作成できます。その型から、既にOrderingがあるもの(この場合はLong
)への関数を指定します。
implicit val localDateOrdering: Ordering[LocalDate] = Ordering.by(_.toEpochDay)
これが私が使用する解決策です:
2つの暗黙を定義します。 Ordering[LocalDate]
を利用可能にするための最初のもの。そして、もう1つはLocalDate
にcompare
メソッドを与えるため、非常に便利です。通常、これらをライブラリのパッケージオブジェクトに配置し、必要な場所に含めることができます。
package object net.fosdal.oslo.odatetime {
implicit val orderingLocalDate: Ordering[LocalDate] = Ordering.by(d => (d.getYear, d.getDayOfYear))
implicit class LocalDateOps(private val localDate: LocalDate) extends AnyVal with Ordered[LocalDate] {
override def compare(that: LocalDate): Int = Ordering[LocalDate].compare(localDate, that)
}
}
これらの両方を定義すると、次のようなことができるようになります。
import net.fosdal.oslo.odatetime._
val bool: Boolean = localDate1 < localDate1
val localDates: Seq[LocalDate] = ...
val sortedSeq = localDates.sorted
あるいは...私のライブラリ(v0.4.3)を直接使用することもできます。参照してください: https://github.com/sfosdal/oslo
暗黙のordered
を少し変更するだけでうまくいくはずです。
type AsComparable[A] = A => Comparable[_ >: A]
implicit def ordered[A: AsComparable]: Ordering[A] = new Ordering[A] {
def compare(x: A, y: A): Int = x compareTo y
}
これで、それ自体またはそれ自体のスーパータイプに相当するすべての型にOrdering
が必要です。
これがJava.time.LocalDateTime
の私の解決策です
implicit val localDateTimeOrdering: Ordering[LocalDateTime] =
Ordering.by(x => x.atZone(ZoneId.of("UTC")).toEpochSecond)