All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sksamuel.elastic4s.ElasticDate.scala Maven / Gradle / Ivy

There is a newer version: 8.15.1
Show newest version
package com.sksamuel.elastic4s

import com.sksamuel.elastic4s.ElasticDate.{ElasticDateMathShow, TimestampElasticDateShow, UnparsedElasticDateShow}
import com.sksamuel.elastic4s.ext.OptionImplicits._

import java.time.LocalDate
import java.time.format.DateTimeFormatter
import scala.language.implicitConversions

abstract class TimeUnit(val symbol: String)
case object Years   extends TimeUnit("y")
case object Months  extends TimeUnit("M")
case object Weeks   extends TimeUnit("w")
case object Days    extends TimeUnit("d")
case object Hours   extends TimeUnit("h")
case object Minutes extends TimeUnit("m")
case object Seconds extends TimeUnit("s")

case class Adjustment(value: Int, unit: TimeUnit)

/**
  * Implementations of this trait are used to represent dates and date math
  * in elasticsearch requests.
  *
  * see https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math
  *
  * There are three types of elastic date you can create.
  *
  * The first is just a wrapped string with no extra help: UnparsedElasticDate("mydate||/d")
  *
  * The second is a wrapped timestamp: TimestampElasticDate(1113232321L)
  *
  * The third and most useful is the ElasticDateMath which allows you to programatically add
  * or subtract values, as well as add a rounding, and it will create the appropriate date string for you.
  * For example, ElasticDate.now.minus(3, Months).add(1, Days).rounding(Weeks)
  */
trait ElasticDate {
  def show: String
}

case class ElasticDateMath(base: String, adjustments: Seq[Adjustment] = Nil, rounding: Option[TimeUnit] = None)
    extends ElasticDate {
  override def show: String                                 = ElasticDateMathShow.show(this)
  def add(value: Int, unit: TimeUnit): ElasticDateMath      = copy(adjustments = adjustments :+ Adjustment(value, unit))
  def minus(value: Int, unit: TimeUnit): ElasticDateMath    = subtract(value, unit)
  def subtract(value: Int, unit: TimeUnit): ElasticDateMath = add(-value, unit)
  def rounding(unit: TimeUnit): ElasticDateMath             = copy(rounding = unit.some)
}

case class UnparsedElasticDate(value: String) extends ElasticDate {
  override def show: String = UnparsedElasticDateShow.show(this)
}

case class TimestampElasticDate(timestamp: Long) extends ElasticDate {
  override def show: String = TimestampElasticDateShow.show(this)
}

object ElasticDate {

  implicit object UnparsedElasticDateShow extends Show[UnparsedElasticDate] {
    override def show(t: UnparsedElasticDate): String = t.value
  }

  implicit object TimestampElasticDateShow extends Show[TimestampElasticDate] {
    override def show(t: TimestampElasticDate): String = t.timestamp.toString
  }

  implicit object ElasticDateMathShow extends Show[ElasticDateMath] {
    override def show(t: ElasticDateMath): String =
      (t.base match {
        case "now" => "now"
        case date  => s"$date||"
      }) + t.adjustments
        .map { adj =>
          val plus = if (adj.value < 0) "" else "+"
          s"$plus${adj.value}${adj.unit.symbol}"
        }
        .mkString("") + t.rounding.fold("")(unit => s"/${unit.symbol}")
  }

  implicit def fromTimestamp(timestamp: Long): TimestampElasticDate = TimestampElasticDate(timestamp)
  implicit def stringToDate(str: String): ElasticDate               = UnparsedElasticDate(str)

  def apply(str: String): ElasticDateMath     = ElasticDateMath(str)
  def now: ElasticDateMath                    = ElasticDateMath("now")
  def apply(date: LocalDate): ElasticDateMath = ElasticDateMath(date.format(DateTimeFormatter.ISO_LOCAL_DATE))
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy