// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // expander-time-funcs.go package text import ( "errors" "fmt" "strconv" "strings" "time" ) const func_time_fmt = "__time-fmt" /* If format is empty, the default template will be used. */ func TimeFmt(when time.Time, format string) (result string, err error) { var sb strings.Builder var sep byte = 0 var filler byte var field int if len(format) == 0 { format = "%Y-%m-%d %H:%M:%S" } perc := false i := 0 for i < len(format) && err == nil { ch := format[i] if ch == '%' { if perc { sb.WriteByte(ch) perc = false } else { perc = true } } else if perc { perc = false switch ch { case '.', '-', '/', '_', ':': if field > 0 { err = fmt.Errorf("invalid time specifier format at %d", i) } else { sep = ch j := i + 1 if j < len(format) && (format[j] == '0' || format[j] == ' ') { filler = format[j] j++ start := j for j < len(format) && format[j] >= '0' && format[j] <= '9' { j++ } field, err = strconv.Atoi(format[start:j]) i = j - 1 } perc = true } case '0', ' ': filler = ch j := i + 1 for j < len(format) && format[j] >= '0' && format[j] <= '9' { j++ } field, err = strconv.Atoi(format[i+1 : j]) i = j - 1 perc = true default: switch ch { case 'D': if filler != 0 { templ := fmt.Sprintf("%%d%c%%%c%dd%c%%%c%dd", sep, filler, field, sep, filler, field) _, err = sb.WriteString(fmt.Sprintf(templ, when.Year(), when.Month(), when.Day())) } else { _, err = sb.WriteString(fmt.Sprintf("%d%c%*d%c%*d", when.Year(), sep, field, when.Month(), sep, field, when.Day())) } case 'T': if filler != 0 { templ := fmt.Sprintf("%%%c%dd%c%%%c%dd%c%%%c%dd", filler, field, sep, filler, field, sep, filler, field) _, err = sb.WriteString(fmt.Sprintf(templ, when.Hour(), when.Minute(), when.Second())) } else { _, err = sb.WriteString(fmt.Sprintf("%d%c%*d%c%*d", when.Hour(), sep, field, when.Minute(), sep, field, when.Second())) } case 'Y': _, err = sb.WriteString(fmt.Sprintf("%d", when.Year())) case 'm': _, err = sb.WriteString(fmt.Sprintf("%02d", when.Month())) case 'd': _, err = sb.WriteString(fmt.Sprintf("%02d", when.Day())) case 'H': _, err = sb.WriteString(fmt.Sprintf("%02d", when.Hour())) case 'M': _, err = sb.WriteString(fmt.Sprintf("%02d", when.Minute())) case 'S': _, err = sb.WriteString(fmt.Sprintf("%02d", when.Second())) default: err = fmt.Errorf("unsupported '%c' time specifier at %q/%d", ch, format, i+1) } filler = 0 field = 0 sep = 0 } } else { err = sb.WriteByte(ch) } i++ } if err == nil { result = sb.String() } return } func parseDelta(source string) (delta time.Duration) { // TODO implementare var err error if delta, err = time.ParseDuration(strings.TrimSpace(source)); err != nil { delta = 0 } return } // Format a time value using a template (see TimeFmt()). // __time-fmt