我想使用隐含java.time.LocalDate
的{{1}}和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) ...
不起作用,因为import scala.math.Ordering.Implicits._
继承自LocalDate
而不是Comparable<ChronoLocalDate>
。
我怎样才能编写自己的非显式Orderd来使用&lt;,&lt; =,&gt;,&gt; =运算符/方法来比较Comparable<LocalDate>
的?
编辑:
我找到了一种使用隐式类的方法:
LocalDate
但我更喜欢像Scala那样为所有实现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")
的Java类做的事情。你只需要
代码中的Comparable<T>
。 Scala实现它:
import scala.math.Ordering.Implicits._
但遗憾的是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
的方法。有什么想法吗?
答案 0 :(得分:16)
您可以使用Ordering.by
为任何类型创建排序,从该类型的函数到已经有订单的函数 - 在本例中为Long
:
implicit val localDateOrdering: Ordering[LocalDate] = Ordering.by(_.toEpochDay)
答案 1 :(得分:10)
LocalDate.toEpochDay
很明显,但可能相对较慢...... answer by @tzach-zohar很棒,因为它最明显的是什么;你是在大纪元日订购的:
implicit val localDateOrdering: Ordering[LocalDate] = Ordering.by(_.toEpochDay)
但是,如果您查看implementation of toEpochDay
,您会看到它相对复杂 - 18行代码,4个分区,3个条件和isLeapYear()
调用 - 并且结果值不是没有缓存,因此每次比较都会重新计算,如果要对大量LocalDate
进行排序,这可能会很昂贵。
LocalDate.compareTo
可能更具性能...... implementation of LocalDate.compareTo
更简单 - 只有2个条件,没有除法 - 这就是scala.math.Ordering.Implicits._
所提供的java.lang.Comparable
to scala.math.Ordering
的隐式转换所带来的,只要它有效!但正如你所说,它没有,因为LocalDate
继承自Comparable<ChronoLocalDate>
而不是Comparable<LocalDate>
。利用它的一种方法可能是......
import scala.math.Ordering.Implicits._
implicit val localDateOrdering: Ordering[LocalDate] =
Ordering.by(identity[ChronoLocalDate])
...这可让您通过将LocalDate
投放到ChronoLocalDate
来订购Ordering[ChronoLocalDate]
,并使用scala.math.Ordering.Implicits._
为您提供的new Ordering
!
Scala 2.12引入的lambda syntax for SAM types可以简化构建implicit val localDateOrdering: Ordering[LocalDate] = _ compareTo _
的工作:
parquet-tools merge
......我认为这最终成为我个人的最爱!简洁,仍然相当清楚,并使用(我认为)表现最佳的比较方法。
答案 2 :(得分:3)
以下是我使用的解决方案:
定义两个含义。第一个使Ordering[LocalDate]
可用。第二个是给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
答案 3 :(得分:1)
这是我对java.time.LocalDateTime
的解决方案
implicit val localDateTimeOrdering: Ordering[LocalDateTime] =
Ordering.by(x => x.atZone(ZoneId.of("UTC")).toEpochSecond)
答案 4 :(得分:0)
对隐式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
。