go.mercari.io/datastore@v1.8.2/testsuite/property_translater.go (about) 1 package testsuite 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "testing" 8 "time" 9 10 "go.mercari.io/datastore" 11 ) 12 13 var _ datastore.PropertyTranslator = (*userID)(nil) 14 var _ datastore.PropertyTranslator = unixTime(time.Time{}) 15 var _ json.Marshaler = unixTime(time.Time{}) 16 var _ json.Unmarshaler = (*unixTime)(&time.Time{}) 17 18 type contextClient struct{} 19 20 type userID int64 21 type unixTime time.Time 22 23 func (id userID) ToPropertyValue(ctx context.Context) (interface{}, error) { 24 client := ctx.Value(contextClient{}).(datastore.Client) 25 key := client.IDKey("User", int64(id), nil) 26 return key, nil 27 } 28 29 func (id userID) FromPropertyValue(ctx context.Context, p datastore.Property) (dst interface{}, err error) { 30 key, ok := p.Value.(datastore.Key) 31 if !ok { 32 return nil, datastore.ErrInvalidEntityType 33 } 34 return userID(key.ID()), nil 35 } 36 37 func (t unixTime) ToPropertyValue(ctx context.Context) (interface{}, error) { 38 return time.Time(t), nil 39 } 40 41 func (t unixTime) FromPropertyValue(ctx context.Context, p datastore.Property) (dst interface{}, err error) { 42 origT, ok := p.Value.(time.Time) 43 if !ok { 44 return nil, datastore.ErrInvalidEntityType 45 } 46 return unixTime(origT), nil 47 } 48 49 func (t unixTime) MarshalJSON() ([]byte, error) { 50 unix := time.Time(t).UnixNano() 51 jsonNumber := json.Number(fmt.Sprintf("%d", unix)) 52 return json.Marshal(jsonNumber) 53 } 54 55 func (t *unixTime) UnmarshalJSON(b []byte) error { 56 var jsonNumber json.Number 57 err := json.Unmarshal(b, &jsonNumber) 58 if err != nil { 59 return err 60 } 61 unix, err := jsonNumber.Int64() 62 if err != nil { 63 return err 64 } 65 66 l, err := time.LoadLocation("Asia/Tokyo") 67 if err != nil { 68 return err 69 } 70 71 v := time.Unix(0, unix).In(l) 72 *t = unixTime(v) 73 return nil 74 } 75 76 func propertyTranslaterPutAndGet(ctx context.Context, t *testing.T, client datastore.Client) { 77 defer func() { 78 err := client.Close() 79 if err != nil { 80 t.Fatal(err) 81 } 82 }() 83 ctx = context.WithValue(ctx, contextClient{}, client) 84 client.SetContext(ctx) 85 86 type User struct { 87 ID int64 `datastore:"-"` 88 Name string 89 } 90 91 type Data struct { 92 UserID userID 93 CreatedAt unixTime 94 } 95 96 userKey, err := client.Put(ctx, client.IncompleteKey("User", nil), &User{Name: "vvakame"}) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 l, err := time.LoadLocation("Europe/Berlin") // not UTC, not PST, not Asia/Tokyo(developer's local timezone) 102 if err != nil { 103 t.Fatal(err) 104 } 105 now := unixTime(time.Date(2017, 11, 2, 10, 11, 22, 33, l)) 106 107 key, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{ 108 UserID: userID(userKey.ID()), 109 CreatedAt: now, 110 }) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 obj := &Data{} 116 err = client.Get(ctx, key, obj) 117 if err != nil { 118 t.Fatal(err) 119 } 120 121 if v := obj.UserID; int64(v) != userKey.ID() { 122 t.Errorf("unexpected: %v", v) 123 } 124 expectedNow := time.Time(now).Truncate(time.Microsecond).In(time.Local) 125 if v := obj.CreatedAt; !time.Time(v).Equal(expectedNow) { 126 t.Errorf("unexpected: %v", v) 127 } 128 }