package com.vgmlr.varnish
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Month
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.Locale
object VarnishClock {
private val YY = DateTimeFormatter.ofPattern("yy")
private val HM = DateTimeFormatter.ofPattern("HH:mm")
private val DM = DateTimeFormatter.ofPattern("dd MMM", Locale.ENGLISH)
private val SPLIT = Regex("[\\s,]+")
fun stamp(millis: Long): String =
stamp(LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()))
fun stamp(dt: LocalDateTime): String {
val start = yearStart(dt.toLocalDate())
val day = ChronoUnit.DAYS.between(start, dt.toLocalDate()) + 1
val year = "0" + start.format(YY)
return "${dt.format(HM)} $day $year (${dt.format(DM)})"
}
private fun yearStart(d: LocalDate): LocalDate {
val mark = LocalDate.of(d.year, 3, 20)
return if (d.isBefore(mark)) mark.minusYears(1) else mark
}
fun matcher(q: String): ((Long) -> Boolean)? {
val parts = q.lowercase(Locale.ROOT).split(SPLIT).filter(String::isNotEmpty)
var year: Int? = null
var month: Int? = null
var day: Int? = null
for (p in parts) {
val n = p.toIntOrNull()
when {
n != null && p.length == 4 && year == null -> year = n
n != null && p.length <= 2 && n in 1..31 && day == null -> day = n
n == null && month == null -> month = monthOf(p) ?: return null
else -> return null
}
}
if (year == null && month == null) return null
val y = year
val m = month
val d = day
val zone = ZoneId.systemDefault()
return { ms ->
val at = Instant.ofEpochMilli(ms).atZone(zone).toLocalDate()
(y == null || at.year == y) &&
(m == null || at.monthValue == m) &&
(d == null || at.dayOfMonth == d)
}
}
private fun monthOf(p: String): Int? =
if (p.length < 3) null
else Month.entries.firstOrNull { it.name.lowercase(Locale.ROOT).startsWith(p) }?.value
}