github.com/hairyhenderson/templater@v3.5.0+incompatible/funcs/time.go (about)

     1  package funcs
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  	"sync"
     8  	gotime "time"
     9  
    10  	"github.com/hairyhenderson/gomplate/conv"
    11  	"github.com/hairyhenderson/gomplate/time"
    12  )
    13  
    14  var (
    15  	timeNS     *TimeFuncs
    16  	timeNSInit sync.Once
    17  )
    18  
    19  // TimeNS -
    20  func TimeNS() *TimeFuncs {
    21  	timeNSInit.Do(func() {
    22  		timeNS = &TimeFuncs{
    23  			ANSIC:       gotime.ANSIC,
    24  			UnixDate:    gotime.UnixDate,
    25  			RubyDate:    gotime.RubyDate,
    26  			RFC822:      gotime.RFC822,
    27  			RFC822Z:     gotime.RFC822Z,
    28  			RFC850:      gotime.RFC850,
    29  			RFC1123:     gotime.RFC1123,
    30  			RFC1123Z:    gotime.RFC1123Z,
    31  			RFC3339:     gotime.RFC3339,
    32  			RFC3339Nano: gotime.RFC3339Nano,
    33  			Kitchen:     gotime.Kitchen,
    34  			Stamp:       gotime.Stamp,
    35  			StampMilli:  gotime.StampMilli,
    36  			StampMicro:  gotime.StampMicro,
    37  			StampNano:   gotime.StampNano,
    38  		}
    39  	})
    40  	return timeNS
    41  }
    42  
    43  // AddTimeFuncs -
    44  func AddTimeFuncs(f map[string]interface{}) {
    45  	f["time"] = TimeNS
    46  }
    47  
    48  // TimeFuncs -
    49  type TimeFuncs struct {
    50  	ANSIC       string
    51  	UnixDate    string
    52  	RubyDate    string
    53  	RFC822      string
    54  	RFC822Z     string
    55  	RFC850      string
    56  	RFC1123     string
    57  	RFC1123Z    string
    58  	RFC3339     string
    59  	RFC3339Nano string
    60  	Kitchen     string
    61  	Stamp       string
    62  	StampMilli  string
    63  	StampMicro  string
    64  	StampNano   string
    65  }
    66  
    67  // ZoneName - return the local system's time zone's name
    68  func (f *TimeFuncs) ZoneName() string {
    69  	return time.ZoneName()
    70  }
    71  
    72  // ZoneOffset - return the local system's time zone's name
    73  func (f *TimeFuncs) ZoneOffset() int {
    74  	return time.ZoneOffset()
    75  }
    76  
    77  // Parse -
    78  func (f *TimeFuncs) Parse(layout string, value interface{}) (gotime.Time, error) {
    79  	return gotime.Parse(layout, conv.ToString(value))
    80  }
    81  
    82  // ParseLocal -
    83  func (f *TimeFuncs) ParseLocal(layout string, value interface{}) (gotime.Time, error) {
    84  	return gotime.ParseInLocation(layout, conv.ToString(value), gotime.Local)
    85  }
    86  
    87  // ParseInLocation -
    88  func (f *TimeFuncs) ParseInLocation(layout, location string, value interface{}) (gotime.Time, error) {
    89  	loc, err := gotime.LoadLocation(location)
    90  	if err != nil {
    91  		return gotime.Time{}, err
    92  	}
    93  	return gotime.ParseInLocation(layout, conv.ToString(value), loc)
    94  }
    95  
    96  // Now -
    97  func (f *TimeFuncs) Now() gotime.Time {
    98  	return gotime.Now()
    99  }
   100  
   101  // Unix - convert UNIX time (in seconds since the UNIX epoch) into a time.Time for further processing
   102  // Takes a string or number (int or float)
   103  func (f *TimeFuncs) Unix(in interface{}) (gotime.Time, error) {
   104  	sec, nsec, err := parseNum(in)
   105  	if err != nil {
   106  		return gotime.Time{}, err
   107  	}
   108  	return gotime.Unix(sec, nsec), nil
   109  }
   110  
   111  // Nanosecond -
   112  func (f *TimeFuncs) Nanosecond(n interface{}) gotime.Duration {
   113  	return gotime.Nanosecond * gotime.Duration(conv.ToInt64(n))
   114  }
   115  
   116  // Microsecond -
   117  func (f *TimeFuncs) Microsecond(n interface{}) gotime.Duration {
   118  	return gotime.Microsecond * gotime.Duration(conv.ToInt64(n))
   119  }
   120  
   121  // Millisecond -
   122  func (f *TimeFuncs) Millisecond(n interface{}) gotime.Duration {
   123  	return gotime.Millisecond * gotime.Duration(conv.ToInt64(n))
   124  }
   125  
   126  // Second -
   127  func (f *TimeFuncs) Second(n interface{}) gotime.Duration {
   128  	return gotime.Second * gotime.Duration(conv.ToInt64(n))
   129  }
   130  
   131  // Minute -
   132  func (f *TimeFuncs) Minute(n interface{}) gotime.Duration {
   133  	return gotime.Minute * gotime.Duration(conv.ToInt64(n))
   134  }
   135  
   136  // Hour -
   137  func (f *TimeFuncs) Hour(n interface{}) gotime.Duration {
   138  	return gotime.Hour * gotime.Duration(conv.ToInt64(n))
   139  }
   140  
   141  // ParseDuration -
   142  func (f *TimeFuncs) ParseDuration(n interface{}) (gotime.Duration, error) {
   143  	return gotime.ParseDuration(conv.ToString(n))
   144  }
   145  
   146  // Since -
   147  func (f *TimeFuncs) Since(n gotime.Time) gotime.Duration {
   148  	return gotime.Since(n)
   149  }
   150  
   151  // Until -
   152  func (f *TimeFuncs) Until(n gotime.Time) gotime.Duration {
   153  	return gotime.Until(n)
   154  }
   155  
   156  // convert a number input to a pair of int64s, representing the integer portion and the decimal remainder
   157  // this can handle a string as well as any integer or float type
   158  // precision is at the "nano" level (i.e. 1e+9)
   159  func parseNum(in interface{}) (integral int64, fractional int64, err error) {
   160  	if s, ok := in.(string); ok {
   161  		ss := strings.Split(s, ".")
   162  		if len(ss) > 2 {
   163  			return 0, 0, fmt.Errorf("can not parse '%s' as a number - too many decimal points", s)
   164  		}
   165  		if len(ss) == 1 {
   166  			integral, err := strconv.ParseInt(s, 0, 64)
   167  			return integral, 0, err
   168  		}
   169  		integral, err := strconv.ParseInt(ss[0], 0, 64)
   170  		if err != nil {
   171  			return integral, 0, err
   172  		}
   173  		fractional, err = strconv.ParseInt(padRight(ss[1], "0", 9), 0, 64)
   174  		return integral, fractional, err
   175  	}
   176  	if s, ok := in.(fmt.Stringer); ok {
   177  		return parseNum(s.String())
   178  	}
   179  	if i, ok := in.(int); ok {
   180  		return int64(i), 0, nil
   181  	}
   182  	if u, ok := in.(uint64); ok {
   183  		return int64(u), 0, nil
   184  	}
   185  	if f, ok := in.(float64); ok {
   186  		return 0, 0, fmt.Errorf("can not parse floating point number (%f) - use a string instead", f)
   187  	}
   188  	if in == nil {
   189  		return 0, 0, nil
   190  	}
   191  	return 0, 0, nil
   192  }
   193  
   194  // pads a number with zeroes
   195  func padRight(in, pad string, length int) string {
   196  	for {
   197  		in += pad
   198  		if len(in) > length {
   199  			return in[0:length]
   200  		}
   201  	}
   202  }