Golang-自定义时间。时间类型返回到数据存储区

I've been working with various examples of custom time formats that come from a JSON POST to our Golang 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.

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?

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.

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, &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()
}

time.Time has an UnmarshalJSON method already. It will unmarshal from a JSON string that is RFC3339 formatted to a time.Time.

If you need it in a different string format after that, you can just use

(t *time.Time).Format(layout string)

with whatever formatting desired.

If there are lots of struct and you just implement custom marshal und unmarshal functions, that's a lot of work to do so. You can use another lib instead,such as a json-iterator extension jsontime:

import "github.com/liamylian/jsontime"

var json = jsontime.ConfigWithCustomTimeFormat

type Book struct {
    Id        int           `json:"id"`
    UpdatedAt *time.Time    `json:"updated_at" time_format:"sql_date" time_utc:"true"`
    CreatedAt time.Time     `json:"created_at" time_format:"sql_datetime" time_location:"UTC"`
}