web-dev-qa-db-ja.com

Java.time.LocalDateで暗黙のOrderedを作成する方法

Java.time.LocalDateJava.time.LocalDateTimeを暗黙のOrderedで使用したい:

val date1 = Java.time.LocalDate.of(2000, 1, 1)
val date2 = Java.time.LocalDate.of(2010, 10, 10)
if (date1 < date2) ...

LocalDateimport 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
}

ただし、残念ながらLocalDateComparable<ChronoLocalDate>ではなくComparable<LocalDate>を実装しています。上記の暗黙の順序付けされたメソッドをLocalDate/Comparable<ChronoLocalDate>に合うように変更する方法が見つかりませんでした。何か案が?

17
Michael

Ordering.byを使用して、任意の型の順序を作成できます。その型から、既にOrderingがあるもの(この場合はLong)への関数を指定します。

implicit val localDateOrdering: Ordering[LocalDate] = Ordering.by(_.toEpochDay)
21
Tzach Zohar

これが私が使用する解決策です:

2つの暗黙を定義します。 Ordering[LocalDate]を利用可能にするための最初のもの。そして、もう1つはLocalDatecompareメソッドを与えるため、非常に便利です。通常、これらをライブラリのパッケージオブジェクトに配置し、必要な場所に含めることができます。

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

3
sfosdal

暗黙の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が必要です。

2
Jasper-M

これがJava.time.LocalDateTimeの私の解決策です

implicit val localDateTimeOrdering: Ordering[LocalDateTime] =
  Ordering.by(x => x.atZone(ZoneId.of("UTC")).toEpochSecond)
1
Alon Catz