src/main/scala/net/tz/lift/model/JodaTimeField.scala
author Tomas Zeman <tzeman@volny.cz>
Thu, 24 May 2012 11:19:26 +0200
changeset 99 49eb72a46208
parent 24 149113e059bd
permissions -rw-r--r--
e45557248ba12a15 Services

/*
 * Copyright 2012 Tomas Zeman <tzeman@volny.cz>
 *
 * 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.tz.lift.model

import java.util.Calendar
import net.liftweb.common._
import net.liftweb.http._
import net.liftweb.record._
import net.liftweb.record.field._
import net.liftweb.util._
import net.liftweb.util.Helpers._
import org.joda.time.{DateTime, DateMidnight}
import org.joda.time.base.AbstractDateTime
import org.joda.time.format.DateTimeFormat
import scala.xml.{Elem, Text, Unparsed}

/**
 * Joda date time field. Renders view in Czech format; renders form as 3 text
 * fields w/ css classes: <code>date</code>, <code>hour</code>,
 * <code>minute</code> to be rendered via CSS (date picker etc.).
 */
class JodaDateTimeField[T <: Record[T]](rec: T) extends DateTimeField(rec) {
  override def setFromAny(in: Any): Box[Calendar] = in match {
    case dt: AbstractDateTime => setBox(Full(dt.toGregorianCalendar))
    case x => super.setFromAny(x)
  }

  def set(dt: AbstractDateTime): Calendar = set(dt.toGregorianCalendar)

  def dateTime = new DateTime(get)

  private def mdt = dateTime.toMutableDateTime

  override def asHtml = Text(AsDateTime(dateTime))
  override def toForm = Full(
    SHtml.text(AsDateMidnight(dateTime.toDateMidnight), { s =>
      val v = mdt
      AsDateMidnight(s) foreach { in =>
        v.setYear(in.getYear)
        v.setMonthOfYear(in.getMonthOfYear)
        v.setDayOfMonth(in.getDayOfMonth)
      }
      set(v.toGregorianCalendar) }, "class" -> "date") ++ Unparsed("&nbsp;") ++
    SHtml.selectObj[Int]((0 to 23) map { v => (v, "%02d".format(v)) },
      Full(dateTime.getHourOfDay), { h =>
      val v = mdt
      v.setHourOfDay(h)
      set(v.toGregorianCalendar) }, "class" -> "hour") ++ Text(":") ++
    SHtml.selectObj[Int](Range(0, 60, minuteStep) map { v =>
      (v, "%02d".format(v)) },
      Full(dateTime.getMinuteOfHour / minuteStep * minuteStep), { m =>
      val v = mdt
      v.setMinuteOfHour(m)
      set(v.toGregorianCalendar) }, "class" -> "minute")
  )

  val minuteStep: Int = 5
}

/**
 * Joda date field.
 */
class JodaDateMidnightField[T <: Record[T]](rec: T) extends DateTimeField(rec) {
  override def setFromAny(in: Any): Box[Calendar] = in match {
    case dt: AbstractDateTime => setBox(Full(dt.toGregorianCalendar))
    case x => super.setFromAny(x)
  }

  def set(dt: AbstractDateTime): Calendar = set(dt.toGregorianCalendar)

  def date = new DateMidnight(get)

  override def asHtml = Text(AsDateMidnight(date))
  override def toForm = Full(SHtml.text(AsDateMidnight(date),
    s => setBox(AsDateMidnight(s) map {_.toGregorianCalendar}),
    "class" -> "date"))
}

/**
 * Optional Joda date field.
 */
class OptionalJodaDateMidnightField[T <: Record[T]](rec: T) extends
  OptionalDateTimeField(rec) {
  override def setFromAny(in: Any): Box[Calendar] = in match {
    case dt: AbstractDateTime => setBox(Full(dt.toGregorianCalendar))
    case x => super.setFromAny(x)
  }

  def set(dt: Box[AbstractDateTime]): Box[Calendar] =
    set(dt map(_.toGregorianCalendar))

  def date = get map(new DateMidnight(_))

  override def toString = date map(AsDateMidnight(_)) getOrElse ""

  override def asHtml = Text(toString)
  override def toForm = Full(SHtml.text(toString,
    s => setBox(AsDateMidnight(s) map {_.toGregorianCalendar}),
    "class" -> "date"))
}

/**
 * Joda date-time converters.
 */
object AsDateTime {
  val fmt = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm")

  def apply(d: DateTime): String = fmt.print(d)
  def apply(s: String): Box[DateTime] = tryo { fmt.parseDateTime(s) }
}

/**
 * Joda date converters.
 */
object AsDateMidnight {
  val fmt = DateTimeFormat.forPattern("dd.MM.yyyy")

  def apply(d: DateMidnight): String = fmt.print(d)
  def apply(s: String): Box[DateMidnight] = s match {
    case null | "" => Empty
    case s => tryo { fmt.parseDateTime(s).toDateMidnight }
  }
}

// vim: set ts=2 sw=2 et: