Pith - wedge_android
wedge_android/app/src/main/java/com/vgmlr/wedge/WedgeHeader.kt [4.7 kb]
Modified: 00:00:27 153 026 (19 Aug 026)
5 Days Ago
package com.vgmlr.wedge

import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale

object WedgeHeader {

    private data class Tok(val text: String, val literal: Boolean)

    private fun tokenize(fmt: String): List<Tok> {
        val out = mutableListOf<Tok>()
        var i = 0
        while (i < fmt.length) {
            if (fmt.regionMatches(i, "otcDay", 0, 6))  { out.add(Tok("otcDay", false));  i += 6; continue }
            if (fmt.regionMatches(i, "otcYear", 0, 7)) { out.add(Tok("otcYear", false)); i += 7; continue }
            val c = fmt[i]
            var j = i
            if (c.isLetter()) {
                while (j < fmt.length && fmt[j] == c) j++
                out.add(Tok(fmt.substring(i, j), false))
            } else {
                while (j < fmt.length && !fmt[j].isLetter()) j++
                out.add(Tok(fmt.substring(i, j), true))
            }
            i = j
        }
        return out
    }

    private fun isDayTok(t: String) = t.equals("dd", true) || t.equals("d", true)

    private fun fmtDate(pattern: String, timestamp: Long): String =
        SimpleDateFormat(pattern, Locale.US).format(Date(timestamp))

    private fun tokValue(t: String, timestamp: Long): String {
        val parts = WedgeDate.getOtcParts(timestamp)
        return when {
            t == "otcDay"        -> parts.first.toString()
            t == "otcYear"       -> "0" + String.format(Locale.US, "%02d", parts.second)
            t == "EEEE"          -> fmtDate("EEEE", timestamp).lowercase(Locale.US)
            t == "EEE"           -> fmtDate("EEE", timestamp).lowercase(Locale.US)
            t == "MMMM"          -> fmtDate("MMMM", timestamp).lowercase(Locale.US)
            t == "MMM"           -> fmtDate("MMM", timestamp).lowercase(Locale.US)
            t == "MM"            -> fmtDate("MM", timestamp)
            t == "M"             -> fmtDate("M", timestamp)
            t.equals("dd", true) -> fmtDate("dd", timestamp)
            t.equals("d", true)  -> fmtDate("d", timestamp)
            t == "yyyy"          -> fmtDate("yyyy", timestamp)
            t == "yy"            -> fmtDate("yy", timestamp)
            else -> t
        }
    }

    private fun litPattern(s: String): String {
        val sb = StringBuilder()
        var i = 0
        while (i < s.length) {
            var j = i
            if (s[i].isWhitespace()) {
                while (j < s.length && s[j].isWhitespace()) j++
                sb.append("\\s+")
            } else {
                while (j < s.length && !s[j].isWhitespace()) j++
                sb.append(Regex.escape(s.substring(i, j)))
            }
            i = j
        }
        return sb.toString()
    }

    private fun tokPattern(t: String): String = when {
        t == "otcDay"  -> "(?<otc>\\d+)"
        t == "otcYear" -> "\\d{1,4}"
        t.startsWith("E") || t == "MMM" || t == "MMMM" -> "[a-zA-Z]{3,}"
        t == "MM" || t == "M" -> "\\d{1,2}"
        isDayTok(t) -> "0?\\d{1,2}"
        t == "yyyy" -> "\\d{4}"
        t == "yy"   -> "\\d{2}"
        else -> Regex.escape(t)
    }

    fun render(format: String, timestamp: Long): String {
        val sb = StringBuilder()
        for (t in tokenize(format)) sb.append(if (t.literal) t.text else tokValue(t.text, timestamp))
        return sb.toString()
    }

    fun matchRegex(format: String): Regex {
        val toks = tokenize(format)
        val sb = StringBuilder("^")
        for (i in toks.indices) {
            val t = toks[i]
            if (!t.literal) { sb.append(tokPattern(t.text)); continue }
            val lp = litPattern(t.text)
            sb.append(if (i == toks.size - 1) "(?:$lp)?" else lp)
        }
        sb.append(".*")
        return Regex(sb.toString(), setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
    }

    fun dateRegex(format: String, timestamp: Long): Regex {
        val toks = tokenize(format)
        val sb = StringBuilder("^")
        for (i in toks.indices) {
            val t = toks[i]
            when {
                t.literal -> {
                    val lp = litPattern(t.text)
                    sb.append(if (i == toks.size - 1) "(?:$lp)?" else lp)
                }
                isDayTok(t.text) -> {
                    val cal = Calendar.getInstance().apply { timeInMillis = timestamp }
                    sb.append("0?" + Regex.escape(cal.get(Calendar.DAY_OF_MONTH).toString()))
                }
                else -> sb.append(Regex.escape(tokValue(t.text, timestamp)))
            }
        }
        sb.append(".*")
        return Regex(sb.toString(), setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
    }

    fun otcDayFromMatch(match: MatchResult): Int? = match.groups["otc"]?.value?.toIntOrNull()
}
Updates
Kerf - Android 157.026
Kiln - Android 157.026
Wedge - Android 156.026
Whittle - Linux 155.026
Grit - Firefox/Chrome 154.026

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)
0.00527
256,826 (+80)