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

eu.shiftforward.apso.time.Implicits.scala Maven / Gradle / Ivy

There is a newer version: 0.13.11
Show newest version
package eu.shiftforward.apso.time

import org.joda.time.ReadableInterval
import com.github.nscala_time.time.Imports._

/**
 * Object containing implicit classes and methods related to datetime libraries.
 */
object Implicits {

  /**
   * Implicit class that provides new methods for `LocalDates`.
   * @param d1 the `LocalDate` to which the new methods are provided.
   */
  implicit class ApsoTimeLocalDate(val d1: LocalDate) extends AnyVal {

    /**
     * Returns a `DateTime` corresponding to this `LocalDate` at UTC midnight.
     * @return a `DateTime` corresponding to this `LocalDate` at UTC midnight.
     */
    def utcDateTime: DateTime = d1.toDateTime(new LocalTime(0, 0), DateTimeZone.UTC)

    /**
     * Returns a `DateTime` corresponding to this `LocalDate` at the latest valid
     * time for the date.
     * @return a `DateTime` corresponding to this `LocalDate` at the latest valid
     *         time for the date.
     */
    def toDateTimeAtEndOfDay =
      (d1 + 1.day).toDateTimeAtStartOfDay - 1.millis

    /**
     * Returns a `DateTime` corresponding to this `LocalDate` at the latest valid
     * time for the date on the given `DateTimeZone`.
     * @param tz the target `DateTimeZone` for the returned `DateTime`
     * @return a `DateTime` corresponding to this `LocalDate` at the latest valid
     *         time for the date on the given `DateTimeZone`.
     */
    def toDateTimeAtEndOfDay(tz: DateTimeZone) =
      (d1 + 1.day).toDateTimeAtStartOfDay(tz) - 1.millis

    /**
     * Returns an iterable interval starting at this `LocalDate` (inclusive) and
     * ending at the given `LocalDate` (inclusive), with a 1 day step.
     * @param d2 the ending `LocalDate`
     * @return an iterable interval starting at this `LocalDate` (inclusive) and
     *         ending at the given `LocalDate` (inclusive), with a 1 day step.
     */
    def to(d2: LocalDate) =
      LocalDateInterval(
        IterableInterval(d1.toDateTimeAtStartOfDay to d2.toDateTimeAtStartOfDay, 1.day, true))

    /**
     * Returns an iterable interval starting at this `LocalDate` (inclusive) and
     * ending at the given `LocalDate` (exclusive), with a 1 day step.
     * @param d2 the ending `LocalDate`
     * @return an iterable interval starting at this `LocalDate` (inclusive) and
     *         ending at the given `LocalDate` (exclusive), with a 1 day step.
     */
    def until(d2: LocalDate) =
      LocalDateInterval(
        IterableInterval(d1.toDateTimeAtStartOfDay to d2.toDateTimeAtStartOfDay, 1.day, false))
  }

  /**
   * Implicit class that provides new methods for `DateTimes`.
   * @param d1 the `DateTime` to which the new methods are provided.
   */
  final implicit class ApsoTimeDateTime(val d1: DateTime) extends AnyVal {

    /**
     * Returns a `LocalDate` corresponding to this `DateTime` at UTC.
     * @return a `LocalDate` corresponding to this `DateTime` at UTC.
     */
    def utcLocalDate: LocalDate = d1.withZone(DateTimeZone.UTC).toLocalDate

    /**
     * Returns `true` if the given `DateTime` is in the same day as this.
     * @param d2 the second `DateTime`
     * @return `true` if the given `DateTime` is in the same day as this,
     *         `false` othwerwise.
     */
    def isSameDay(d2: DateTime) = d1.year == d2.year && d1.dayOfYear == d2.dayOfYear

    /**
     * Retuns `true` if this `DateTime` is in the range between the two given
     * `DateTimes`.
     * @param dStart the starting `DateTime`
     * @param dEnd the ending `DateTime`
     * @return `true` if this `DateTime` is in the range between the two given
     *         `DateTimes`, `false` otherwise.
     */
    def between(dStart: DateTime, dEnd: DateTime) = dStart < d1 && d1 < dEnd

    /**
     * Returns an iterable interval starting at this `DateTime` (inclusive) and
     * ending at the given `DateTime` (exclusive), with a 1 day step.
     * @param d2 the ending `DateTime`
     * @return an iterable interval starting at this `DateTime` (inclusive) and
     *         ending at the given `DateTime` (exclusive), with a 1 day step.
     */
    def until(d2: DateTime) = IterableInterval(d1 to d2, 1.day, false)
  }

  /**
   * Implicit class that provides new methods for `ReadableIntervals`.
   * @param interval the `ReadableInterval` to which the new methods are provided.
   */
  final implicit class ApsoTimeInterval(val interval: ReadableInterval) extends AnyVal {

    /**
     * Partitions this time interval into a given number of equal subintervals.
     * @param n the number of subintervals to return
     * @return a sequence of time intervals resultant of the division of this
     *         interval in `n` equal parts.
     */
    def split(n: Int): Seq[ReadableInterval] = {
      require(n >= 0, "n must not be negative")
      if (n == 0) Seq.empty
      else {
        val q = (interval.millis / n).toInt
        (0 until n).map { i => (interval.getStart + q * i + i) to (interval.getStart + q * (i + 1) + i) }
      }
    }
  }

  /**
   * Implicit method that allows whe view of a time interval as an indexed
   * sequence. Time intervals are split with a 1 day step.
   * @param interval the time interval to be iterated over
   * @return an iterable time interval.
   */
  implicit def intervalToStepped(interval: ReadableInterval) = IterableInterval(interval, 1.day)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy