Path: blob/main/vendor/github.com/spf13/cast/time.go
2875 views
// Copyright © 2014 Steve Francia <[email protected]>.1//2// Use of this source code is governed by an MIT-style3// license that can be found in the LICENSE file.45package cast67import (8"encoding/json"9"errors"10"fmt"11"strings"12"time"1314"github.com/spf13/cast/internal"15)1617// ToTimeE any value to a [time.Time] type.18func ToTimeE(i any) (time.Time, error) {19return ToTimeInDefaultLocationE(i, time.UTC)20}2122// ToTimeInDefaultLocationE casts an empty interface to [time.Time],23// interpreting inputs without a timezone to be in the given location,24// or the local timezone if nil.25func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, err error) {26i, _ = indirect(i)2728switch v := i.(type) {29case time.Time:30return v, nil31case string:32return StringToDateInDefaultLocation(v, location)33case json.Number:34// Originally this used ToInt64E, but adding string float conversion broke ToTime.35// the behavior of ToTime would have changed if we continued using it.36// For now, using json.Number's own Int64 method should be good enough to preserve backwards compatibility.37v = json.Number(trimZeroDecimal(string(v)))38s, err1 := v.Int64()39if err1 != nil {40return time.Time{}, fmt.Errorf(errorMsg, i, i, time.Time{})41}42return time.Unix(s, 0), nil43case int:44return time.Unix(int64(v), 0), nil45case int32:46return time.Unix(int64(v), 0), nil47case int64:48return time.Unix(v, 0), nil49case uint:50return time.Unix(int64(v), 0), nil51case uint32:52return time.Unix(int64(v), 0), nil53case uint64:54return time.Unix(int64(v), 0), nil55case nil:56return time.Time{}, nil57default:58return time.Time{}, fmt.Errorf(errorMsg, i, i, time.Time{})59}60}6162// ToDurationE casts any value to a [time.Duration] type.63func ToDurationE(i any) (time.Duration, error) {64i, _ = indirect(i)6566switch s := i.(type) {67case time.Duration:68return s, nil69case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:70v, err := ToInt64E(s)71if err != nil {72// TODO: once there is better error handling, this should be easier73return 0, errors.New(strings.ReplaceAll(err.Error(), " int64", "time.Duration"))74}7576return time.Duration(v), nil77case float32, float64, float64EProvider, float64Provider:78v, err := ToFloat64E(s)79if err != nil {80// TODO: once there is better error handling, this should be easier81return 0, errors.New(strings.ReplaceAll(err.Error(), " float64", "time.Duration"))82}8384return time.Duration(v), nil85case string:86if !strings.ContainsAny(s, "nsuµmh") {87return time.ParseDuration(s + "ns")88}8990return time.ParseDuration(s)91case nil:92return time.Duration(0), nil93default:94if i, ok := resolveAlias(i); ok {95return ToDurationE(i)96}9798return 0, fmt.Errorf(errorMsg, i, i, time.Duration(0))99}100}101102// StringToDate attempts to parse a string into a [time.Time] type using a103// predefined list of formats.104//105// If no suitable format is found, an error is returned.106func StringToDate(s string) (time.Time, error) {107return internal.ParseDateWith(s, time.UTC, internal.TimeFormats)108}109110// StringToDateInDefaultLocation casts an empty interface to a [time.Time],111// interpreting inputs without a timezone to be in the given location,112// or the local timezone if nil.113func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) {114return internal.ParseDateWith(s, location, internal.TimeFormats)115}116117118