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 datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/base64" | 8 "encoding/base64" |
9 "errors" | 9 "errors" |
10 "fmt" | 10 "fmt" |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 err := error(nil) | 263 err := error(nil) |
264 if checkValid && !x.Valid() { | 264 if checkValid && !x.Valid() { |
265 err = errors.New("invalid GeoPoint value") | 265 err = errors.New("invalid GeoPoint value") |
266 } | 266 } |
267 return PTGeoPoint, err | 267 return PTGeoPoint, err |
268 default: | 268 default: |
269 return PTUnknown, fmt.Errorf("gae: Property has bad type %T", v) | 269 return PTUnknown, fmt.Errorf("gae: Property has bad type %T", v) |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 // timeLocationsEqual tests if two time.Location are equal. | 273 // timeLocationIsUTC tests if two time.Location are equal. |
274 // | 274 // |
275 // This is tricky using the standard time API, as time is implicitly normalized | 275 // This is tricky using the standard time API, as time is implicitly normalized |
276 // to UTC and all equality checks are performed relative to that normalized | 276 // to UTC and all equality checks are performed relative to that normalized |
277 // time. To compensate, we instantiate two new time.Time using the respective | 277 // time. To compensate, we instantiate two new time.Time using the respective |
278 // Locations. | 278 // Locations. |
279 func timeLocationIsUTC(l *time.Location) bool { | 279 func timeLocationIsUTC(l *time.Location) bool { |
280 return time.Date(1970, 1, 1, 0, 0, 0, 0, l).Equal(utcTestTime) | 280 return time.Date(1970, 1, 1, 0, 0, 0, 0, l).Equal(utcTestTime) |
281 } | 281 } |
282 | 282 |
283 // UpconvertUnderlyingType takes an object o, and attempts to convert it to | 283 // UpconvertUnderlyingType takes an object o, and attempts to convert it to |
(...skipping 17 matching lines...) Expand all Loading... |
301 } | 301 } |
302 case reflect.Float32, reflect.Float64: | 302 case reflect.Float32, reflect.Float64: |
303 o = v.Float() | 303 o = v.Float() |
304 case reflect.Slice: | 304 case reflect.Slice: |
305 if t.Elem().Kind() == reflect.Uint8 { | 305 if t.Elem().Kind() == reflect.Uint8 { |
306 o = v.Bytes() | 306 o = v.Bytes() |
307 } | 307 } |
308 case reflect.Struct: | 308 case reflect.Struct: |
309 if t == typeOfTime { | 309 if t == typeOfTime { |
310 // time in a Property can only hold microseconds | 310 // time in a Property can only hold microseconds |
311 » » » o = v.Interface().(time.Time).Round(time.Microsecond) | 311 » » » tim := v.Interface().(time.Time) |
| 312 » » » if !tim.IsZero() { |
| 313 » » » » o = v.Interface().(time.Time).Round(time.Microse
cond) |
| 314 » » » } |
312 } | 315 } |
313 } | 316 } |
314 return o | 317 return o |
315 } | 318 } |
316 | 319 |
317 // Value returns the current value held by this property. It's guaranteed to | 320 // Value returns the current value held by this property. It's guaranteed to |
318 // be a valid value type (i.e. `p.SetValue(p.Value(), true)` will never return | 321 // be a valid value type (i.e. `p.SetValue(p.Value(), true)` will never return |
319 // an error). | 322 // an error). |
320 func (p *Property) Value() interface{} { return p.value } | 323 func (p *Property) Value() interface{} { return p.value } |
321 | 324 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 case to == p.propType: | 405 case to == p.propType: |
403 return p.value, nil | 406 return p.value, nil |
404 | 407 |
405 case to == PTInt && p.propType == PTTime: | 408 case to == PTInt && p.propType == PTTime: |
406 t := p.value.(time.Time) | 409 t := p.value.(time.Time) |
407 v := uint64(t.Unix())*1e6 + uint64(t.Nanosecond()/1e3) | 410 v := uint64(t.Unix())*1e6 + uint64(t.Nanosecond()/1e3) |
408 return int64(v), nil | 411 return int64(v), nil |
409 | 412 |
410 case to == PTTime && p.propType == PTInt: | 413 case to == PTTime && p.propType == PTInt: |
411 v := p.value.(int64) | 414 v := p.value.(int64) |
412 » » return time.Unix(int64(v/1e6), int64((v%1e6)*1e3)).UTC(), nil | 415 » » t := time.Unix(int64(v/1e6), int64((v%1e6)*1e3)) |
| 416 » » if t.IsZero() { |
| 417 » » » return time.Time{}, nil |
| 418 » » } |
| 419 » » return t.UTC(), nil |
413 | 420 |
414 case to == PTString && p.propType == PTBytes: | 421 case to == PTString && p.propType == PTBytes: |
415 return string(p.value.([]byte)), nil | 422 return string(p.value.([]byte)), nil |
416 | 423 |
417 case to == PTString && p.propType == PTBlobKey: | 424 case to == PTString && p.propType == PTBlobKey: |
418 return string(p.value.(blobstore.Key)), nil | 425 return string(p.value.(blobstore.Key)), nil |
419 | 426 |
420 case to == PTBytes && p.propType == PTString: | 427 case to == PTBytes && p.propType == PTString: |
421 return []byte(p.value.(string)), nil | 428 return []byte(p.value.(string)), nil |
422 | 429 |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 dflt = UpconvertUnderlyingType(dflt) | 788 dflt = UpconvertUnderlyingType(dflt) |
782 cur, err := gm(key) | 789 cur, err := gm(key) |
783 if err != nil { | 790 if err != nil { |
784 return dflt | 791 return dflt |
785 } | 792 } |
786 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { | 793 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { |
787 return dflt | 794 return dflt |
788 } | 795 } |
789 return cur | 796 return cur |
790 } | 797 } |
OLD | NEW |