blob: 38733d7d5b85438e8b6fb23601b077e6dc8678ff [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.griffin.measure.utils
import scala.util.{Failure, Success, Try}
import scala.util.matching.Regex
import org.apache.griffin.measure.Loggable
object TimeUtil extends Loggable {
private object Units {
case class TimeUnit(name: String, shortName: String, ut: Long, regex: Regex) {
def toMs(t: Long): Long = t * ut
def fromMs(ms: Long): Long = ms / ut
def fitUnit(ms: Long): Boolean = ms % ut == 0
}
val dayUnit: TimeUnit = TimeUnit("day", "d", 24 * 60 * 60 * 1000, """^(?i)d(?:ay)?$""".r)
val hourUnit: TimeUnit = TimeUnit("hour", "h", 60 * 60 * 1000, """^(?i)h(?:our|r)?$""".r)
val minUnit: TimeUnit = TimeUnit("minute", "m", 60 * 1000, """^(?i)m(?:in(?:ute)?)?$""".r)
val secUnit: TimeUnit = TimeUnit("second", "s", 1000, """^(?i)s(?:ec(?:ond)?)?$""".r)
val msUnit: TimeUnit =
TimeUnit("millisecond", "ms", 1, """^(?i)m(?:illi)?s(?:ec(?:ond)?)?$""".r)
val timeUnits: List[TimeUnit] = dayUnit :: hourUnit :: minUnit :: secUnit :: msUnit :: Nil
}
import Units._
// final val TimeRegex = """^([+\-]?\d+)(ms|s|m|h|d)$""".r
final val TimeRegex = """^([+\-]?\d+)([a-zA-Z]+)$""".r
final val PureTimeRegex = """^([+\-]?\d+)$""".r
def milliseconds(timeString: String): Option[Long] = {
val value: Option[Long] = {
Try {
timeString match {
case TimeRegex(time, unit) =>
val t = time.toLong
unit match {
case dayUnit.regex() => dayUnit.toMs(t)
case hourUnit.regex() => hourUnit.toMs(t)
case minUnit.regex() => minUnit.toMs(t)
case secUnit.regex() => secUnit.toMs(t)
case msUnit.regex() => msUnit.toMs(t)
case _ => throw new Exception(s"$timeString is invalid time format")
}
case PureTimeRegex(time) =>
val t = time.toLong
msUnit.toMs(t)
case _ => throw new Exception(s"$timeString is invalid time format")
}
} match {
case Success(v) => Some(v)
case Failure(_) => None
}
}
value
}
def timeToUnit(ms: Long, unit: String): Long = {
unit match {
case dayUnit.regex() => dayUnit.fromMs(ms)
case hourUnit.regex() => hourUnit.fromMs(ms)
case minUnit.regex() => minUnit.fromMs(ms)
case secUnit.regex() => secUnit.fromMs(ms)
case msUnit.regex() => msUnit.fromMs(ms)
case _ => ms
}
}
def timeFromUnit(t: Long, unit: String): Long = {
unit match {
case dayUnit.regex() => dayUnit.toMs(t)
case hourUnit.regex() => hourUnit.toMs(t)
case minUnit.regex() => minUnit.toMs(t)
case secUnit.regex() => secUnit.toMs(t)
case msUnit.regex() => msUnit.toMs(t)
case _ => t
}
}
def time2String(t: Long): String = {
val matchedUnitOpt = timeUnits.foldLeft(None: Option[TimeUnit]) { (retOpt, unit) =>
if (retOpt.isEmpty && unit.fitUnit(t)) Some(unit) else retOpt
}
val unit = matchedUnitOpt.getOrElse(msUnit)
val unitTime = unit.fromMs(t)
val unitStr = unit.shortName
s"$unitTime$unitStr"
}
}