title: Custom time.Time type back into datastore
body: <p>I've been working with various examples of custom time formats that come from a JSON POST to our Go API. I've got an overridden function of the UnmarshalJSON all seemingly working fine. However, when I go to save the struct into the datastore it is not being recognized as a time.Time value therefore not being set/saved. The 'toString' function is printing out the correct time I'd like to see in the datastore but can't figure out how to convert it or cast it to time.Time on datastore save. This is a simple logging API feature we're building out. See code below. </p>
  
  <p>I guess like the UnmarshalJSON that converts an arbitrary string to time.Time then to 'Timestamp' (in this case) is there then a Datastore equivalent for putting it back to time.Time before saving?</p>
  
  <p>Thank you for any help/guidance. I did have it such that a 'DateString' was a string value set via JSON when unmarshaling the 'AppLog' struck then I converted that to the 'Date' time.Time, but would like to be a little more 'slick' and utilized the UnmarshalJSON if possible.</p>
  
  <pre><code>package logger
  
  import (
      "encoding/json"
      "errors"
      "fmt"
      "io"
      "io/ioutil"
      "log"
      "net/http"
      "time"
  
      "golang.org/x/net/context"
  
      "google.golang.org/appengine"
      "google.golang.org/appengine/datastore"
  
      "github.com/gorilla/mux"
  )
  
  func init() {
      router := mux.NewRouter()
  
      router.HandleFunc("/applogger", DoLog).Methods("POST")
  
      http.Handle("/applogger/", router)
  }
  
  // DoLog --
  func DoLog(rw http.ResponseWriter, request *http.Request) {
      var applog AppLog
  
      body, err := ioutil.ReadAll(io.LimitReader(request.Body, 1048576))
  
      if err != nil {
          panic(err)
      }
  
      if err := request.Body.Close(); err != nil {
          panic(err)
      }
  
      if err := json.Unmarshal(body, &amp;applog); err != nil {
          panic(err)
      }
  
      applog.IP = request.RemoteAddr
  
      log.Print("my timestamp", applog.Date)
  
      ctx := appengine.NewContext(request)
      applog.Save(ctx)
  
      fmt.Fprint(rw, "applogger - success")
  }
  
  // AppLog struct
  type AppLog struct {
      Application string    `json:"application" datastore:"application"`
      Platform    string    `json:"platform" datastore:"platform,noindex"`
      Date        Timestamp `json:"date" datastore:"date"`
      Data        string    `json:"data" datastore:"data,noindex"`
      IP          string    `json:"-" datastore:"ip,noindex"`
  }
  
  // Save --
  func (al *AppLog) Save(ctx context.Context) *datastore.Key {
  
      key := datastore.NewKey(ctx, "AppLog", "", 0, nil)
  
      if _, err := datastore.Put(ctx, key, al); err != nil {
          return nil
      }
  
      return key
  }
  
  // Timestamp -- Generic Timestamp entity to handle different generic date formats
  type Timestamp time.Time
  
  const TimestampDateLayout1 = "2006-01-02 15:04:05 +0000"
  
  func (t *Timestamp) UnmarshalJSON(b []byte) error {
      ts, err := time.Parse(TimestampDateLayout1, string(b[1:len(b)-1]))
      if err == nil {
          log.Print("ts ", ts)
          *t = Timestamp(ts)
          log.Print("t ", t)
          return nil
      }
  
      *t = Timestamp(time.Now())
      return nil
  }
  
  func (t Timestamp) String() string {
      return time.Time(t).String()
  }
  </code></pre>