Files
patrick 9a24ea29e1 FDN-01: repository & projektgerüst
Git-Repository für bestehenden archivdms-Code initialisiert, Branch-/Commit-Konvention (feature/<ticket>-<slug>-Branches, Ticket-Prefix in Commit-Nachricht) etabliert.
2026-08-11 21:27:53 +02:00

62 lines
2.1 KiB
Go

// Package dateformat translates a small, user-friendly token pattern (e.g.
// "DD.MM.YYYY HH:mm") into a Go time layout ("02.01.2006 15:04"). It is a
// neutral package imported by both internal/api and internal/tenantstore so
// they can share one validator without importing each other (which would be a
// circular dependency).
//
// Admins may enter an arbitrary token string; anything that is not a known
// token is preserved verbatim as literal text in the resulting layout.
package dateformat
import (
"fmt"
"regexp"
"unicode/utf8"
)
// MaxPatternLen bounds the token pattern length, mirroring the scan-title
// prefix limit so an oversized value can never be persisted.
const MaxPatternLen = 40
// tokenLayout maps each supported token to its Go reference-time fragment.
// Order matters at match time (longest first) so e.g. "YYYY" is not consumed
// as "YY"+"YY"; the regex alternation below encodes that ordering explicitly.
var tokenLayout = map[string]string{
"AM/PM": "PM",
"YYYY": "2006",
"YY": "06",
"MM": "01",
"DD": "02",
"HH": "15",
"hh": "03",
"mm": "04",
"ss": "05",
"PM": "PM",
}
// tokenRE matches known tokens, longest alternatives first so a greedy leftmost
// match never splits a long token into shorter ones.
var tokenRE = regexp.MustCompile(`AM/PM|YYYY|YY|MM|DD|HH|hh|mm|ss|PM`)
// Translate converts a token pattern into a Go time layout. It fails when the
// pattern is empty, too long, or contains no recognised token (a pattern of
// pure literal text would make time.Format return that literal unchanged,
// which is never what the admin intends).
func Translate(pattern string) (goLayout string, err error) {
if pattern == "" {
return "", fmt.Errorf("Format darf nicht leer sein")
}
if utf8.RuneCountInString(pattern) > MaxPatternLen {
return "", fmt.Errorf("Format zu lang (max %d Zeichen)", MaxPatternLen)
}
matched := false
layout := tokenRE.ReplaceAllStringFunc(pattern, func(tok string) string {
matched = true
return tokenLayout[tok]
})
if !matched {
return "", fmt.Errorf("Format muss mindestens einen Datums-/Zeit-Platzhalter enthalten")
}
return layout, nil
}