diff --git a/model/park.go b/model/park.go index 23a488d..c681cc8 100644 --- a/model/park.go +++ b/model/park.go @@ -62,9 +62,9 @@ type ParkSimplified struct { } type ParkPeriodStatistics struct { - Id string `bun:"park__id,notnull" json:"id"` - Name string `bun:"park__name,notnull" json:"name"` - Period *time.Time `bun:"type:date" json:"period" time_format:"simple_date" time_location:"shanghai"` + Id string `bun:"park__id,notnull" json:"id"` + Name string `bun:"park__name,notnull" json:"name"` + Period *Date `bun:"type:date" json:"period"` } func FromPark(park Park) ParkSimplified { diff --git a/model/report.go b/model/report.go index 79191e1..fc1a417 100644 --- a/model/report.go +++ b/model/report.go @@ -69,7 +69,7 @@ type ReportIndexSimplified struct { bun.BaseModel `bun:"table:report,alias:r"` Id string `bun:",pk,notnull" json:"id"` ParkId string `bun:",notnull" json:"parkId"` - Period time.Time `bun:"type:date,notnull" json:"period" time_format:"simple_date" time_location:"shanghai"` + Period Date `bun:"type:date,notnull" json:"period"` StepState Steps `bun:"type:jsonb,notnull" json:"stepState"` Published bool `bun:",notnull,default:false" json:"published"` PublishedAt *time.Time `bun:"type:timestampz" json:"publishedAt" time_format:"simple_datetime" time_location:"shanghai"` diff --git a/model/types.go b/model/types.go new file mode 100644 index 0000000..0acd31c --- /dev/null +++ b/model/types.go @@ -0,0 +1,78 @@ +package model + +import ( + "database/sql" + "database/sql/driver" + "encoding/json" + "fmt" + "time" +) + +type Date struct { + time.Time +} + +func NewDate(t time.Time) Date { + loc, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + panic(err) + } + t = t.In(loc) + return Date{ + Time: time.Date(0, 1, 1, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc), + } +} + +var _ driver.Valuer = (*Date)(nil) + +func (d Date) Value() (driver.Value, error) { + loc, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + panic(err) + } + return d.In(loc).Format("2006-01-02"), nil +} + +var _ sql.Scanner = (*Date)(nil) + +// Scan scans the time parsing it if necessary using timeFormat. +func (d *Date) Scan(src interface{}) (err error) { + loc, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + panic(err) + } + switch src := src.(type) { + case time.Time: + *d = NewDate(src) + return nil + case string: + d.Time, err = time.ParseInLocation("2006-01-02", src, loc) + return err + case []byte: + d.Time, err = time.ParseInLocation("2006-01-02", string(src), loc) + return err + case nil: + d.Time = time.Time{} + return nil + default: + return fmt.Errorf("unsupported data type: %T", src) + } +} + +var _ json.Marshaler = (*Date)(nil) + +func (d Date) MarshalJSON() ([]byte, error) { + return []byte(d.Time.Format("2006-01-02")), nil +} + +var _ json.Unmarshaler = (*Date)(nil) + +func (d *Date) UnmarshalJSON(raw []byte) error { + loc, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + return fmt.Errorf("unable to load time zone, %w", err) + } + s := string(raw) + d.Time, err = time.ParseInLocation("2006-01-02", s, loc) + return err +} diff --git a/model/user_charges.go b/model/user_charges.go index 70a89fd..e2902c5 100644 --- a/model/user_charges.go +++ b/model/user_charges.go @@ -16,7 +16,7 @@ type UserCharge struct { Fee decimal.NullDecimal `json:"fee"` Discount decimal.NullDecimal `json:"discount"` Amount decimal.NullDecimal `json:"amount"` - ChargeTo time.Time `bun:"type:date,notnull" json:"chargeTo" time_format:"simple_date" time_location:"shanghai"` + ChargeTo Date `bun:"type:date,notnull" json:"chargeTo"` Settled bool `bun:",notnull,default:false" json:"settled"` SettledAt *time.Time `bun:"type:timestamptz" json:"settledAt" time_format:"simple_datetime" time_location:"shanghai"` Cancelled bool `bun:",notnull,default:false" json:"cancelled"` diff --git a/model/user_detail.go b/model/user_detail.go index 76969b4..8465885 100644 --- a/model/user_detail.go +++ b/model/user_detail.go @@ -21,7 +21,7 @@ type UserDetail struct { Contact *string `json:"contact"` Phone *string `json:"phone"` UnitServiceFee decimal.Decimal `bun:",notnull" json:"unitServiceFee"` - ServiceExpiration time.Time `bun:"type:date,notnull" json:"serviceExpiration" time_format:"simple_date" time_location:"shanghai"` + ServiceExpiration Date `bun:"type:date,notnull" json:"serviceExpiration"` } type JoinedUserDetail struct {