diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2024-01-25 20:11:31 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-25 20:11:31 -0500 |
| commit | ebb97fb7367fb983cffc1935a8fb57e4b80f5249 (patch) | |
| tree | 43ef6cd01f629f60f59efe1e5b003f7c8e3a1257 /internal/funcs/time.go | |
| parent | f1d9158ea99abbe556251c1ff2fe970f3b460ee9 (diff) | |
Move funcs package to internal (#1977)
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'internal/funcs/time.go')
| -rw-r--r-- | internal/funcs/time.go | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/internal/funcs/time.go b/internal/funcs/time.go new file mode 100644 index 00000000..ca02a35a --- /dev/null +++ b/internal/funcs/time.go @@ -0,0 +1,229 @@ +package funcs + +import ( + "context" + "fmt" + "strconv" + "strings" + gotime "time" + + "github.com/hairyhenderson/gomplate/v4/conv" + "github.com/hairyhenderson/gomplate/v4/env" + "github.com/hairyhenderson/gomplate/v4/time" +) + +// TimeNS - +// +// Deprecated: don't use +func TimeNS() *TimeFuncs { + return &TimeFuncs{ + ANSIC: gotime.ANSIC, + UnixDate: gotime.UnixDate, + RubyDate: gotime.RubyDate, + RFC822: gotime.RFC822, + RFC822Z: gotime.RFC822Z, + RFC850: gotime.RFC850, + RFC1123: gotime.RFC1123, + RFC1123Z: gotime.RFC1123Z, + RFC3339: gotime.RFC3339, + RFC3339Nano: gotime.RFC3339Nano, + Kitchen: gotime.Kitchen, + Stamp: gotime.Stamp, + StampMilli: gotime.StampMilli, + StampMicro: gotime.StampMicro, + StampNano: gotime.StampNano, + } +} + +// AddTimeFuncs - +// +// Deprecated: use [CreateTimeFuncs] instead +func AddTimeFuncs(f map[string]interface{}) { + for k, v := range CreateTimeFuncs(context.Background()) { + f[k] = v + } +} + +// CreateTimeFuncs - +func CreateTimeFuncs(ctx context.Context) map[string]interface{} { + ns := &TimeFuncs{ + ctx: ctx, + ANSIC: gotime.ANSIC, + UnixDate: gotime.UnixDate, + RubyDate: gotime.RubyDate, + RFC822: gotime.RFC822, + RFC822Z: gotime.RFC822Z, + RFC850: gotime.RFC850, + RFC1123: gotime.RFC1123, + RFC1123Z: gotime.RFC1123Z, + RFC3339: gotime.RFC3339, + RFC3339Nano: gotime.RFC3339Nano, + Kitchen: gotime.Kitchen, + Stamp: gotime.Stamp, + StampMilli: gotime.StampMilli, + StampMicro: gotime.StampMicro, + StampNano: gotime.StampNano, + } + + return map[string]interface{}{ + "time": func() interface{} { return ns }, + } +} + +// TimeFuncs - +type TimeFuncs struct { + ctx context.Context + ANSIC string + UnixDate string + RubyDate string + RFC822 string + RFC822Z string + RFC850 string + RFC1123 string + RFC1123Z string + RFC3339 string + RFC3339Nano string + Kitchen string + Stamp string + StampMilli string + StampMicro string + StampNano string +} + +// ZoneName - return the local system's time zone's name +func (TimeFuncs) ZoneName() string { + return time.ZoneName() +} + +// ZoneOffset - return the local system's time zone's name +func (TimeFuncs) ZoneOffset() int { + return time.ZoneOffset() +} + +// Parse - +func (TimeFuncs) Parse(layout string, value interface{}) (gotime.Time, error) { + return gotime.Parse(layout, conv.ToString(value)) +} + +// ParseLocal - +func (f TimeFuncs) ParseLocal(layout string, value interface{}) (gotime.Time, error) { + tz := env.Getenv("TZ", "Local") + return f.ParseInLocation(layout, tz, value) +} + +// ParseInLocation - +func (TimeFuncs) ParseInLocation(layout, location string, value interface{}) (gotime.Time, error) { + loc, err := gotime.LoadLocation(location) + if err != nil { + return gotime.Time{}, err + } + return gotime.ParseInLocation(layout, conv.ToString(value), loc) +} + +// Now - +func (TimeFuncs) Now() gotime.Time { + return gotime.Now() +} + +// Unix - convert UNIX time (in seconds since the UNIX epoch) into a time.Time for further processing +// Takes a string or number (int or float) +func (TimeFuncs) Unix(in interface{}) (gotime.Time, error) { + sec, nsec, err := parseNum(in) + if err != nil { + return gotime.Time{}, err + } + return gotime.Unix(sec, nsec), nil +} + +// Nanosecond - +func (TimeFuncs) Nanosecond(n interface{}) gotime.Duration { + return gotime.Nanosecond * gotime.Duration(conv.ToInt64(n)) +} + +// Microsecond - +func (TimeFuncs) Microsecond(n interface{}) gotime.Duration { + return gotime.Microsecond * gotime.Duration(conv.ToInt64(n)) +} + +// Millisecond - +func (TimeFuncs) Millisecond(n interface{}) gotime.Duration { + return gotime.Millisecond * gotime.Duration(conv.ToInt64(n)) +} + +// Second - +func (TimeFuncs) Second(n interface{}) gotime.Duration { + return gotime.Second * gotime.Duration(conv.ToInt64(n)) +} + +// Minute - +func (TimeFuncs) Minute(n interface{}) gotime.Duration { + return gotime.Minute * gotime.Duration(conv.ToInt64(n)) +} + +// Hour - +func (TimeFuncs) Hour(n interface{}) gotime.Duration { + return gotime.Hour * gotime.Duration(conv.ToInt64(n)) +} + +// ParseDuration - +func (TimeFuncs) ParseDuration(n interface{}) (gotime.Duration, error) { + return gotime.ParseDuration(conv.ToString(n)) +} + +// Since - +func (TimeFuncs) Since(n gotime.Time) gotime.Duration { + return gotime.Since(n) +} + +// Until - +func (TimeFuncs) Until(n gotime.Time) gotime.Duration { + return gotime.Until(n) +} + +// convert a number input to a pair of int64s, representing the integer portion and the decimal remainder +// this can handle a string as well as any integer or float type +// precision is at the "nano" level (i.e. 1e+9) +func parseNum(in interface{}) (integral int64, fractional int64, err error) { + if s, ok := in.(string); ok { + ss := strings.Split(s, ".") + if len(ss) > 2 { + return 0, 0, fmt.Errorf("can not parse '%s' as a number - too many decimal points", s) + } + if len(ss) == 1 { + integral, err := strconv.ParseInt(s, 0, 64) + return integral, 0, err + } + integral, err := strconv.ParseInt(ss[0], 0, 64) + if err != nil { + return integral, 0, err + } + fractional, err = strconv.ParseInt(padRight(ss[1], "0", 9), 0, 64) + return integral, fractional, err + } + if s, ok := in.(fmt.Stringer); ok { + return parseNum(s.String()) + } + if i, ok := in.(int); ok { + return int64(i), 0, nil + } + if u, ok := in.(uint64); ok { + return int64(u), 0, nil + } + if f, ok := in.(float64); ok { + return 0, 0, fmt.Errorf("can not parse floating point number (%f) - use a string instead", f) + } + if in == nil { + return 0, 0, nil + } + return 0, 0, nil +} + +// pads a number with zeroes +func padRight(in, pad string, length int) string { + for { + in += pad + if len(in) > length { + return in[0:length] + } + } +} |
