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  }