OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package serialize | 5 package serialize |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "errors" | 9 "errors" |
10 "fmt" | 10 "fmt" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 | 182 |
183 gp.Lng, _, e = cmpbin.ReadFloat64(buf) | 183 gp.Lng, _, e = cmpbin.ReadFloat64(buf) |
184 panicIf(e) | 184 panicIf(e) |
185 | 185 |
186 if !gp.Valid() { | 186 if !gp.Valid() { |
187 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) | 187 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) |
188 } | 188 } |
189 return | 189 return |
190 } | 190 } |
191 | 191 |
| 192 // TimeToInt converts a time value to a datastore-appropraite integer value. |
| 193 // |
| 194 // This method truncates the time to microseconds and drops the timezone, |
| 195 // because that's the (undocumented) way that the appengine SDK does it. |
| 196 func TimeToInt(t time.Time) int64 { |
| 197 t = t.Round(time.Microsecond) |
| 198 return t.Unix()*1e6 + int64(t.Nanosecond()/1e3) |
| 199 } |
| 200 |
| 201 // IntToTime converts a time integer produced by TimeToInt to a time.Time |
| 202 // instance. |
| 203 func IntToTime(v int64) time.Time { |
| 204 t := time.Unix(v/1e6, (v%1e6)*1e3) |
| 205 if t.IsZero() { |
| 206 return time.Time{} |
| 207 } |
| 208 return t.UTC() |
| 209 } |
| 210 |
192 // WriteTime writes a time.Time in a byte-sortable way. | 211 // WriteTime writes a time.Time in a byte-sortable way. |
193 // | 212 // |
194 // This method truncates the time to microseconds and drops the timezone, | 213 // This method uses TimeToInt to convert the time to an integer value. This |
195 // because that's the (undocumented) way that the appengine SDK does it. | 214 // truncates the time to microseconds and drops the timezone. |
196 func WriteTime(buf Buffer, t time.Time) error { | 215 func WriteTime(buf Buffer, t time.Time) error { |
197 name, off := t.Zone() | 216 name, off := t.Zone() |
198 if name != "UTC" || off != 0 { | 217 if name != "UTC" || off != 0 { |
199 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) | 218 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) |
200 } | 219 } |
201 » _, err := cmpbin.WriteInt(buf, t.Unix()*1e6+int64(t.Nanosecond()/1e3)) | 220 » _, err := cmpbin.WriteInt(buf, TimeToInt(t)) |
202 return err | 221 return err |
203 } | 222 } |
204 | 223 |
205 // ReadTime reads a time.Time from the buffer. | 224 // ReadTime reads a time.Time from the buffer. |
206 func ReadTime(buf Buffer) (time.Time, error) { | 225 func ReadTime(buf Buffer) (time.Time, error) { |
207 v, _, err := cmpbin.ReadInt(buf) | 226 v, _, err := cmpbin.ReadInt(buf) |
208 if err != nil { | 227 if err != nil { |
209 return time.Time{}, err | 228 return time.Time{}, err |
210 } | 229 } |
211 » t := time.Unix(v/1e6, (v%1e6)*1e3) | 230 » return IntToTime(v), nil |
212 » if t.IsZero() { | |
213 » » return time.Time{}, nil | |
214 » } | |
215 » return t.UTC(), nil | |
216 } | 231 } |
217 | 232 |
218 // WriteProperty writes a Property to the buffer. `context` behaves the same | 233 // WriteProperty writes a Property to the buffer. `context` behaves the same |
219 // way that it does for WriteKey, but only has an effect if `p` contains a | 234 // way that it does for WriteKey, but only has an effect if `p` contains a |
220 // Key as its Value. | 235 // Key as its Value. |
221 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { | 236 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { |
222 defer recoverTo(&err) | 237 defer recoverTo(&err) |
223 typb := byte(p.Type()) | 238 typb := byte(p.Type()) |
224 if p.IndexSetting() != ds.NoIndex { | 239 if p.IndexSetting() != ds.NoIndex { |
225 typb |= 0x80 | 240 typb |= 0x80 |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 } | 608 } |
594 } | 609 } |
595 | 610 |
596 func recoverTo(err *error) { | 611 func recoverTo(err *error) { |
597 if r := recover(); r != nil { | 612 if r := recover(); r != nil { |
598 if rerr := r.(parseError); rerr != nil { | 613 if rerr := r.(parseError); rerr != nil { |
599 *err = error(rerr) | 614 *err = error(rerr) |
600 } | 615 } |
601 } | 616 } |
602 } | 617 } |
OLD | NEW |