podman

Форк
0
319 строк · 9.5 Кб
1
// Copyright 2015 go-swagger maintainers
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
//
7
//	http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package strfmt
16

17
import (
18
	"database/sql/driver"
19
	"encoding/binary"
20
	"encoding/json"
21
	"errors"
22
	"fmt"
23
	"regexp"
24
	"strings"
25
	"time"
26

27
	"go.mongodb.org/mongo-driver/bson"
28

29
	"go.mongodb.org/mongo-driver/bson/bsontype"
30
)
31

32
var (
33
	// UnixZero sets the zero unix timestamp we want to compare against.
34
	// Unix 0 for an EST timezone is not equivalent to a UTC timezone.
35
	UnixZero = time.Unix(0, 0).UTC()
36
)
37

38
func init() {
39
	dt := DateTime{}
40
	Default.Add("datetime", &dt, IsDateTime)
41
}
42

43
// IsDateTime returns true when the string is a valid date-time
44
func IsDateTime(str string) bool {
45
	if len(str) < 4 {
46
		return false
47
	}
48
	s := strings.Split(strings.ToLower(str), "t")
49
	if len(s) < 2 || !IsDate(s[0]) {
50
		return false
51
	}
52

53
	matches := rxDateTime.FindAllStringSubmatch(s[1], -1)
54
	if len(matches) == 0 || len(matches[0]) == 0 {
55
		return false
56
	}
57
	m := matches[0]
58
	res := m[1] <= "23" && m[2] <= "59" && m[3] <= "59"
59
	return res
60
}
61

62
const (
63
	// RFC3339Millis represents a ISO8601 format to millis instead of to nanos
64
	RFC3339Millis = "2006-01-02T15:04:05.000Z07:00"
65
	// RFC3339MillisNoColon represents a ISO8601 format to millis instead of to nanos
66
	RFC3339MillisNoColon = "2006-01-02T15:04:05.000Z0700"
67
	// RFC3339Micro represents a ISO8601 format to micro instead of to nano
68
	RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
69
	// RFC3339MicroNoColon represents a ISO8601 format to micro instead of to nano
70
	RFC3339MicroNoColon = "2006-01-02T15:04:05.000000Z0700"
71
	// ISO8601LocalTime represents a ISO8601 format to ISO8601 in local time (no timezone)
72
	ISO8601LocalTime = "2006-01-02T15:04:05"
73
	// ISO8601TimeWithReducedPrecision represents a ISO8601 format with reduced precision (dropped secs)
74
	ISO8601TimeWithReducedPrecision = "2006-01-02T15:04Z"
75
	// ISO8601TimeWithReducedPrecisionLocaltime represents a ISO8601 format with reduced precision and no timezone (dropped seconds + no timezone)
76
	ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04"
77
	// ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern.
78
	ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05"
79
	// DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6
80
	DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$`
81
)
82

83
var (
84
	rxDateTime = regexp.MustCompile(DateTimePattern)
85

86
	// DateTimeFormats is the collection of formats used by ParseDateTime()
87
	DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern}
88

89
	// MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds)
90
	MarshalFormat = RFC3339Millis
91

92
	// NormalizeTimeForMarshal provides a normalization function on time befeore marshalling (e.g. time.UTC).
93
	// By default, the time value is not changed.
94
	NormalizeTimeForMarshal = func(t time.Time) time.Time { return t }
95

96
	// DefaultTimeLocation provides a location for a time when the time zone is not encoded in the string (ex: ISO8601 Local variants).
97
	DefaultTimeLocation = time.UTC
98
)
99

100
// ParseDateTime parses a string that represents an ISO8601 time or a unix epoch
101
func ParseDateTime(data string) (DateTime, error) {
102
	if data == "" {
103
		return NewDateTime(), nil
104
	}
105
	var lastError error
106
	for _, layout := range DateTimeFormats {
107
		dd, err := time.ParseInLocation(layout, data, DefaultTimeLocation)
108
		if err != nil {
109
			lastError = err
110
			continue
111
		}
112
		return DateTime(dd), nil
113
	}
114
	return DateTime{}, lastError
115
}
116

117
// DateTime is a time but it serializes to ISO8601 format with millis
118
// It knows how to read 3 different variations of a RFC3339 date time.
119
// Most APIs we encounter want either millisecond or second precision times.
120
// This just tries to make it worry-free.
121
//
122
// swagger:strfmt date-time
123
type DateTime time.Time
124

125
// NewDateTime is a representation of zero value for DateTime type
126
func NewDateTime() DateTime {
127
	return DateTime(time.Unix(0, 0).UTC())
128
}
129

130
// String converts this time to a string
131
func (t DateTime) String() string {
132
	return NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat)
133
}
134

135
// IsZero returns whether the date time is a zero value
136
func (t *DateTime) IsZero() bool {
137
	if t == nil {
138
		return true
139
	}
140
	return time.Time(*t).IsZero()
141
}
142

143
// IsUnixZerom returns whether the date time is equivalent to time.Unix(0, 0).UTC().
144
func (t *DateTime) IsUnixZero() bool {
145
	if t == nil {
146
		return true
147
	}
148
	return time.Time(*t).Equal(UnixZero)
149
}
150

151
// MarshalText implements the text marshaller interface
152
func (t DateTime) MarshalText() ([]byte, error) {
153
	return []byte(t.String()), nil
154
}
155

156
// UnmarshalText implements the text unmarshaller interface
157
func (t *DateTime) UnmarshalText(text []byte) error {
158
	tt, err := ParseDateTime(string(text))
159
	if err != nil {
160
		return err
161
	}
162
	*t = tt
163
	return nil
164
}
165

166
// Scan scans a DateTime value from database driver type.
167
func (t *DateTime) Scan(raw interface{}) error {
168
	// TODO: case int64: and case float64: ?
169
	switch v := raw.(type) {
170
	case []byte:
171
		return t.UnmarshalText(v)
172
	case string:
173
		return t.UnmarshalText([]byte(v))
174
	case time.Time:
175
		*t = DateTime(v)
176
	case nil:
177
		*t = DateTime{}
178
	default:
179
		return fmt.Errorf("cannot sql.Scan() strfmt.DateTime from: %#v", v)
180
	}
181

182
	return nil
183
}
184

185
// Value converts DateTime to a primitive value ready to written to a database.
186
func (t DateTime) Value() (driver.Value, error) {
187
	return driver.Value(t.String()), nil
188
}
189

190
// MarshalJSON returns the DateTime as JSON
191
func (t DateTime) MarshalJSON() ([]byte, error) {
192
	return json.Marshal(NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat))
193
}
194

195
// UnmarshalJSON sets the DateTime from JSON
196
func (t *DateTime) UnmarshalJSON(data []byte) error {
197
	if string(data) == jsonNull {
198
		return nil
199
	}
200

201
	var tstr string
202
	if err := json.Unmarshal(data, &tstr); err != nil {
203
		return err
204
	}
205
	tt, err := ParseDateTime(tstr)
206
	if err != nil {
207
		return err
208
	}
209
	*t = tt
210
	return nil
211
}
212

213
// MarshalBSON renders the DateTime as a BSON document
214
func (t DateTime) MarshalBSON() ([]byte, error) {
215
	return bson.Marshal(bson.M{"data": t})
216
}
217

218
// UnmarshalBSON reads the DateTime from a BSON document
219
func (t *DateTime) UnmarshalBSON(data []byte) error {
220
	var obj struct {
221
		Data DateTime
222
	}
223

224
	if err := bson.Unmarshal(data, &obj); err != nil {
225
		return err
226
	}
227

228
	*t = obj.Data
229

230
	return nil
231
}
232

233
// MarshalBSONValue is an interface implemented by types that can marshal themselves
234
// into a BSON document represented as bytes. The bytes returned must be a valid
235
// BSON document if the error is nil.
236
// Marshals a DateTime as a bsontype.DateTime, an int64 representing
237
// milliseconds since epoch.
238
func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) {
239
	// UnixNano cannot be used directly, the result of calling UnixNano on the zero
240
	// Time is undefined. Thats why we use time.Nanosecond() instead.
241

242
	tNorm := NormalizeTimeForMarshal(time.Time(t))
243
	i64 := tNorm.Unix()*1000 + int64(tNorm.Nanosecond())/1e6
244

245
	buf := make([]byte, 8)
246
	binary.LittleEndian.PutUint64(buf, uint64(i64))
247

248
	return bsontype.DateTime, buf, nil
249
}
250

251
// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
252
// BSON value representation of themselves. The BSON bytes and type can be
253
// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
254
// wishes to retain the data after returning.
255
func (t *DateTime) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error {
256
	if tpe == bsontype.Null {
257
		*t = DateTime{}
258
		return nil
259
	}
260

261
	if len(data) != 8 {
262
		return errors.New("bson date field length not exactly 8 bytes")
263
	}
264

265
	i64 := int64(binary.LittleEndian.Uint64(data))
266
	// TODO: Use bsonprim.DateTime.Time() method
267
	*t = DateTime(time.Unix(i64/1000, i64%1000*1000000))
268

269
	return nil
270
}
271

272
// DeepCopyInto copies the receiver and writes its value into out.
273
func (t *DateTime) DeepCopyInto(out *DateTime) {
274
	*out = *t
275
}
276

277
// DeepCopy copies the receiver into a new DateTime.
278
func (t *DateTime) DeepCopy() *DateTime {
279
	if t == nil {
280
		return nil
281
	}
282
	out := new(DateTime)
283
	t.DeepCopyInto(out)
284
	return out
285
}
286

287
// GobEncode implements the gob.GobEncoder interface.
288
func (t DateTime) GobEncode() ([]byte, error) {
289
	return t.MarshalBinary()
290
}
291

292
// GobDecode implements the gob.GobDecoder interface.
293
func (t *DateTime) GobDecode(data []byte) error {
294
	return t.UnmarshalBinary(data)
295
}
296

297
// MarshalBinary implements the encoding.BinaryMarshaler interface.
298
func (t DateTime) MarshalBinary() ([]byte, error) {
299
	return NormalizeTimeForMarshal(time.Time(t)).MarshalBinary()
300
}
301

302
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
303
func (t *DateTime) UnmarshalBinary(data []byte) error {
304
	var original time.Time
305

306
	err := original.UnmarshalBinary(data)
307
	if err != nil {
308
		return err
309
	}
310

311
	*t = DateTime(original)
312

313
	return nil
314
}
315

316
// Equal checks if two DateTime instances are equal using time.Time's Equal method
317
func (t DateTime) Equal(t2 DateTime) bool {
318
	return time.Time(t).Equal(time.Time(t2))
319
}
320

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.