alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (TimeHelpers.scala)

This example Lift Framework source code file (TimeHelpers.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

b, date, date, datetime, int, left, long, long, period, right, right, string, text, timespan, timespan, util

The Lift Framework TimeHelpers.scala source code

/*
 * Copyright 2006-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.liftweb
package util

import java.text.SimpleDateFormat
import java.util.{TimeZone, Calendar, Date, Locale}
import common._
import org.joda.time.{DateTime, Duration, Period, PeriodType}

/**
 * The TimeHelpers object extends the TimeHelpers. It can be imported to access all of the trait functions.
 */
object TimeHelpers extends TimeHelpers with ControlHelpers with ClassHelpers

/**
 * The TimeHelpers trait provide functions to create TimeSpans (an object representing an amount of time), to manage date formats
 * or general utility functions (get the date for today, get year/month/day number,...)
 */
trait TimeHelpers { self: ControlHelpers =>
  // Logger must be lazy, since we cannot instantiate until after boot is complete
  private  lazy val logger = Logger(classOf[TimeHelpers])

  /** private variable allowing the access to all TimeHelpers functions from inside the TimeSpan class */
  private val outer = this

  /** transforms a long to a TimeSpanBuilder object. Usage: 3L.seconds returns a TimeSpan of 3000L millis  */
  implicit def longToTimeSpanBuilder(in: Long): TimeSpanBuilder = TimeSpanBuilder(in)

  /** transforms an int to a TimeSpanBuilder object. Usage: 3.seconds returns a TimeSpan of 3000L millis  */
  implicit def intToTimeSpanBuilder(in: Int): TimeSpanBuilder = TimeSpanBuilder(in)

  /** transforms a long to a TimeSpan object. Usage: 3000L returns a TimeSpan of 3000L millis  */
  implicit def longToTimeSpan(in: Long): TimeSpan = TimeSpan(in)

  /** transforms an int to a TimeSpan object. Usage: 3000 returns a TimeSpan of 3000L millis  */
  implicit def intToTimeSpan(in: Int): TimeSpan = TimeSpan(in)

  private implicit def durToPeriod(dur: Duration): Period = dur.toPeriod(PeriodType.standard())

  /** class building TimeSpans given an amount (len) and a method specify the time unit  */
  case class TimeSpanBuilder(val len: Long) {
    def seconds = new TimeSpan(Right((new Period).plusSeconds(len.toInt)))
    def second = seconds
    def minutes = new TimeSpan(Right((new Period).plusMinutes(len.toInt)))
    def minute = minutes
    def hours = new TimeSpan(Right(Duration.standardHours(len): Period))
    def hour = hours
    def days = new TimeSpan(Right(Duration.standardDays(len): Period))
    def day = days
    def weeks = new TimeSpan(Right(Duration.standardDays(len * 7L): Period))
    def week = weeks
    def months = new TimeSpan(Right((new Period().plusMonths(len.toInt))))
    def month = months
    def years = new TimeSpan(Right((new Period().plusYears(len.toInt))))
    def year = years
  }

  /*
  /**
   * transforms a TimeSpan to a date by converting the TimeSpan expressed as millis and creating
   * a Date lasting that number of millis from the Epoch time (see the documentation for java.util.Date)
   */
  implicit def timeSpanToDate(in: TimeSpan): Date = in.date

  /** transforms a TimeSpan to its long value as millis */
  implicit def timeSpanToLong(in: TimeSpan): Long = in.millis
  */

  /**
   * The TimeSpan class represents an amount of time.
   * It can be translated to a date with the date method. In that case, the number of millis seconds will be used to create a Date
   * object starting from the Epoch time (see the documentation for java.util.Date)
   */
  class TimeSpan(private val dt: Either[DateTime, Period]) extends ConvertableToDate {
    /** @return a Date as the amount of time represented by the TimeSpan after the Epoch date */

    def this(ms: Long) = 
      this(if (ms < 52L * 7L * 24L * 60L * 60L * 1000L) Right(new Period(ms))
           else Left(new DateTime(ms)))

    def date: Date = dt match {
      case Left(datetime) => new Date(datetime.getMillis())
      case _ => new Date(millis)
    }

    /**
     * Convert to a Date
     */
    def toDate: Date = date
    
    /**
     * Convert to a JodaTime DateTime
     */
    def toDateTime = dt match {
      case Left(datetime) => datetime
      case _ => new DateTime(millis)
    }

    def toMillis = millis

    def millis = dt match {
      case Left(datetime) => datetime.getMillis()
      case Right(duration) => duration.toStandardDuration.getMillis()
    }
    

    /** @return a Date as the amount of time represented by the TimeSpan after now */
    def later: TimeSpan = dt match {
      case Right(duration) => new TimeSpan(Left(new DateTime(outer.millis).plus(duration)))
      case _ => TimeSpan(millis + outer.millis)
    }

    /** @return a Date as the amount of time represented by the TimeSpan before now */
    def ago: TimeSpan = dt match {
      case Right(duration) => new TimeSpan(Left(new DateTime(outer.millis).minus(duration)))
      case _ => TimeSpan(outer.millis - millis)
    }

    def noTime: Date = new DateExtension(this).noTime

    /** @return a TimeSpan representing the addition of 2 TimeSpans */
    def +[B](in: B)(implicit f: B => TimeSpan): TimeSpan =
      (this.dt, f(in).dt) match {
        case (Right(p1), Right(p2)) => p1.plus(p2)
        case (Left(date), Right(duration)) => date.plus(duration)
        case (Right(duration), Left(date)) => date.plus(duration)
        case _ => TimeSpan(this.millis + f(in).millis)
      }

    /** @return a TimeSpan representing the addition of 2 TimeSpans */
    def plus[B](in: B)(implicit f: B => TimeSpan): TimeSpan = this.+(in)(f)

    /** @return a TimeSpan representing the substraction of 2 TimeSpans */
    def -[B](in: B)(implicit f: B => TimeSpan): TimeSpan =
      (this.dt, f(in).dt) match {
        case (Right(p1), Right(p2)) => p1.minus(p2)
        case (Left(date), Right(duration)) => date.minus(duration)
        case (Right(duration), Left(date)) => date.minus(duration)
        case _ => TimeSpan(this.millis - f(in).millis)
      }

    /** override the equals method so that TimeSpans can be compared to long, int and TimeSpan */
    override def equals(cmp: Any) = {
      cmp match {
        case lo: Long => lo == this.millis
        case i: Int => i == this.millis
        case ti: TimeSpan => ti.dt == this.dt
        case d: Date => d.getTime() == this.millis
        case dt: DateTime => Left(dt) == this.dt
        case dur: Duration => Right(dur: Period) == this.dt
        case dur: Period => Right(dur) == this.dt
        case _ => false
      }
    }

    /** override the toString method to display a readable amount of time */
    override def toString = dt match {
      case Left(date) => date.toString
      case Right(dur) => TimeSpan.format(millis)
    }
  }

  /**
   * The TimeSpan object provides class represents an amount of time.
   * It can be translated to a date with the date method. In that case, the number of millis seconds will be used to create a Date
   * object starting from the Epoch time (see the documentation for java.util.Date)
   */
  object TimeSpan {
    /** time units and values used when converting a total number of millis to those units (see the format function)  */
    val scales = List((1000L, "milli"), (60L, "second"), (60L, "minute"), (24L, "hour"), (7L, "day"), (10000L, "week"))

    /** explicit constructor for a TimeSpan  */
    def apply(in: Long) = new TimeSpan(in)

    /**
     * Formats a number of millis to a string representing the number of weeks, days, hours, minutes, seconds, millis
     */
    def format(millis: Long): String = {
      def divideInUnits(millis: Long) = scales.foldLeft[(Long, List[(Long, String)])]((millis, Nil)){ (total, div) =>
        (total._1 / div._1, (total._1 % div._1, div._2) :: total._2)
      }._2
      def formatAmount(amountUnit: (Long, String)) = amountUnit match {
        case (amount, unit) if (amount == 1) => amount + " " + unit
        case (amount, unit) => amount + " " + unit + "s"
      }
      divideInUnits(millis).filter(_._1 > 0).map(formatAmount(_)).mkString(", ")
    }

    /**
     * Convert a Date to a TimeSpan
     */
    implicit def dateToTS(in: Date): TimeSpan =
      new TimeSpan(Left(new DateTime(in.getTime)))

    /**
     * Convert a DateTime to a TimeSpan
     */
    implicit def dateTimeToTS(in: DateTime): TimeSpan =
      new TimeSpan(Left(in))

    /**
     * Convert a Duration to a TimeSpan
     */
    implicit def durationToTS(in: Duration): TimeSpan =
      new TimeSpan(Right(in: Period))

    /**
     * Convert a Period to a TimeSpan
     */
    implicit def periodToTS(in: Period): TimeSpan =
      new TimeSpan(Right(in))
  }

  /** @return the current System.nanoTime() */
  def nano = System.nanoTime()

  /** @return the current number of millis: System.currentTimeMillis  */
  def millis = System.currentTimeMillis

  /** @return the number of millis corresponding to 'in' seconds */
  def seconds(in: Long): Long = in * 1000L

  /** @return the number of millis corresponding to 'in' minutes */
  def minutes(in: Long): Long = seconds(in) * 60L

  /** @return the number of millis corresponding to 'in' hours */
  def hours(in: Long): Long = minutes(in) * 60L

  /** @return the number of millis corresponding to 'in' days */
  def days(in: Long): Long = hours(in) * 24L

  /** @return the number of millis corresponding to 'in' weeks */
  def weeks(in: Long): Long = days(in) * 7L

  /** implicit def used to add the noTime method to the Date class */
  implicit def toDateExtension(d: Date) = new DateExtension(d)

  /** This class adds a noTime method the Date class, in order to get at Date object starting at 00:00 */
  class DateExtension(date: Date) {
    /** @returns a Date object starting at 00:00 from date */
    def noTime = {
      val calendar = Calendar.getInstance
      calendar.set(Calendar.HOUR_OF_DAY, 0)
      calendar.set(Calendar.MINUTE, 0)
      calendar.set(Calendar.SECOND, 0)
      calendar.set(Calendar.MILLISECOND, 0)
      calendar.getTime
    }
  }

  /** implicit def used to add the setXXX methods to the Calendar class */
  implicit def toCalendarExtension(c: Calendar) = new CalendarExtension(c)

  /** This class adds the setXXX methods to the Calendar class. Each setter returns the updated Calendar */
  class CalendarExtension(c: Calendar) {
    /** set the day of the month (1 based) and return the calendar */
    def setDay(d: Int) = { c.set(Calendar.DAY_OF_MONTH, d); c }

    /** set the month (0 based) and return the calendar */
    def setMonth(m: Int) = { c.set(Calendar.MONTH, m); c }

    /** set the year and return the calendar */
    def setYear(y: Int) = { c.set(Calendar.YEAR, y); c }

    /** set the TimeZone and return the calendar */
    def setTimezone(tz: TimeZone) = { c.setTimeZone(tz); c }

    /** set the time to 00:00:00.000 and return the calendar */
    def noTime = { c.setTime(c.getTime.noTime); c }
  }

  /** @return the date object for now */
  def now  = new Date

  /** @return the Calendar object for today (the TimeZone is the local TimeZone). Its time is 00:00:00.000 */
  def today  = Calendar.getInstance.noTime

  /** @return the current year */
  def currentYear: Int = Calendar.getInstance.get(Calendar.YEAR)

  /**
   * @deprecated use now instead
   * @return the current time as a Date object
   */
  def timeNow = new Date

  /**
   * @deprecated use today instead
   * @return the current Day as a Date object
   */
  def dayNow: Date = 0.seconds.later.noTime

  /** alias for new Date(millis) */
  def time(when: Long) = new Date(when)

  /** @return the month corresponding to today (0 based, relative to UTC) */
  def month(in: Date): Int = {
    val cal = Calendar.getInstance(utc)
    cal.setTimeInMillis(in.getTime)
    cal.get(Calendar.MONTH)
  }

  /** @return the year corresponding to today (relative to UTC) */
  def year(in: Date): Int =  {
    val cal = Calendar.getInstance(utc)
    cal.setTimeInMillis(in.getTime)
    cal.get(Calendar.YEAR)
  }

  /** @return the day of month corresponding to the input date (1 based) */
  def day(in: Date): Int =  {
    val cal = Calendar.getInstance(utc)
    cal.setTimeInMillis(in.getTime)
    cal.get(Calendar.DAY_OF_MONTH)
  }

  /** The UTC TimeZone */
  val utc = TimeZone.getTimeZone("UTC")

  /** @return the number of days since epoch converted from millis */
  def millisToDays(millis: Long): Long = millis / (1000L * 60L * 60L * 24L)

  /** @return the number of days since epoch */
  def daysSinceEpoch: Long = millisToDays(millis)

  /** @return the time taken to evaluate f in millis and the result */
  def calcTime[T](f: => T): (Long, T) = {
    val start = millis
    val result = f
    (millis - start, result)
  }

  /**
   * Log a message with the time taken in millis to do something and return the result
   * @return the result
   */
  def logTime[T](msg: String)(f: => T): T = {
    val (time, ret) = calcTime(f)
    logger.info(msg + " took " + time + " Milliseconds")
    ret
  }

 /**
   * Call f and log the string returned together with the time taken in millis.
   * @return the second result from f
   */
  def logTime[T](f: => (String,T)): T = {
    val (time, fret) = calcTime(f)
    val (msg, ret) = fret
    logger.info(msg + " took " + time + " Milliseconds")
    ret
  }

  /**
   * @return a standard format HH:mm:ss
   */
  def hourFormat = new SimpleDateFormat("HH:mm:ss")

  /**
   * @return the formatted time for a given Date
   */
  def hourFormat(in: Date): String = hourFormat.format(in)

  /** @return a standard format for the date yyyy/MM/dd */
  def dateFormatter = new SimpleDateFormat("yyyy/MM/dd")

  /** @return a format for the time which includes the TimeZone: HH:mm zzz*/
  def timeFormatter = new SimpleDateFormat("HH:mm zzz")

  /** @return today's date formatted as yyyy/MM/dd */
  def formattedDateNow = dateFormatter.format(now)

  /** @return now's time formatted as HH:mm zzz */
  def formattedTimeNow = timeFormatter.format(now)

  /** @return a formatter for internet dates (RFC822/1123) including:
   *  the day of week, the month, day of month, time and time zone */
  def internetDateFormatter = {
    val ret = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US)
    ret.setTimeZone(utc)
    ret
  }

  /** @return a date from a string using the internet format. Return the Epoch date if the parse is unsuccesfull */
  def boxParseInternetDate(dateString: String): Box[Date] = tryo {
    internetDateFormatter.parse(dateString)
  }

  /** @return a date from a string using the internet format. Return the Epoch date if the parse is unsuccesfull */
  def parseInternetDate(dateString: String): Date = tryo {
    internetDateFormatter.parse(dateString)
  } openOr new Date(0L)

  /** @return a date formatted with the internet format */
  def toInternetDate(in: Date): String = internetDateFormatter.format(in)

  /** @return a date formatted with the internet format (from a number of millis) */
  def toInternetDate(in: Long): String = internetDateFormatter.format(new Date(in))

  /** @return the current time as an internet date */
  def nowAsInternetDate: String = toInternetDate(millis)

  /** @return a Full(date) or a failure if the input couldn't be translated to date (or Empty if the input is null)*/
  def toDate(in: Any): Box[Date] = {
    try {
      in match {
        case null => Empty
        case d: Date => Full(d)
        case lng: Long => Full(new Date(lng))
        case lng: Number => Full(new Date(lng.longValue))
        case Nil | Empty | None | Failure(_, _, _) => Empty
        case Full(v) => toDate(v)
        case Some(v) => toDate(v)
        case v :: vs => toDate(v)
        case s : String => tryo(internetDateFormatter.parse(s)) or tryo(dateFormatter.parse(s))
        case o => toDate(o.toString)
      }
    } catch {
      case e => logger.debug("Error parsing date "+in, e); Failure("Bad date: "+in, Full(e), Empty)
    }
  }
}

trait ConvertableToDate {
  def toDate: Date
  def toDateTime: DateTime
  def millis: Long
}

object ConvertableToDate {
  implicit def toDate(in: ConvertableToDate): Date = in.toDate
  implicit def toDateTime(in: ConvertableToDate): DateTime = in.toDateTime
  implicit def toMillis(in: ConvertableToDate): Long = in.millis
  
}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework TimeHelpers.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.