package model import ( "encoding/json" "fmt" "github.com/mailru/easyjson/jlexer" "github.com/mailru/easyjson/jwriter" "io" "log" "regexp" "strconv" "time" ) type DateTime int64 var datetimeLayout = "2006-01-02T15:04:05Z0700" func NewDateTime(milli int64) *DateTime { date := DateTime(milli) return &date } func NewDateTimeIn(seconds int64) DateTime { return DateTime( time.Unix(seconds, 0). In(time.UTC). UnixMilli()) } func NewDateTimeFrom(t time.Time) *DateTime { date := DateTime(t.In(time.UTC).UnixMilli()) return &date } func Now() DateTime { return DateTime(time.Now().In(time.UTC).UnixMilli()) } func (d DateTime) String() string { return time.UnixMilli(int64(d)).In(time.UTC).Format(datetimeLayout) } func (d DateTime) MarshalJSON() ([]byte, error) { return json.Marshal(time.UnixMilli(int64(d)).In(time.UTC)) } func (d DateTime) MarshalGQL(w io.Writer) { _, err := w.Write([]byte(strconv.Quote(d.String()))) if err != nil { log.Default().Println(err) } } func (d *DateTime) UnixMilli() int64 { return int64(*d) } func (d *DateTime) UnmarshalGQL(v interface{}) error { switch v := v.(type) { case float64: *d = DateTime(v) case int: *d = DateTime(v) case time.Time: *d = DateTime(v.In(time.UTC).UnixMilli()) case string: if regexp.MustCompile(`^\d{13}$`).MatchString(v) { if i, err := strconv.Atoi(v); err == nil { *d = DateTime(i) return nil } } t, err := time.Parse(datetimeLayout, v) if err != nil { return err } *d = DateTime(t.In(time.UTC).UnixMilli()) case DateTime: *d = v } return nil } func (d *DateTime) Scan(src any) error { if t, ok := src.(int64); ok { *d = NewDateTimeIn(t) return nil } return fmt.Errorf("cannot scan %T into DateTime", src) } func (d *DateTime) MarshalEasyJSON(w *jwriter.Writer) { w.RawString(fmt.Sprintf("%d", d.UnixMilli())) } func (d *DateTime) UnmarshalEasyJSON(l *jlexer.Lexer) { if l.IsNull() { l.Skip() *d = DateTime(0) } else { *d = DateTime(l.Int64()) } }