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.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user