time.go (3622B)
1 // Copyright 2017 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 // Package time provides template functions for measuring and displaying time.
15 package time
16
17 import (
18 "fmt"
19 "time"
20 _time "time"
21
22 "github.com/gohugoio/hugo/common/htime"
23
24 "github.com/spf13/cast"
25 )
26
27 // New returns a new instance of the time-namespaced template functions.
28 func New(timeFormatter htime.TimeFormatter, location *time.Location) *Namespace {
29 return &Namespace{
30 timeFormatter: timeFormatter,
31 location: location,
32 }
33 }
34
35 // Namespace provides template functions for the "time" namespace.
36 type Namespace struct {
37 timeFormatter htime.TimeFormatter
38 location *time.Location
39 }
40
41 // AsTime converts the textual representation of the datetime string into
42 // a time.Time interface.
43 func (ns *Namespace) AsTime(v any, args ...any) (any, error) {
44 loc := ns.location
45 if len(args) > 0 {
46 locStr, err := cast.ToStringE(args[0])
47 if err != nil {
48 return nil, err
49 }
50 loc, err = _time.LoadLocation(locStr)
51 if err != nil {
52 return nil, err
53 }
54 }
55
56 return htime.ToTimeInDefaultLocationE(v, loc)
57
58 }
59
60 // Format converts the textual representation of the datetime string in v into
61 // time.Time if needed and formats it with the given layout.
62 func (ns *Namespace) Format(layout string, v any) (string, error) {
63 t, err := htime.ToTimeInDefaultLocationE(v, ns.location)
64 if err != nil {
65 return "", err
66 }
67
68 return ns.timeFormatter.Format(t, layout), nil
69 }
70
71 // Now returns the current local time or `clock` time
72 func (ns *Namespace) Now() _time.Time {
73 return htime.Now()
74 }
75
76 // ParseDuration parses the duration string s.
77 // A duration string is a possibly signed sequence of
78 // decimal numbers, each with optional fraction and a unit suffix,
79 // such as "300ms", "-1.5h" or "2h45m".
80 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
81 // See https://golang.org/pkg/time/#ParseDuration
82 func (ns *Namespace) ParseDuration(s any) (_time.Duration, error) {
83 ss, err := cast.ToStringE(s)
84 if err != nil {
85 return 0, err
86 }
87
88 return _time.ParseDuration(ss)
89 }
90
91 var durationUnits = map[string]_time.Duration{
92 "nanosecond": _time.Nanosecond,
93 "ns": _time.Nanosecond,
94 "microsecond": _time.Microsecond,
95 "us": _time.Microsecond,
96 "µs": _time.Microsecond,
97 "millisecond": _time.Millisecond,
98 "ms": _time.Millisecond,
99 "second": _time.Second,
100 "s": _time.Second,
101 "minute": _time.Minute,
102 "m": _time.Minute,
103 "hour": _time.Hour,
104 "h": _time.Hour,
105 }
106
107 // Duration converts the given number to a time.Duration.
108 // Unit is one of nanosecond/ns, microsecond/us/µs, millisecond/ms, second/s, minute/m or hour/h.
109 func (ns *Namespace) Duration(unit any, number any) (_time.Duration, error) {
110 unitStr, err := cast.ToStringE(unit)
111 if err != nil {
112 return 0, err
113 }
114 unitDuration, found := durationUnits[unitStr]
115 if !found {
116 return 0, fmt.Errorf("%q is not a valid duration unit", unit)
117 }
118 n, err := cast.ToInt64E(number)
119 if err != nil {
120 return 0, err
121 }
122 return _time.Duration(n) * unitDuration, nil
123 }