blob: cdd9a6a7a0cc7ab6c65ff90e7963c7b4c59a86e6 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package v1
18
19import (
20 "encoding/json"
21 "time"
22
23 "github.com/google/gofuzz"
24)
25
26const RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
27
28// MicroTime is version of Time with microsecond level precision.
29//
30// +protobuf.options.marshal=false
31// +protobuf.as=Timestamp
32// +protobuf.options.(gogoproto.goproto_stringer)=false
33type MicroTime struct {
34 time.Time `protobuf:"-"`
35}
36
37// DeepCopy returns a deep-copy of the MicroTime value. The underlying time.Time
38// type is effectively immutable in the time API, so it is safe to
39// copy-by-assign, despite the presence of (unexported) Pointer fields.
40func (t *MicroTime) DeepCopyInto(out *MicroTime) {
41 *out = *t
42}
43
Zack Williamse940c7a2019-08-21 14:25:39 -070044// NewMicroTime returns a wrapped instance of the provided time
45func NewMicroTime(time time.Time) MicroTime {
46 return MicroTime{time}
47}
48
49// DateMicro returns the MicroTime corresponding to the supplied parameters
50// by wrapping time.Date.
51func DateMicro(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) MicroTime {
52 return MicroTime{time.Date(year, month, day, hour, min, sec, nsec, loc)}
53}
54
55// NowMicro returns the current local time.
56func NowMicro() MicroTime {
57 return MicroTime{time.Now()}
58}
59
60// IsZero returns true if the value is nil or time is zero.
61func (t *MicroTime) IsZero() bool {
62 if t == nil {
63 return true
64 }
65 return t.Time.IsZero()
66}
67
68// Before reports whether the time instant t is before u.
69func (t *MicroTime) Before(u *MicroTime) bool {
David Bainbridge86971522019-09-26 22:09:39 +000070 if t != nil && u != nil {
71 return t.Time.Before(u.Time)
72 }
73 return false
Zack Williamse940c7a2019-08-21 14:25:39 -070074}
75
76// Equal reports whether the time instant t is equal to u.
77func (t *MicroTime) Equal(u *MicroTime) bool {
David Bainbridge86971522019-09-26 22:09:39 +000078 if t == nil && u == nil {
79 return true
80 }
81 if t != nil && u != nil {
82 return t.Time.Equal(u.Time)
83 }
84 return false
Zack Williamse940c7a2019-08-21 14:25:39 -070085}
86
87// BeforeTime reports whether the time instant t is before second-lever precision u.
88func (t *MicroTime) BeforeTime(u *Time) bool {
David Bainbridge86971522019-09-26 22:09:39 +000089 if t != nil && u != nil {
90 return t.Time.Before(u.Time)
91 }
92 return false
Zack Williamse940c7a2019-08-21 14:25:39 -070093}
94
95// EqualTime reports whether the time instant t is equal to second-lever precision u.
96func (t *MicroTime) EqualTime(u *Time) bool {
David Bainbridge86971522019-09-26 22:09:39 +000097 if t == nil && u == nil {
98 return true
99 }
100 if t != nil && u != nil {
101 return t.Time.Equal(u.Time)
102 }
103 return false
Zack Williamse940c7a2019-08-21 14:25:39 -0700104}
105
106// UnixMicro returns the local time corresponding to the given Unix time
107// by wrapping time.Unix.
108func UnixMicro(sec int64, nsec int64) MicroTime {
109 return MicroTime{time.Unix(sec, nsec)}
110}
111
112// UnmarshalJSON implements the json.Unmarshaller interface.
113func (t *MicroTime) UnmarshalJSON(b []byte) error {
114 if len(b) == 4 && string(b) == "null" {
115 t.Time = time.Time{}
116 return nil
117 }
118
119 var str string
120 err := json.Unmarshal(b, &str)
121 if err != nil {
122 return err
123 }
124
125 pt, err := time.Parse(RFC3339Micro, str)
126 if err != nil {
127 return err
128 }
129
130 t.Time = pt.Local()
131 return nil
132}
133
134// UnmarshalQueryParameter converts from a URL query parameter value to an object
135func (t *MicroTime) UnmarshalQueryParameter(str string) error {
136 if len(str) == 0 {
137 t.Time = time.Time{}
138 return nil
139 }
140 // Tolerate requests from older clients that used JSON serialization to build query params
141 if len(str) == 4 && str == "null" {
142 t.Time = time.Time{}
143 return nil
144 }
145
146 pt, err := time.Parse(RFC3339Micro, str)
147 if err != nil {
148 return err
149 }
150
151 t.Time = pt.Local()
152 return nil
153}
154
155// MarshalJSON implements the json.Marshaler interface.
156func (t MicroTime) MarshalJSON() ([]byte, error) {
157 if t.IsZero() {
158 // Encode unset/nil objects as JSON's "null".
159 return []byte("null"), nil
160 }
161
162 return json.Marshal(t.UTC().Format(RFC3339Micro))
163}
164
165// OpenAPISchemaType is used by the kube-openapi generator when constructing
166// the OpenAPI spec of this type.
167//
168// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
169func (_ MicroTime) OpenAPISchemaType() []string { return []string{"string"} }
170
171// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
172// the OpenAPI spec of this type.
173func (_ MicroTime) OpenAPISchemaFormat() string { return "date-time" }
174
175// MarshalQueryParameter converts to a URL query parameter value
176func (t MicroTime) MarshalQueryParameter() (string, error) {
177 if t.IsZero() {
178 // Encode unset/nil objects as an empty string
179 return "", nil
180 }
181
182 return t.UTC().Format(RFC3339Micro), nil
183}
184
185// Fuzz satisfies fuzz.Interface.
186func (t *MicroTime) Fuzz(c fuzz.Continue) {
187 if t == nil {
188 return
189 }
190 // Allow for about 1000 years of randomness. Accurate to a tenth of
191 // micro second. Leave off nanoseconds because JSON doesn't
192 // represent them so they can't round-trip properly.
193 t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 1000*c.Rand.Int63n(1000000))
194}
195
196var _ fuzz.Interface = &MicroTime{}