diff --git a/core/actor/src/main/scala/net/liftweb/actor/LAPinger.scala b/core/actor/src/main/scala/net/liftweb/actor/LAPinger.scala index 2bb9e034a..6616b8da5 100644 --- a/core/actor/src/main/scala/net/liftweb/actor/LAPinger.scala +++ b/core/actor/src/main/scala/net/liftweb/actor/LAPinger.scala @@ -66,7 +66,7 @@ object LAPinger { * @param msg The message to send. * @param delay The number of milliseconds to delay before sending msg * @return a ScheduledFuture which sends the msg to - * the to Actor after the specified TimeSpan delay. + * the to Actor after the specified delay milliseconds. */ def schedule[T](to: SpecializedLiftActor[T], msg: T, delay: Long): ScheduledFuture[Unit] = { val r = new Callable[Unit] { diff --git a/core/util/src/main/scala/net/liftweb/util/Schedule.scala b/core/util/src/main/scala/net/liftweb/util/Schedule.scala index d55021932..3aaadf534 100644 --- a/core/util/src/main/scala/net/liftweb/util/Schedule.scala +++ b/core/util/src/main/scala/net/liftweb/util/Schedule.scala @@ -21,8 +21,8 @@ import java.util.concurrent._ import actor.ThreadPoolRules import common._ +import scala.concurrent.duration._ import util.Helpers -import util.Helpers.TimeSpan class ScheduleJBridge { def schedule: Schedule = Schedule @@ -100,28 +100,28 @@ sealed trait Schedule extends Loggable { * Schedules the sending of a message to occur after the specified delay. * * @return a ScheduledFuture which sends the msg to - * the to Actor after the specified TimeSpan delay. + * the to Actor after the specified FiniteDuration delay. */ - def schedule[T](to: SimpleActor[T], msg: T, delay: TimeSpan): ScheduledFuture[Unit] = - this.schedule(() => Helpers.tryo( to ! msg ), delay) + def schedule[T](to: SimpleActor[T], msg: T, delay: FiniteDuration): ScheduledFuture[Unit] = + this.schedule(() => Helpers.tryo(to ! msg), delay) /** * Schedules the sending of a message to occur after the specified delay. * * @return a ScheduledFuture which sends the msg to - * the to Actor after the specified TimeSpan delay. + * the to Actor after the specified FiniteDuration delay. */ def perform[T](to: SimpleActor[T], msg: T, delay: Long): ScheduledFuture[Unit] = - this.schedule(() => Helpers.tryo( to ! msg ), TimeSpan(delay)) + this.schedule(() => Helpers.tryo(to ! msg), Duration(delay, TimeUnit.MILLISECONDS)) - /** + /** * Schedules the sending of a message to occur after the specified delay. * * @return a ScheduledFuture which applies the function f * after delay */ def perform(f: () => Unit, delay: Long): ScheduledFuture[Unit] = - schedule(f, TimeSpan(delay)) + schedule(f, Duration(delay, TimeUnit.MILLISECONDS)) /** @@ -130,35 +130,32 @@ sealed trait Schedule extends Loggable { * @return a ScheduledFuture which executes the function f * immediately on a worker thread */ - def apply(f: () => Unit): ScheduledFuture[Unit] = schedule(f, TimeSpan(0)) - + def apply(f: () => Unit): ScheduledFuture[Unit] = schedule(f, 0.millis) + /** * Schedules the application of a function * * @return a ScheduledFuture which executes the function f * after the delay */ - def apply(f: () => Unit, delay: TimeSpan): ScheduledFuture[Unit] = + def apply(f: () => Unit, delay: FiniteDuration): ScheduledFuture[Unit] = schedule(f, delay) - + /** * Schedules the application of a function * * @return a ScheduledFuture which executes the function f * after the delay */ - def schedule(f: () => Unit, delay: TimeSpan): ScheduledFuture[Unit] = + def schedule(f: () => Unit, delay: FiniteDuration): ScheduledFuture[Unit] = synchronized { val r = new Runnable { - def run(): Unit = { - try { - f.apply() - } catch { - case e: Exception => logger.error(e.getMessage, e) - } + def run(): Unit = { + try { f.apply() } + catch { case e: Exception => logger.error(e.getMessage, e) } } } - + val fast = new java.util.concurrent.Callable[Unit] { def call(): Unit = { try { @@ -169,10 +166,10 @@ sealed trait Schedule extends Loggable { } } } - + try { this.restart - service.schedule(fast, delay.millis, TimeUnit.MILLISECONDS) + service.schedule(fast, delay.toMillis, TimeUnit.MILLISECONDS) } catch { case e: RejectedExecutionException => throw ActorPingException("ping could not be scheduled", e) } diff --git a/core/util/src/main/scala/net/liftweb/util/TimeHelpers.scala b/core/util/src/main/scala/net/liftweb/util/TimeHelpers.scala index f4dd4e1b5..16c09cb9d 100644 --- a/core/util/src/main/scala/net/liftweb/util/TimeHelpers.scala +++ b/core/util/src/main/scala/net/liftweb/util/TimeHelpers.scala @@ -22,7 +22,7 @@ import java.util.{TimeZone, Calendar, Date, Locale} import scala.language.implicitConversions -import org.joda.time._ +import org.joda.time.DateTime import common._ @@ -32,261 +32,13 @@ import common._ object TimeHelpers extends TimeHelpers with ControlHelpers with ClassHelpers /** - * The TimeHelpers trait provide functions to create TimeSpans (an object representing duration in milliseconds), - * to manage date formats or general utility functions (get the date for today, get year/month/day number,...) + * The TimeHelpers trait provides date and time utilities: duration formatting, date parsing, + * calendar manipulation, and format helpers. */ trait TimeHelpers { self: ControlHelpers => // Logger must be lazy, since we cannot instantiate until after boot is complete private lazy val logger = Logger(classOf[TimeHelpers]) - /** 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 */ - @deprecated("Long to TimeSpan conversion will be removed for possibility of ambiguous behaviours, use TimeSpan(in) instead if you are using in.millis", "3.0.0") - implicit def longToTimeSpan(in: Long): TimeSpan = TimeSpan(in) - - /** transforms an int to a TimeSpan object. Usage: 3000 returns a TimeSpan of 3000L millis */ - @deprecated("Int to TimeSpan conversion will be removed for possibility of ambiguous behaviours, use TimeSpan(in) instead if you are using in.millis", "3.0.0") - implicit def intToTimeSpan(in: Int): TimeSpan = TimeSpan(in) - - /** class building TimeSpans given an amount (len) and a method specify the time unit */ - case class TimeSpanBuilder(len: Long) { - def seconds = new TimeSpan(Left(Duration.standardSeconds(len))) - def second = seconds - def minutes = new TimeSpan(Left(Duration.standardMinutes(len))) - def minute = minutes - def hours = new TimeSpan(Left(Duration.standardHours(len))) - def hour = hours - def days = new TimeSpan(Left(Duration.standardDays(len))) - def day = days - def weeks = new TimeSpan(Left(Duration.standardDays(len * 7L))) - def week = weeks - @deprecated("This builder will be removed due to its unclear behavior; use Joda-Time `Period.months` and convert to `TimeSpan` manually instead.", "3.0.0") - def months = new TimeSpan(Right(new Period().plusMonths(len.toInt))) - @deprecated("This builder will be removed due to its unclear behavior; use Joda-Time `Period.months` and convert to `TimeSpan` manually instead.", "3.0.0") - def month = months - @deprecated("This builder will be removed due to its unclear behavior; use Joda-Time `Period.years` and convert to `TimeSpan` manually instead.", "3.0.0") - def years = new TimeSpan(Right(new Period().plusYears(len.toInt))) - @deprecated("This builder will be removed due to its unclear behavior; use Joda-Time `Period.years` and convert to `TimeSpan` manually instead.", "3.0.0") - def year = years - } - - /** - * The `TimeSpan` class represents a duration of time in milliseconds. In this - * way, it is similar to the `[[scala.concurrent.Duration]]` class. It is - * mostly used in Lift APIs in similar positions as the Scala `Duration` - * class (for example, in event scheduling). - * - * Unlike in the Lift 2.x series, building a `TimeSpan` with a `Long` will not - * have different behavior depending on the value passed. Any passed `Long` - * will be used as a duration. - * - * Prior to Lift 3.0, `TimeSpan` was an amalgam of duration and joda - * `DateTime`, and allowed conversions between the two. As a result, - * operational semantics were poorly defined and it was easy to call a method - * that seemed like it should have simple duration semantics but run into - * `DateTime` semantics that made things more complicated instead. - * - * Lift 3.0 mostly maintains API compatibility with the Lift 2.x series, but - * introduces a series of deprecations to indicate places where dangerous - * and potentially unclear behavior may occur. Lift 3.1 will maintain API - * compatibility with all non-deprecated parts of the `TimeSpan` API, but will - * remove the deprecated aspects. - * - * For deprecated years and month builders it handle an operations on duration - * field values. Then it could be used only in to-period implicit conversion. - */ - class TimeSpan(private val dt: Either[Duration, Period]) extends ConvertableToDate { - - def this(ms: Long) = - this(Left(new Duration(ms))) - - /** - * Convert to a Java `Date`. The number of milliseconds in the `Duration` - * will be added to the UNIX epoch to create a `Date` object. - */ - @deprecated("This method will be removed due to its unclear behavior; use new Date(timeSpan.millis) instead.", "3.0.0") - def date: Date = new Date(millis) - - /** - * Convert to a Java `Date`. Synonym of `[[date]]`. - */ - @deprecated("This method will be removed due to its unclear behavior; use new Date(timeSpan.millis) instead.", "3.0.0") - def toDate: Date = date - - /** - * Convert to a Joda-Time `DateTime`. The number of milliseconds in the `Duration` - * will be added to the UNIX epoch to create a `DateTime` object. - */ - @deprecated("This method will be removed due to its unclear behavior; use new DateTime(timeSpan.millis) instead.", "3.0.0") - def toDateTime = new DateTime(millis) - - @deprecated("TimeSpan will not support operations on Joda-Time `Period`s in the future; use new Period(timeSpan.millis) instead.", "3.0.0") - private[util] def toPeriod: Period = dt match { // package protected because of view bound usage in tsToPeriod - case Left(duration) => duration.toPeriod - case Right(period) => period - } - - /** - * @return The amount of milliseconds this `TimeSpan` represents. - * @throws UnsupportedOperationException When created by the deprecated - * months/years builder (month and year lengths in milliseconds - * are only defined with respect to a reference point, since the - * length of a month or year can vary). - */ - def toMillis = millis - - /** - * @return The amount of milliseconds this `TimeSpan` represents. - * @throws UnsupportedOperationException When created by the deprecated months/years builder ( - * month and year lengths in milliseconds are only defined with respect to a reference point, - * since the length of a month or year can vary). - */ - def millis = dt match { - case Left(duration) => duration.getMillis - case Right(period) => period.toStandardDuration.getMillis // will throw exception because it holds month or year - } - - // TODO If we choose to move away from TimeSpan, we'll need to take into - // TODO account the fact that this method can take anything convertible to - // TODO a TimeSpan, so we'll need at least one release where TimeSpan is - // TODO around for the purposes of these implicit conversions in case client - // TODO code defines one. - /** - * Sums this `TimeSpan` with an object that can be converted to a - * `TimeSpan`. If either `TimeSpan` represents a `Duration`, add the - * `Duration`s directly. If both `TimeSpan`s represents a `Period` (which is - * deprecated behavior), adds them using `Period` addition. - * - * @note Adding two `TimeSpan`s where one of the two was constructed using the - * deprecated `months` or `years` builders will throw an exception. - * @note Adding two `TimeSpan`s where both were constructed using the - * deprecated `months` or `years` builders will result in a `TimeSpan` - * representing a `Period`. These `TimeSpan`s can behave in unexpected - * ways, including throwing exceptions when their millisecond duration - * is required. - * - * @return A `TimeSpan` representing the sum of this span and `in`'s - * `TimeSpan` representation. - * @throws UnsupportedOperationException If only one of the two `TimeSpan`s - * represents a `Period` and that `Period` has a year or month - * component (this only occurs if the deprecated `months` or - * `years` builders are used, as month and year lengths in - * milliseconds are only defined with respect to a reference point, - * since the length of a month or year can vary) - */ - def +[B](in: B)(implicit f: B => TimeSpan): TimeSpan = - (this.dt, f(in).dt) match { - case (Right(p1), Right(p2)) => new TimeSpan(Right(p1.plus(p2))) - case (Left(duration), Right(period)) => new TimeSpan(Left(duration.plus(period.toStandardDuration))) - case (Right(period), Left(duration)) => new TimeSpan(Left(period.toStandardDuration.plus(duration))) - case (Left(d1), Left(d2)) => new TimeSpan(Left(d1.plus(d2))) - } - - /** - * Alias for `[[+]]`. - */ - def plus[B](in: B)(implicit f: B => TimeSpan): TimeSpan = this.+(in)(f) - - // TODO If we choose to move away from TimeSpan, we'll need to take into - // TODO account the fact that this method can take anything convertible to - // TODO a TimeSpan, so we'll need at least one release where TimeSpan is - // TODO around for the purposes of these implicit conversions in case client - // TODO code defines one. - /** - * Subtracts an object that can be converted to a `TimeSpan` from this - * `TimeSpan`. If either `TimeSpan` represents a `Duration`, subtracts the - * `Duration`s directly. If both `TimeSpan`s represents a `Period` (which is - * deprecated behavior), subtracts them using `Period` subtraction. - * - * @note Subtracting two `TimeSpan`s where one of the two was constructed - * using the deprecated `months` or `years` builders will throw an - * exception. - * @note Subtracting two `TimeSpan`s where both were constructed using the - * deprecated `months` or `years` builders will result in a `TimeSpan` - * representing a `Period`. These `TimeSpan`s can behave in unexpected - * ways, including throwing exceptions when their millisecond duration - * is required. - * - * @return A `TimeSpan` representing the sum of this span and `in`'s - * `TimeSpan` representation. - * @throws UnsupportedOperationException If only one of the two `TimeSpan`s - * represents a `Period` and that `Period` has a year or month - * component (this only occurs if the deprecated `months` or - * `years` builders are used, as month and year lengths in - * milliseconds are only defined with respect to a reference point, - * since the length of a month or year can vary) - */ - def -[B](in: B)(implicit f: B => TimeSpan): TimeSpan = - (this.dt, f(in).dt) match { - case (Right(p1), Right(p2)) => new TimeSpan(Right(p1.minus(p2))) - case (Left(duration), Right(period)) => new TimeSpan(Left(duration.minus(period.toStandardDuration))) - case (Right(period), Left(duration)) => new TimeSpan(Left(period.toStandardDuration.minus(duration))) - case (Left(d1), Left(d2)) => new TimeSpan(Left(d1.minus(d2))) - } - - /** - * Override the equals method so that `TimeSpan`s can be compared to long, int, - * Joda-Time `Duration`, and `TimeSpan`. - * - * @note Comparing to a Joda-Time `Period` is also done correctly, but is - * deprecated. - */ - 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 dur: Duration => Left(dur) == this.dt - case period: Period => Right(period) == this.dt - case _ => false - } - } - - /** - * Override the toString method to display a readable amount of time using - * `[[TimeSpan.format]]`` - */ - override def toString = 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) => s"${amount} ${unit}" - case (amount, unit) => s"${amount} ${unit}s" - } - divideInUnits(millis).filter(_._1 > 0).map(formatAmount(_)).mkString(", ") - } - - /** - * Convert a Duration to a TimeSpan - */ - implicit def durationToTS(in: Duration): TimeSpan = - new TimeSpan(Left(in)) - } - /** @return the current System.nanoTime() */ def nano = System.nanoTime() @@ -489,16 +241,18 @@ trait TimeHelpers { self: ControlHelpers => case e: Exception => 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 + /** Formats a number of milliseconds as a human-readable duration string (e.g., "1 minute, 30 seconds"). */ + def formatDuration(millis: Long): String = { + val scales = List( + (1000L, "milli"), (60L, "second"), (60L, "minute"), + (24L, "hour"), (7L, "day"), (10000L, "week") + ) + def divideInUnits(ms: Long) = + scales.foldLeft[(Long, List[(Long, String)])]((ms, Nil)) { (total, div) => + (total._1 / div._1, (total._1 % div._1, div._2) :: total._2) + }._2 + def fmt(pair: (Long, String)) = if (pair._1 == 1) s"${pair._1} ${pair._2}" else s"${pair._1} ${pair._2}s" + divideInUnits(millis).filter(_._1 > 0).map(fmt).mkString(", ") + } } diff --git a/core/util/src/main/scala/net/liftweb/util/Wiring.scala b/core/util/src/main/scala/net/liftweb/util/Wiring.scala index d8da41937..ee37fe015 100644 --- a/core/util/src/main/scala/net/liftweb/util/Wiring.scala +++ b/core/util/src/main/scala/net/liftweb/util/Wiring.scala @@ -19,7 +19,7 @@ package util import net.liftweb.common._ import java.lang.ref.WeakReference -import Helpers.TimeSpan +import scala.concurrent.duration._ /** * Something that depends on the values of other cells @@ -143,7 +143,7 @@ trait Cell[T] extends Dependent { * will be performed on a separate thread asynchronously */ def notifyDependents(): Unit = { - Schedule.schedule(() => dependents.foreach(_.predicateChanged(this)),TimeSpan(0)) + Schedule.schedule(() => dependents.foreach(_.predicateChanged(this)), 0.millis) } /** diff --git a/core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala b/core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala index 8081b4dd0..7a1512861 100644 --- a/core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala +++ b/core/util/src/test/scala/net/liftweb/util/ScheduleSpec.scala @@ -21,6 +21,7 @@ import org.specs2.mutable.Specification import org.specs2.specification.BeforeEach import org.specs2.execute.PendingUntilFixed +import scala.concurrent.duration._ import actor._ import Helpers._ @@ -35,20 +36,20 @@ class ScheduleSpec extends Specification with PendingUntilFixed with PingedServi "The Schedule object" should { "provide a schedule method to ping an actor regularly" in { - Schedule.schedule(service, Alive, TimeSpan(10)) + Schedule.schedule(service, Alive, 10.millis) service.pinged must eventually(beTrue) } "honor multiple restarts" in { Schedule.restart Schedule.restart Schedule.restart - Schedule.schedule(service, Alive, TimeSpan(10)) + Schedule.schedule(service, Alive, 10.millis) service.pinged must eventually(beTrue) } "honor shutdown followed by restart" in { Schedule.shutdown() Schedule.restart - Schedule.schedule(service, Alive, TimeSpan(10)) + Schedule.schedule(service, Alive, 10.millis) service.pinged must eventually(beTrue) } "not honor multiple shutdowns" in { diff --git a/core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala b/core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala index 7321ac952..b1a8d099f 100644 --- a/core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala +++ b/core/util/src/test/scala/net/liftweb/util/TimeHelpersSpec.scala @@ -21,8 +21,7 @@ import java.util.{Calendar, Date, TimeZone} import net.liftweb.common._ import net.liftweb.util.TimeHelpers._ -import org.joda.time.{Period, DateTimeZone, DateTime} -import org.scalacheck.Gen._ +import org.joda.time.DateTimeZone import org.scalacheck.Prop._ import org.specs2.ScalaCheck import org.specs2.execute.AsResult @@ -33,70 +32,20 @@ import org.specs2.specification.Around /** * Systems under specification for TimeHelpers. */ -class TimeHelpersSpec extends Specification with ScalaCheck with TimeAmountsGen { +class TimeHelpersSpec extends Specification with ScalaCheck { "TimeHelpers Specification".title - "A TimeSpan" can { - "be created from a number of milliseconds" in forAllTimeZones { - TimeSpan(3000) === TimeSpan(3 * 1000) + "formatDuration" should { + "format milliseconds as a human-readable string" in { + formatDuration(3000L) must beEqualTo("3 seconds") } - "be created from a number of seconds" in forAllTimeZones { - 3.seconds === TimeSpan(3 * 1000) + "pluralize correctly for single units" in { + formatDuration(1000L) must beEqualTo("1 second") } - "be created from a number of minutes" in forAllTimeZones { - 3.minutes === TimeSpan(3 * 60 * 1000) - } - "be created from a number of hours" in forAllTimeZones { - 3.hours === TimeSpan(3 * 60 * 60 * 1000) - } - "be created from a number of days" in forAllTimeZones { - 3.days === TimeSpan(3 * 24 * 60 * 60 * 1000) - } - "be created from a number of weeks" in forAllTimeZones { - 3.weeks === TimeSpan(3 * 7 * 24 * 60 * 60 * 1000) - } - "be created from a number of months" in forAllTimeZones { - 3.months must beEqualTo(Period.months(3)) - } - "be created from a number of years" in forAllTimeZones { - 3.years must beEqualTo(Period.years(3)) - } - "be converted implicitly to a date starting from the epoch time" in forAllTimeZones { - 3.seconds.after(new Date(0)) must beTrue - } - "be converted to a date starting from the epoch time, using the date method" in forAllTimeZones { - 3.seconds.after(new Date(0)) must beTrue - } - "be compared to another TimeSpan" in forAllTimeZones { - 3.seconds === 3.seconds - 3.seconds must not(beEqualTo(2.seconds)) - } - "be compared to another object" in forAllTimeZones { - 3.seconds must not(beEqualTo("string")) - } - } - - "A TimeSpan" should { - "return a new TimeSpan representing the sum of the 2 times when added with another TimeSpan" in forAllTimeZones { - 3.seconds + 3.seconds === 6.seconds - } - "return a new TimeSpan representing the difference of the 2 times when substracted with another TimeSpan" in forAllTimeZones { - 3.seconds - 4.seconds === (-1).seconds - } - "have a toString method returning the relevant number of weeks, days, hours, minutes, seconds, millis" in forAllTimeZones { - val conversionIsOk = forAll(timeAmounts)((t: TimeAmounts) => { val (timeSpanToString, timeSpanAmounts) = t - timeSpanAmounts forall { case (amount, unit) => - amount >= 1 && - timeSpanToString.contains(amount.toString) || true } - }) - val timeSpanStringIsPluralized = forAll(timeAmounts)((t: TimeAmounts) => { val (timeSpanToString, timeSpanAmounts) = t - timeSpanAmounts forall { case (amount, unit) => - amount > 1 && timeSpanToString.contains(unit + "s") || - amount == 1 && timeSpanToString.contains(unit) || - amount == 0 && !timeSpanToString.contains(unit) - } - }) - conversionIsOk && timeSpanStringIsPluralized + "combine multiple units" in { + val result = formatDuration(90000L) + result must contain("1 minute") + result must contain("30 seconds") } } @@ -227,23 +176,3 @@ object forAllTimeZones extends Around { } } } - - -trait TimeAmountsGen { - - type TimeAmounts = (String, List[(Int, String)]) - - val timeAmounts = - for { - w <- choose(0, 2) - d <- choose(0, 6) - h <- choose(0, 23) - m <- choose(0, 59) - s <- choose(0, 59) - ml <- choose(0, 999) - } - yield ( - TimeSpan(weeks(w) + days(d) + hours(h) + minutes(m) + seconds(s) + ml).toString, - (w, "week") :: (d, "day") :: (h, "hour") :: (m, "minute") :: (s, "second") :: (ml, "milli") :: Nil - ) -} diff --git a/web/webkit/src/main/scala/net/liftweb/builtin/comet/AsyncRenderComet.scala b/web/webkit/src/main/scala/net/liftweb/builtin/comet/AsyncRenderComet.scala index e7d6f5aa1..b05d44603 100644 --- a/web/webkit/src/main/scala/net/liftweb/builtin/comet/AsyncRenderComet.scala +++ b/web/webkit/src/main/scala/net/liftweb/builtin/comet/AsyncRenderComet.scala @@ -3,6 +3,7 @@ package builtin package comet import scala.xml.NodeSeq +import scala.concurrent.duration._ import common._ import http._ @@ -37,7 +38,7 @@ private case class Render(js: JsCmd) */ class AsyncRenderComet extends MessageCometActor { - override def lifespan: Box[TimeSpan] = Full(90.seconds) + override def lifespan: Box[FiniteDuration] = Full(90.seconds) // make this method visible so that we can initialize the actor override def initCometActor(creationInfo: CometCreationInfo): Unit = { diff --git a/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala b/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala index a71dabbfc..408002210 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala @@ -29,6 +29,7 @@ import net.liftweb.http.js._ import JsCmds._ import JE._ import java.util.Locale +import scala.concurrent.duration.FiniteDuration /** * A case class that contains the information necessary to set up a CometActor @@ -562,7 +563,7 @@ trait BaseCometActor extends LiftActor with LiftCometActor with CssBindImplicits * isn't visible on any page for some period after its lifespan * the CometActor will be shut down. */ - def lifespan: Box[TimeSpan] = Empty + def lifespan: Box[FiniteDuration] = Empty private var _running = true @@ -934,7 +935,7 @@ trait BaseCometActor extends LiftActor with LiftCometActor with CssBindImplicits case ShutdownIfPastLifespan => for { - ls <- lifespan if listeners.isEmpty && (lastListenerTime + ls.millis + 1000L) < millis + ls <- lifespan if listeners.isEmpty && (lastListenerTime + ls.toMillis + 1000L) < millis } { this ! ShutDown } diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftMerge.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftMerge.scala index 031f28aa2..a2031d7f0 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/LiftMerge.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/LiftMerge.scala @@ -71,7 +71,7 @@ private[http] trait LiftMerge { */ def merge(xhtml: NodeSeq, req: Req): Node = { val snippetHashs: HashMap[String, Box[NodeSeq]] = this.deferredSnippets.is - val waitUntil = millis + LiftRules.lazySnippetTimeout.vend.millis + val waitUntil = millis + LiftRules.lazySnippetTimeout.vend.toMillis val stripComments: Boolean = LiftRules.stripComments.vend def waitUntilSnippetsDone(): Unit ={ diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftRules.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftRules.scala index d4a238aa8..8eb40c6d0 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/LiftRules.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/LiftRules.scala @@ -33,6 +33,8 @@ import scala.xml._ import java.util.{Locale, TimeZone, ResourceBundle, Date} import java.io.{InputStream, ByteArrayOutputStream, BufferedReader, StringReader} import java.util.concurrent.{ConcurrentHashMap => CHash} +import java.util.concurrent.TimeUnit +import scala.concurrent.duration._ import scala.reflect.Manifest import java.util.concurrent.atomic.AtomicInteger @@ -251,7 +253,7 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { * for general notices (not associated with id-s) regardless if they are set for the page rendering, ajax * response or Comet response. */ - val noticesAutoFadeOut = new FactoryMaker[(NoticeType.Value) => Box[(TimeSpan, TimeSpan)]]((notice : NoticeType.Value) => Empty){} + val noticesAutoFadeOut = new FactoryMaker[(NoticeType.Value) => Box[(FiniteDuration, FiniteDuration)]]((notice : NoticeType.Value) => Empty){} /** * Use this to apply various effects to the notices. The user function receives the NoticeType @@ -804,7 +806,7 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { * the long polling connection */ val clientActorLifespan = new FactoryMaker[LiftActor => Long]( - () => (actor: LiftActor) => (30.minutes): Long + () => (actor: LiftActor) => 30.minutes.toMillis ){} /** @@ -827,17 +829,17 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { /** * If a Comet request fails timeout for this period of time. Default value is 10 seconds */ - @volatile var cometFailureRetryTimeout: Long = 10.seconds + @volatile var cometFailureRetryTimeout: Long = 10.seconds.toMillis /** * The timeout in milliseconds of a comet ajax-request. Defaults to 5000 ms. */ - @volatile var cometProcessingTimeout: Long = 5.seconds + @volatile var cometProcessingTimeout: Long = 5.seconds.toMillis /** * The timeout in milliseconds of a comet render-request. Defaults to 30000 ms. */ - @volatile var cometRenderTimeout: Long = 30.seconds + @volatile var cometRenderTimeout: Long = 30.seconds.toMillis /** * Adjusts LiftRules to allow a page's comets to "rehydrate" (i.e. reconnect to the page) after a server restart. @@ -1224,7 +1226,7 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { /** * How long should we wait for all the lazy snippets to render */ - val lazySnippetTimeout: FactoryMaker[TimeSpan] = new FactoryMaker(() => 30.seconds) {} + val lazySnippetTimeout: FactoryMaker[FiniteDuration] = new FactoryMaker(() => 30.seconds) {} /** * Does the current context support parallel snippet execution @@ -1865,13 +1867,13 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { * (given in milliseconds) will be discarded, hence eligible for garbage collection. * The default value is 10 minutes. */ - @volatile var unusedFunctionsLifeTime: Long = 10.minutes + @volatile var unusedFunctionsLifeTime: Long = 10.minutes.toMillis /** * The polling interval for background Ajax requests to prevent functions of being garbage collected. * Default value is set to 75 seconds. */ - @volatile var liftGCPollingInterval: Long = 75.seconds + @volatile var liftGCPollingInterval: Long = 75.seconds.toMillis /** * Put a test for being logged in into this function @@ -1882,7 +1884,7 @@ class LiftRules() extends Factory with FormVendor with LazyLoggable { * The polling interval for background Ajax requests to keep functions to not be garbage collected. * This will be applied if the Ajax request will fail. Default value is set to 15 seconds. */ - @volatile var liftGCFailureRetryTimeout: Long = 15.seconds + @volatile var liftGCFailureRetryTimeout: Long = 15.seconds.toMillis /** * If this is Full, comet updates (partialUpdates or reRenders) are diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftServlet.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftServlet.scala index 521194284..564189e9c 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/LiftServlet.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/LiftServlet.scala @@ -27,6 +27,9 @@ import js._ import auth._ import provider._ +import scala.concurrent.duration._ +import java.util.concurrent.TimeUnit + import org.json4s._ /** @@ -110,7 +113,7 @@ class LiftServlet extends Loggable { func(answerFunc) - }, TimeSpan(5)) + }, Duration(5, TimeUnit.MILLISECONDS)) } @@ -825,7 +828,7 @@ class LiftServlet extends Loggable { try { session.enterComet(cont -> request) - LAPinger.schedule(cont, BreakOut(), TimeSpan(cometTimeout)) + LAPinger.schedule(cont, BreakOut(), cometTimeout) request.request.suspend(cometTimeout + 2000L) } finally { @@ -901,7 +904,7 @@ class LiftServlet extends Loggable { session.enterComet(cont -> request) - LAPinger.schedule(cont, BreakOut(), TimeSpan(cometTimeout)) + LAPinger.schedule(cont, BreakOut(), cometTimeout) val ret2 = f.get(cometTimeout) openOr Nil diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala index 3e85a4bbb..4ae42d068 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala @@ -19,6 +19,7 @@ package http import java.lang.reflect.Method import java.util.concurrent.ConcurrentHashMap +import scala.concurrent.duration.FiniteDuration import scala.collection.mutable.{HashMap, ListBuffer} import collection.mutable.{HashMap, ListBuffer} @@ -458,7 +459,7 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri @volatile private[http] var inactivityLength: Long = - LiftRules.sessionInactivityTimeout.vend openOr ((30.minutes): Long) + LiftRules.sessionInactivityTimeout.vend openOr minutes(30) private[http] var highLevelSessionDispatcher = new HashMap[String, LiftRules.DispatchPF]() private[http] var sessionRewriter = new HashMap[String, LiftRules.RewritePF]() @@ -1229,7 +1230,7 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri case _: EmptyBox => NodeSeq.Empty case b: Box[_] => runSourceContext(b.toList, xform, ns) case b: Option[_] => runSourceContext(b.toList, xform, ns) - case fut: LAFuture[_] => runSourceContext(fut.get(5.seconds).openOr(Empty), xform, ns) + case fut: LAFuture[_] => runSourceContext(fut.get(seconds(5)).openOr(Empty), xform, ns) case node: scala.xml.Node => currentSourceContext.doWith(node)(processSurroundAndInclude("Source", xform(ns))) case na: org.mozilla.javascript.NativeArray => val len = na.getLength.toInt @@ -1277,7 +1278,7 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri case b: Boolean => xformRule #> b case b: Box[_] => runSourceContext(b.toList, retFunc _, _) case b: Option[_] => runSourceContext(b.toList, retFunc _, _) - case fut: LAFuture[_] => runSourceContext(fut.get(5.seconds).openOr(Empty), retFunc _, _) + case fut: LAFuture[_] => runSourceContext(fut.get(seconds(5)).openOr(Empty), retFunc _, _) case n: java.lang.Iterable[_] => runSourceContext(n.iterator(), retFunc _, _) case n: java.util.Iterator[_] => runSourceContext(n, retFunc _, _) case en: java.util.Enumeration[_] => runSourceContext(en, retFunc _, _) @@ -2191,7 +2192,11 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri Helpers.tryo(shutdownFunc.foreach(_(this))) } - override def lifespan: Full[TimeSpan] = Full(TimeSpan(LiftRules.clientActorLifespan.vend.apply(this))) + override def lifespan: Box[FiniteDuration] = { + import scala.concurrent.duration._ + import java.util.concurrent.TimeUnit + Full(Duration(LiftRules.clientActorLifespan.vend.apply(this), TimeUnit.MILLISECONDS)) + } override def hasOuter = false @@ -2804,7 +2809,11 @@ class LiftSession(private[http] val _contextPath: String, val underlyingId: Stri - override def lifespan = Full(TimeSpan(LiftRules.clientActorLifespan.vend.apply(this))) + override def lifespan: Box[FiniteDuration] = { + import scala.concurrent.duration._ + import java.util.concurrent.TimeUnit + Full(Duration(LiftRules.clientActorLifespan.vend.apply(this), TimeUnit.MILLISECONDS)) + } override def hasOuter = false diff --git a/web/webkit/src/main/scala/net/liftweb/http/NamedCometActorTrait.scala b/web/webkit/src/main/scala/net/liftweb/http/NamedCometActorTrait.scala index fa670ca84..4964025cd 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/NamedCometActorTrait.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/NamedCometActorTrait.scala @@ -18,7 +18,8 @@ package net.liftweb package http import util.Helpers._ -import common.{Loggable, Full} +import common.{Loggable, Full, Box} +import scala.concurrent.duration._ trait NamedCometActorTrait extends BaseCometActor with Loggable { @@ -45,6 +46,6 @@ trait NamedCometActorTrait extends BaseCometActor with Loggable { } // time out the comet actor if it hasn't been on a page for 2 minutes - override def lifespan = Full(120.seconds) + override def lifespan: Box[FiniteDuration] = Full(120.seconds) } diff --git a/web/webkit/src/main/scala/net/liftweb/http/ResourceServer.scala b/web/webkit/src/main/scala/net/liftweb/http/ResourceServer.scala index 4bc883837..ec6dbb421 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/ResourceServer.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/ResourceServer.scala @@ -22,6 +22,7 @@ import net.liftweb.util._ import Helpers._ import java.net.{URL, URLConnection, JarURLConnection} import java.util.concurrent.{ConcurrentHashMap => CHash} +import scala.concurrent.duration._ object ResourceServer { var allowedPaths: PartialFunction[List[String], Boolean] = { @@ -96,13 +97,13 @@ object ResourceServer { url <- LiftRules.getResource(path) lastModified = calcLastModified(url) } yield - request.testFor304(lastModified, "Expires" -> toInternetDate(millis + 30.days)) openOr { + request.testFor304(lastModified, "Expires" -> toInternetDate(millis + 30.days.toMillis)) openOr { val stream = url.openStream val uc = url.openConnection StreamingResponse(stream, () => stream.close, uc.getContentLength, (if (lastModified == 0L) Nil else List("Last-Modified" -> toInternetDate(lastModified))) ::: - List("Expires" -> toInternetDate(millis + 30.days), + List("Expires" -> toInternetDate(millis + 30.days.toMillis), "Date" -> Helpers.nowAsInternetDate, "Pragma" -> "", "Cache-Control" -> "", diff --git a/web/webkit/src/main/scala/net/liftweb/http/SessionMaster.scala b/web/webkit/src/main/scala/net/liftweb/http/SessionMaster.scala index f36c8d5ce..10e1690c6 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/SessionMaster.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/SessionMaster.scala @@ -17,6 +17,7 @@ package net.liftweb package http import java.util.concurrent.ConcurrentHashMap +import scala.concurrent.duration._ import common._ import actor._ @@ -229,7 +230,7 @@ object SessionMaster extends LiftActor with Loggable { import scala.jdk.CollectionConverters._ /* remove dead sessions that are more than 45 minutes old */ - val now = Helpers.millis - 45.minutes + val now = Helpers.millis - 45.minutes.toMillis val removeKeys: Iterable[String] = killedSessions.asScala.filter(_._2 < now).map(_._1) removeKeys.foreach(s => killedSessions.remove(s)) diff --git a/web/webkit/src/main/scala/net/liftweb/http/auth/HttpAuthentication.scala b/web/webkit/src/main/scala/net/liftweb/http/auth/HttpAuthentication.scala index 6fcf538e2..de5400e7a 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/auth/HttpAuthentication.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/auth/HttpAuthentication.scala @@ -25,6 +25,7 @@ import net.liftweb.util.Helpers._ import net.liftweb.http._ import org.apache.commons.codec.binary._ import scala.collection.mutable.{HashMap} +import scala.concurrent.duration._ /** * All http authentication methods must implement these methods. @@ -140,7 +141,7 @@ case class HttpDigestAuthentication(realmName: String)(func: PartialFunction[(St * The default value returned is 30 seconds. * */ - def nonceValidityPeriod: Long = 30.seconds + def nonceValidityPeriod: Long = 30.seconds.toMillis override def realm = realmName diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/JSArtifacts.scala b/web/webkit/src/main/scala/net/liftweb/http/js/JSArtifacts.scala index 9b158d261..39086e0a0 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/JSArtifacts.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/JSArtifacts.scala @@ -21,6 +21,7 @@ package js import net.liftweb.common.{Box, Full, Empty} import scala.xml.NodeSeq import net.liftweb.util.Helpers._ +import scala.concurrent.duration.FiniteDuration /** * Abstracted JavaScript artifacts used by lift core. @@ -73,7 +74,7 @@ trait JSArtifacts { * Fades out the element denominated by id, by waiting * for duration milliseconds and fading out for fadeTime milliseconds */ - def fadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan): JsCmd + def fadeOut(id: String, duration: FiniteDuration, fadeTime: FiniteDuration): JsCmd /** * Transforms a JSON object into its string representation diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/JsCommands.scala b/web/webkit/src/main/scala/net/liftweb/http/js/JsCommands.scala index 1359cc04c..875c34414 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/JsCommands.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/JsCommands.scala @@ -25,6 +25,7 @@ import scala.xml.Node import org.json4s._ import org.json4s.native._ +import scala.concurrent.duration._ object JsCommands { def create = new JsCommands(Nil) @@ -836,13 +837,13 @@ object JsCmds { } trait HasTime { - def time: Box[TimeSpan] + def time: Box[FiniteDuration] - def timeStr = time.map(_.millis.toString) openOr "" + def timeStr = time.map(_.toMillis.toString) openOr "" } - case class After(time: TimeSpan, toDo: JsCmd) extends JsCmd { - def toJsCmd = "setTimeout(function() {" + toDo.toJsCmd + "}, " + time.millis + ");" + case class After(time: FiniteDuration, toDo: JsCmd) extends JsCmd { + def toJsCmd = "setTimeout(function() {" + toDo.toJsCmd + "}, " + time.toMillis + ");" } case class Alert(text: String) extends JsCmd { @@ -1000,13 +1001,13 @@ object JsRules { * messages. */ //@deprecated - @volatile var prefadeDuration: Helpers.TimeSpan = 5.seconds + @volatile var prefadeDuration: FiniteDuration = 5.seconds /** * The default fade time for fading FadeOut and FadeIn * messages. */ //@deprecated - @volatile var fadeTime: Helpers.TimeSpan = 1.second + @volatile var fadeTime: FiniteDuration = 1.second } diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/extcore/ExtCoreArtifacts.scala b/web/webkit/src/main/scala/net/liftweb/http/js/extcore/ExtCoreArtifacts.scala index 75e674a95..397e3ca4f 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/extcore/ExtCoreArtifacts.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/extcore/ExtCoreArtifacts.scala @@ -20,6 +20,7 @@ package js package extcore import scala.xml.NodeSeq +import scala.concurrent.duration.FiniteDuration import net.liftweb.http.S import net.liftweb.http.js.JE @@ -113,7 +114,7 @@ object ExtCoreArtifacts extends JSArtifacts { * Fades out the element having the provided id, by waiting * for the given duration and fades out during fadeTime */ - def fadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan) = Noop + def fadeOut(id: String, duration: FiniteDuration, fadeTime: FiniteDuration) = Noop /** * Trabsforms a JSON object intoits string representation diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JQueryArtifacts.scala b/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JQueryArtifacts.scala index 262331468..ef5645930 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JQueryArtifacts.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JQueryArtifacts.scala @@ -20,6 +20,7 @@ package js package jquery import scala.xml.{Elem, NodeSeq} +import scala.concurrent.duration.FiniteDuration import net.liftweb.http.S import net.liftweb.http.js.JE @@ -87,7 +88,7 @@ trait JQueryArtifacts extends JSArtifacts { * Fades out the element having the provided id, by waiting * for the given duration and fades out during fadeTime */ - def fadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan) = + def fadeOut(id: String, duration: FiniteDuration, fadeTime: FiniteDuration) = FadeOut(id, duration, fadeTime) /** diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JqJsCmds.scala b/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JqJsCmds.scala index ee281247b..c242bcf69 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JqJsCmds.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/jquery/JqJsCmds.scala @@ -24,6 +24,7 @@ import net.liftweb.util.Helpers import net.liftweb.util.TimeHelpers import net.liftweb.common._ import net.liftweb.util._ +import scala.concurrent.duration._ import net.liftweb.http.js.{JsExp, JE} import JE._ @@ -510,7 +511,7 @@ object JqJsCmds { * @param uid the element id * @param time the duration of the effect. */ - def apply(uid: String, time: TimeSpan) = new Show(uid, Full(time)) + def apply(uid: String, time: FiniteDuration) = new Show(uid, Full(time)) } /** @@ -519,7 +520,7 @@ object JqJsCmds { * @param uid the element id * @param time the duration of the effect. */ - class Show(val uid: String, val time: Box[TimeSpan]) extends JsCmd with HasTime { + class Show(val uid: String, val time: Box[FiniteDuration]) extends JsCmd with HasTime { def toJsCmd = "try{jQuery(" + ("#" + uid).encJs + ").show(" + timeStr + ");} catch (e) {}" } @@ -540,20 +541,20 @@ object JqJsCmds { * @param uid the element id * @param time the duration of the effect. */ - def apply(uid: String, time: TimeSpan) = new Hide(uid, Full(time)) + def apply(uid: String, time: FiniteDuration) = new Hide(uid, Full(time)) } /** * Hide an element identified by uid and the animation will last @time */ - class Hide(val uid: String, val time: Box[TimeSpan]) extends JsCmd with HasTime { + class Hide(val uid: String, val time: Box[FiniteDuration]) extends JsCmd with HasTime { def toJsCmd = "try{jQuery(" + ("#" + uid).encJs + ").hide(" + timeStr + ");} catch (e) {}" } /** * Show a message msg in the element with id where for duration milliseconds and fade out in fadeout milliseconds */ - case class DisplayMessage(where: String, msg: NodeSeq, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { + case class DisplayMessage(where: String, msg: NodeSeq, duration: FiniteDuration, fadeTime: FiniteDuration) extends JsCmd { def toJsCmd = (Show(where) & JqSetHtml(where, msg) & After(duration, Hide(where, fadeTime))).toJsCmd } @@ -571,8 +572,8 @@ object JqJsCmds { * Fades out the element having the provided id, by waiting * for the given duration and fading out during fadeTime */ - case class FadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { - def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeOut(" + fadeTime.millis + ")") with JsMember))).toJsCmd + case class FadeOut(id: String, duration: FiniteDuration, fadeTime: FiniteDuration) extends JsCmd { + def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeOut(" + fadeTime.toMillis + ")") with JsMember))).toJsCmd } /** @@ -590,8 +591,8 @@ object JqJsCmds { * for the given duration and fading in during fadeTime * and use @fadeTime */ - case class FadeIn(id: String, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { - def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeIn(" + fadeTime.millis + ")") with JsMember))).toJsCmd + case class FadeIn(id: String, duration: FiniteDuration, fadeTime: FiniteDuration) extends JsCmd { + def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeIn(" + fadeTime.toMillis + ")") with JsMember))).toJsCmd } /** diff --git a/web/webkit/src/main/scala/net/liftweb/http/js/yui/YUIArtifacts.scala b/web/webkit/src/main/scala/net/liftweb/http/js/yui/YUIArtifacts.scala index ff5a03e6e..de41d5787 100755 --- a/web/webkit/src/main/scala/net/liftweb/http/js/yui/YUIArtifacts.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/js/yui/YUIArtifacts.scala @@ -20,6 +20,7 @@ package js package yui import scala.xml.{Elem, NodeSeq} +import scala.concurrent.duration.FiniteDuration import net.liftweb.http.S import net.liftweb.http.js.JE @@ -119,7 +120,7 @@ object YUIArtifacts extends JSArtifacts { * Fades out the element having the provided id, by waiting * for the given duration and fades out during fadeTime */ - def fadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan) = Noop + def fadeOut(id: String, duration: FiniteDuration, fadeTime: FiniteDuration) = Noop /** * Trabsforms a JSON object intoits string representation