Skip to content

Instantly share code, notes, and snippets.

@pronvis
Created September 21, 2017 13:34
Show Gist options
  • Save pronvis/900317ca91d157edac116200f1d63ff7 to your computer and use it in GitHub Desktop.
Save pronvis/900317ca91d157edac116200f1d63ff7 to your computer and use it in GitHub Desktop.
Apply string modifiers to joda DateTime
import org.joda.time.DateTime
object DateUtils {
def applyModifier(dt: DateTime, strWithModifiers: String): DateTime = {
val modifiers = parseString(strWithModifiers)
val withPlusesDt = modifiers.plusModifiers.foldLeft(dt) { case(newDt, dateModifier) => dateModifier.`type` match {
case "second" => newDt.plusSeconds(dateModifier.count)
case "seconds" => newDt.plusSeconds(dateModifier.count)
case "minute" => newDt.plusMinutes(dateModifier.count)
case "minutes" => newDt.plusMinutes(dateModifier.count)
case "hour" => newDt.plusHours(dateModifier.count)
case "hours" => newDt.plusHours(dateModifier.count)
case "day" => newDt.plusDays(dateModifier.count)
case "days" => newDt.plusDays(dateModifier.count)
case "week" => newDt.plusWeeks(dateModifier.count)
case "weeks" => newDt.plusWeeks(dateModifier.count)
case "month" => newDt.plusMonths(dateModifier.count)
case "months" => newDt.plusMonths(dateModifier.count)
case "year" => newDt.plusYears(dateModifier.count)
case "years" => newDt.plusYears(dateModifier.count)
}}
modifiers.minusModifiers.foldLeft(withPlusesDt) { case(newDt, dateModifier) => dateModifier.`type` match {
case "second" => newDt.minusSeconds(dateModifier.count)
case "seconds" => newDt.minusSeconds(dateModifier.count)
case "minute" => newDt.minusMinutes(dateModifier.count)
case "minutes" => newDt.minusMinutes(dateModifier.count)
case "hour" => newDt.minusHours(dateModifier.count)
case "hours" => newDt.minusHours(dateModifier.count)
case "day" => newDt.minusDays(dateModifier.count)
case "days" => newDt.minusDays(dateModifier.count)
case "week" => newDt.minusWeeks(dateModifier.count)
case "weeks" => newDt.minusWeeks(dateModifier.count)
case "month" => newDt.minusMonths(dateModifier.count)
case "months" => newDt.minusMonths(dateModifier.count)
case "year" => newDt.minusYears(dateModifier.count)
case "years" => newDt.minusYears(dateModifier.count)
}}
}
private def parseString(strToSplit: String): Modifiers = {
val firstChar = strToSplit.head
if(firstChar == '+' || firstChar == '-') {
val plusList = scala.collection.mutable.ListBuffer[String]()
val minusList = scala.collection.mutable.ListBuffer[String]()
var start: Int = -1
var index: Int = 0
var listToAdd: scala.collection.mutable.ListBuffer[String] = null
for (ch <- strToSplit.toCharArray) {
if (ch == '-' || ch == '+') {
if (start > 0) {
val modifier = strToSplit.substring(start, index)
listToAdd.append(modifier)
}
listToAdd = ch match {
case '-' => minusList
case '+' => plusList
}
start = index + 1
} else if (index + 1 == strToSplit.length) {
val modifier = strToSplit.substring(start, index + 1)
listToAdd.append(modifier)
}
index += 1
}
Modifiers(
plusList.toList.map(parseModifier),
minusList.toList.map(parseModifier))
} else {
throw new RuntimeException(s"wrong input line: '$strToSplit'")
}
}
private def parseModifier(modifier: String): DateModifier = {
val numberBuffer = new StringBuffer()
val wordBuffer = new StringBuffer()
for(ch <- modifier.toCharArray) {
if(ch.isDigit) {
numberBuffer.append(ch)
} else {
wordBuffer.append(ch)
}
}
val numberStr = numberBuffer.toString
val number = if(numberStr.isEmpty) 1 else numberStr.toInt
DateModifier(number, wordBuffer.toString)
}
private case class DateModifier(count: Int, `type`: String)
private case class Modifiers(
plusModifiers: List[DateModifier],
minusModifiers: List[DateModifier]
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment