1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package strfmt
16
17 import (
18 "database/sql/driver"
19 "encoding/json"
20 "errors"
21 "fmt"
22 "regexp"
23 "strconv"
24 "strings"
25 "time"
26
27 "go.mongodb.org/mongo-driver/bson"
28 )
29
30 func init() {
31 d := Duration(0)
32
33 Default.Add("duration", &d, IsDuration)
34 }
35
36 var (
37 timeUnits = [][]string{
38 {"ns", "nano"},
39 {"us", "µs", "micro"},
40 {"ms", "milli"},
41 {"s", "sec"},
42 {"m", "min"},
43 {"h", "hr", "hour"},
44 {"d", "day"},
45 {"w", "wk", "week"},
46 }
47
48 timeMultiplier = map[string]time.Duration{
49 "ns": time.Nanosecond,
50 "us": time.Microsecond,
51 "ms": time.Millisecond,
52 "s": time.Second,
53 "m": time.Minute,
54 "h": time.Hour,
55 "d": 24 * time.Hour,
56 "w": 7 * 24 * time.Hour,
57 }
58
59 durationMatcher = regexp.MustCompile(`((\d+)\s*([A-Za-zµ]+))`)
60 )
61
62
63 func IsDuration(str string) bool {
64 _, err := ParseDuration(str)
65 return err == nil
66 }
67
68
69
70
71
72
73
74 type Duration time.Duration
75
76
77 func (d Duration) MarshalText() ([]byte, error) {
78 return []byte(time.Duration(d).String()), nil
79 }
80
81
82 func (d *Duration) UnmarshalText(data []byte) error {
83 dd, err := ParseDuration(string(data))
84 if err != nil {
85 return err
86 }
87 *d = Duration(dd)
88 return nil
89 }
90
91
92 func ParseDuration(cand string) (time.Duration, error) {
93 if dur, err := time.ParseDuration(cand); err == nil {
94 return dur, nil
95 }
96
97 var dur time.Duration
98 ok := false
99 for _, match := range durationMatcher.FindAllStringSubmatch(cand, -1) {
100
101 factor, err := strconv.Atoi(match[2])
102 if err != nil {
103 return 0, err
104 }
105 unit := strings.ToLower(strings.TrimSpace(match[3]))
106
107 for _, variants := range timeUnits {
108 last := len(variants) - 1
109 multiplier := timeMultiplier[variants[0]]
110
111 for i, variant := range variants {
112 if (last == i && strings.HasPrefix(unit, variant)) || strings.EqualFold(variant, unit) {
113 ok = true
114 dur += (time.Duration(factor) * multiplier)
115 }
116 }
117 }
118 }
119
120 if ok {
121 return dur, nil
122 }
123 return 0, fmt.Errorf("unable to parse %s as duration", cand)
124 }
125
126
127 func (d *Duration) Scan(raw interface{}) error {
128 switch v := raw.(type) {
129
130 case int64:
131 *d = Duration(v)
132 case float64:
133 *d = Duration(int64(v))
134 case nil:
135 *d = Duration(0)
136 default:
137 return fmt.Errorf("cannot sql.Scan() strfmt.Duration from: %#v", v)
138 }
139
140 return nil
141 }
142
143
144 func (d Duration) Value() (driver.Value, error) {
145 return driver.Value(int64(d)), nil
146 }
147
148
149 func (d Duration) String() string {
150 return time.Duration(d).String()
151 }
152
153
154 func (d Duration) MarshalJSON() ([]byte, error) {
155 return json.Marshal(time.Duration(d).String())
156 }
157
158
159 func (d *Duration) UnmarshalJSON(data []byte) error {
160 if string(data) == jsonNull {
161 return nil
162 }
163
164 var dstr string
165 if err := json.Unmarshal(data, &dstr); err != nil {
166 return err
167 }
168 tt, err := ParseDuration(dstr)
169 if err != nil {
170 return err
171 }
172 *d = Duration(tt)
173 return nil
174 }
175
176 func (d Duration) MarshalBSON() ([]byte, error) {
177 return bson.Marshal(bson.M{"data": d.String()})
178 }
179
180 func (d *Duration) UnmarshalBSON(data []byte) error {
181 var m bson.M
182 if err := bson.Unmarshal(data, &m); err != nil {
183 return err
184 }
185
186 if data, ok := m["data"].(string); ok {
187 rd, err := ParseDuration(data)
188 if err != nil {
189 return err
190 }
191 *d = Duration(rd)
192 return nil
193 }
194
195 return errors.New("couldn't unmarshal bson bytes value as Date")
196 }
197
198
199 func (d *Duration) DeepCopyInto(out *Duration) {
200 *out = *d
201 }
202
203
204 func (d *Duration) DeepCopy() *Duration {
205 if d == nil {
206 return nil
207 }
208 out := new(Duration)
209 d.DeepCopyInto(out)
210 return out
211 }
212
View as plain text