refactor(types):将日期时间类型提取到公共的类型定义包中。
This commit is contained in:
parent
c22e7e7dc0
commit
85f4d04a7f
|
@ -6,6 +6,7 @@ import (
|
||||||
"electricity_bill_calc/repository"
|
"electricity_bill_calc/repository"
|
||||||
"electricity_bill_calc/response"
|
"electricity_bill_calc/response"
|
||||||
"electricity_bill_calc/service"
|
"electricity_bill_calc/service"
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
@ -26,12 +27,12 @@ func searchCharges(c *fiber.Ctx) error {
|
||||||
result := response.NewResult(c)
|
result := response.NewResult(c)
|
||||||
keyword := c.Query("keyword", "")
|
keyword := c.Query("keyword", "")
|
||||||
page := c.QueryInt("page", 1)
|
page := c.QueryInt("page", 1)
|
||||||
beginTime, err := model.ParseDate(c.Query("begin"))
|
beginTime, err := types.ParseDate(c.Query("begin"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chargeLog.Error("无法解析查询起始时间。", zap.Error(err))
|
chargeLog.Error("无法解析查询起始时间。", zap.Error(err))
|
||||||
return result.Error(http.StatusInternalServerError, err.Error())
|
return result.Error(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
endTime, err := model.ParseDate(c.Query("end"))
|
endTime, err := types.ParseDate(c.Query("end"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chargeLog.Error("无法解析查询结束时间。", zap.Error(err))
|
chargeLog.Error("无法解析查询结束时间。", zap.Error(err))
|
||||||
return result.Error(http.StatusInternalServerError, err.Error())
|
return result.Error(http.StatusInternalServerError, err.Error())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"electricity_bill_calc/model"
|
"electricity_bill_calc/types"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
@ -137,6 +137,17 @@ func DecimalField(key string, val *decimal.Decimal) zap.Field {
|
||||||
return zap.String(key, val.String())
|
return zap.String(key, val.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func DateField(key string, val *model.Date) zap.Field {
|
func NullDecimalField(key string, val *decimal.NullDecimal) zap.Field {
|
||||||
return zap.String(key, val.Format("2006-01-02"))
|
if val.Valid {
|
||||||
|
return DecimalField(key, &val.Decimal)
|
||||||
|
}
|
||||||
|
return zap.String(key, "null")
|
||||||
|
}
|
||||||
|
|
||||||
|
func DateField(key string, val *types.Date) zap.Field {
|
||||||
|
return val.Log(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DateTimeField(key string, val *types.DateTime) zap.Field {
|
||||||
|
return val.Log(key)
|
||||||
}
|
}
|
||||||
|
|
3
main.go
3
main.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"electricity_bill_calc/repository"
|
"electricity_bill_calc/repository"
|
||||||
"electricity_bill_calc/router"
|
"electricity_bill_calc/router"
|
||||||
"electricity_bill_calc/service"
|
"electricity_bill_calc/service"
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ func intializeSingularity() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
singularityId := "000"
|
singularityId := "000"
|
||||||
singularityExpires, err := model.ParseDate("2099-12-31")
|
singularityExpires, err := types.ParseDate("2099-12-31")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Error("奇点用户账号过期时间解析失败。", zap.Error(err))
|
l.Error("奇点用户账号过期时间解析失败。", zap.Error(err))
|
||||||
return fmt.Errorf("奇点用户账号过期时间解析失败: %w", err)
|
return fmt.Errorf("奇点用户账号过期时间解析失败: %w", err)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
@ -13,7 +14,7 @@ type UserChargeDetail struct {
|
||||||
Fee *decimal.Decimal `json:"fee"`
|
Fee *decimal.Decimal `json:"fee"`
|
||||||
Discount *decimal.Decimal `json:"discount"`
|
Discount *decimal.Decimal `json:"discount"`
|
||||||
Amount *decimal.Decimal `json:"amount"`
|
Amount *decimal.Decimal `json:"amount"`
|
||||||
ChargeTo Date `json:"charge_to"`
|
ChargeTo types.Date `json:"charge_to"`
|
||||||
Settled bool `json:"settled"`
|
Settled bool `json:"settled"`
|
||||||
SettledAt *time.Time `json:"settled_at"`
|
SettledAt *time.Time `json:"settled_at"`
|
||||||
Cancelled bool `json:"cancelled"`
|
Cancelled bool `json:"cancelled"`
|
||||||
|
@ -26,5 +27,5 @@ type ChargeRecordCreationForm struct {
|
||||||
Fee *decimal.Decimal `json:"fee"`
|
Fee *decimal.Decimal `json:"fee"`
|
||||||
Discount *decimal.Decimal `json:"discount"`
|
Discount *decimal.Decimal `json:"discount"`
|
||||||
Amount *decimal.Decimal `json:"amount"`
|
Amount *decimal.Decimal `json:"amount"`
|
||||||
ChargeTo Date `json:"chargeTo"`
|
ChargeTo types.Date `json:"chargeTo"`
|
||||||
}
|
}
|
||||||
|
|
100
model/types.go
100
model/types.go
|
@ -1,100 +0,0 @@
|
||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
et "electricity_bill_calc/tools/time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Date struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDate(t time.Time) Date {
|
|
||||||
t = t.In(et.Loc)
|
|
||||||
return Date{
|
|
||||||
Time: time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, et.Loc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SpecificDate(year int, month time.Month, date int) Date {
|
|
||||||
return NewDate(et.Time(year, month, date, 0, 0, 0, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEmptyDate() Date {
|
|
||||||
return Date{
|
|
||||||
Time: time.Time{}.In(et.Loc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseDate(t string) (Date, error) {
|
|
||||||
d, err := time.ParseInLocation("2006-01-02", t, et.Loc)
|
|
||||||
if err != nil {
|
|
||||||
return NewEmptyDate(), fmt.Errorf("unable to parse given time, %w", err)
|
|
||||||
}
|
|
||||||
return Date{
|
|
||||||
Time: d,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Date) IsEmpty() bool {
|
|
||||||
return d.Time.IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Date) Format(fmt string) string {
|
|
||||||
return d.Time.Format(fmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Date) ToString() string {
|
|
||||||
return d.Time.Format("2006-01-02")
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ driver.Valuer = (*Date)(nil)
|
|
||||||
|
|
||||||
func (d Date) Value() (driver.Value, error) {
|
|
||||||
return d.In(et.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) {
|
|
||||||
switch src := src.(type) {
|
|
||||||
case time.Time:
|
|
||||||
*d = NewDate(src)
|
|
||||||
return nil
|
|
||||||
case string:
|
|
||||||
d.Time, err = time.ParseInLocation("2006-01-02", src, et.Loc)
|
|
||||||
return err
|
|
||||||
case []byte:
|
|
||||||
d.Time, err = time.ParseInLocation("2006-01-02", string(src), et.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 json.Marshal(d.Time.Format("2006-01-02"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ json.Unmarshaler = (*Date)(nil)
|
|
||||||
|
|
||||||
func (d *Date) UnmarshalJSON(raw []byte) error {
|
|
||||||
var s string
|
|
||||||
err := json.Unmarshal(raw, &s)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to unmarshal value, %w", err)
|
|
||||||
}
|
|
||||||
d.Time, err = time.ParseInLocation("2006-01-02", s, et.Loc)
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
@ -20,7 +21,7 @@ type ManagementAccountCreationForm struct {
|
||||||
Phone *string `json:"phone"`
|
Phone *string `json:"phone"`
|
||||||
Type int16 `json:"type"`
|
Type int16 `json:"type"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Expires Date `json:"expires"`
|
Expires types.Date `json:"expires"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m ManagementAccountCreationForm) IntoUser() *User {
|
func (m ManagementAccountCreationForm) IntoUser() *User {
|
||||||
|
@ -83,7 +84,7 @@ type UserDetail struct {
|
||||||
Contact *string `json:"contact"`
|
Contact *string `json:"contact"`
|
||||||
Phone *string `json:"phone"`
|
Phone *string `json:"phone"`
|
||||||
UnitServiceFee decimal.Decimal `db:"unit_service_fee" json:"unitServiceFee"`
|
UnitServiceFee decimal.Decimal `db:"unit_service_fee" json:"unitServiceFee"`
|
||||||
ServiceExpiration Date `json:"serviceExpiration"`
|
ServiceExpiration types.Date `json:"serviceExpiration"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
CreatedBy *string `json:"createdBy"`
|
CreatedBy *string `json:"createdBy"`
|
||||||
LastModifiedAt time.Time `json:"lastModifiedAt"`
|
LastModifiedAt time.Time `json:"lastModifiedAt"`
|
||||||
|
@ -105,7 +106,7 @@ type UserWithDetail struct {
|
||||||
Contact *string `json:"contact"`
|
Contact *string `json:"contact"`
|
||||||
Phone *string `json:"phone"`
|
Phone *string `json:"phone"`
|
||||||
UnitServiceFee decimal.Decimal `db:"unit_service_fee" json:"unitServiceFee"`
|
UnitServiceFee decimal.Decimal `db:"unit_service_fee" json:"unitServiceFee"`
|
||||||
ServiceExpiration Date `json:"serviceExpiration"`
|
ServiceExpiration types.Date `json:"serviceExpiration"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
CreatedBy *string `json:"createdBy"`
|
CreatedBy *string `json:"createdBy"`
|
||||||
LastModifiedAt time.Time `json:"lastModifiedAt"`
|
LastModifiedAt time.Time `json:"lastModifiedAt"`
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"electricity_bill_calc/model"
|
"electricity_bill_calc/model"
|
||||||
"electricity_bill_calc/tools"
|
"electricity_bill_calc/tools"
|
||||||
"electricity_bill_calc/tools/time"
|
"electricity_bill_calc/tools/time"
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"fmt"
|
"fmt"
|
||||||
st "time"
|
st "time"
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ func (cr _ChargeRepository) FindCharges(page uint, beginTime, endTime *st.Time,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在用户充值记录中创建一条新的记录
|
// 在用户充值记录中创建一条新的记录
|
||||||
func (cr _ChargeRepository) CreateChargeRecord(tx pgx.Tx, ctx context.Context, uid string, fee, discount, amount *decimal.Decimal, chargeTo model.Date) (bool, error) {
|
func (cr _ChargeRepository) CreateChargeRecord(tx pgx.Tx, ctx context.Context, uid string, fee, discount, amount *decimal.Decimal, chargeTo types.Date) (bool, error) {
|
||||||
createQuery, createArgs, _ := cr.ds.
|
createQuery, createArgs, _ := cr.ds.
|
||||||
Insert(goqu.T("user_charge")).
|
Insert(goqu.T("user_charge")).
|
||||||
Cols("user_id", "fee", "discount", "amount", "charge_to", "created_at").
|
Cols("user_id", "fee", "discount", "amount", "charge_to", "created_at").
|
||||||
|
@ -142,7 +143,7 @@ func (cr _ChargeRepository) CancelCharge(tx pgx.Tx, ctx context.Context, uid str
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检索用户最近有效的服务期限
|
// 检索用户最近有效的服务期限
|
||||||
func (cr _ChargeRepository) LatestValidChargeTo(tx pgx.Tx, ctx context.Context, uid string) (*model.Date, error) {
|
func (cr _ChargeRepository) LatestValidChargeTo(tx pgx.Tx, ctx context.Context, uid string) (*types.Date, error) {
|
||||||
searchSql, searchArgs, _ := cr.ds.
|
searchSql, searchArgs, _ := cr.ds.
|
||||||
From(goqu.T("user_charge")).
|
From(goqu.T("user_charge")).
|
||||||
Select("charge_to").
|
Select("charge_to").
|
||||||
|
@ -154,7 +155,7 @@ func (cr _ChargeRepository) LatestValidChargeTo(tx pgx.Tx, ctx context.Context,
|
||||||
).
|
).
|
||||||
Prepared(true).ToSQL()
|
Prepared(true).ToSQL()
|
||||||
|
|
||||||
var chargeTo []*model.Date
|
var chargeTo []*types.Date
|
||||||
if err := pgxscan.Select(ctx, tx, &chargeTo, searchSql, searchArgs...); err != nil {
|
if err := pgxscan.Select(ctx, tx, &chargeTo, searchSql, searchArgs...); err != nil {
|
||||||
cr.log.Error("检索用户有效服务期限列表失败。", zap.Error(err))
|
cr.log.Error("检索用户有效服务期限列表失败。", zap.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -162,6 +163,6 @@ func (cr _ChargeRepository) LatestValidChargeTo(tx pgx.Tx, ctx context.Context,
|
||||||
if len(chargeTo) == 0 {
|
if len(chargeTo) == 0 {
|
||||||
return nil, fmt.Errorf("无法找到用户最近的有效服务期限。")
|
return nil, fmt.Errorf("无法找到用户最近的有效服务期限。")
|
||||||
}
|
}
|
||||||
lastCharge := lo.MaxBy(chargeTo, func(a, b *model.Date) bool { return a.Time.After(b.Time) })
|
lastCharge := lo.MaxBy(chargeTo, func(a, b *types.Date) bool { return a.Time.After(b.Time) })
|
||||||
return lastCharge, nil
|
return lastCharge, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"electricity_bill_calc/cache"
|
"electricity_bill_calc/cache"
|
||||||
"electricity_bill_calc/global"
|
"electricity_bill_calc/global"
|
||||||
"electricity_bill_calc/logger"
|
"electricity_bill_calc/logger"
|
||||||
"electricity_bill_calc/model"
|
|
||||||
"electricity_bill_calc/repository"
|
"electricity_bill_calc/repository"
|
||||||
|
"electricity_bill_calc/types"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
@ -21,7 +21,7 @@ var ChargeService = &_ChargeService{
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建一条新的用户充值记录,同时更新用户的服务期限
|
// 创建一条新的用户充值记录,同时更新用户的服务期限
|
||||||
func (cs _ChargeService) RecordUserCharge(uid string, fee, discount, amount *decimal.Decimal, chargeTo model.Date, extendExpriationIgnoringSettle bool) (bool, error) {
|
func (cs _ChargeService) RecordUserCharge(uid string, fee, discount, amount *decimal.Decimal, chargeTo types.Date, extendExpriationIgnoringSettle bool) (bool, error) {
|
||||||
cs.log.Info(
|
cs.log.Info(
|
||||||
"创建一条新的用户充值记录。",
|
"创建一条新的用户充值记录。",
|
||||||
zap.String("uid", uid),
|
zap.String("uid", uid),
|
||||||
|
|
123
types/date.go
Normal file
123
types/date.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Date struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDate(year int, month time.Month, day int) Date {
|
||||||
|
return Date{
|
||||||
|
Time: time.Date(year, month, day, 0, 0, 0, 0, loc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmptyDate() Date {
|
||||||
|
return Date{
|
||||||
|
Time: time.Time{}.In(loc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NowDate() Date {
|
||||||
|
return Now().Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDate(t string) (Date, error) {
|
||||||
|
d, err := time.ParseInLocation("2006-01-02", t, loc)
|
||||||
|
if err != nil {
|
||||||
|
return NewEmptyDate(), fmt.Errorf("无法解析给定的日期, %w", err)
|
||||||
|
}
|
||||||
|
return Date{
|
||||||
|
Time: d,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Valuer = (*Date)(nil)
|
||||||
|
|
||||||
|
func (dt Date) Value() (driver.Value, error) {
|
||||||
|
return dt.In(loc).Format("2006-01-02"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ sql.Scanner = (*Date)(nil)
|
||||||
|
|
||||||
|
func (d *Date) Scan(src interface{}) (err error) {
|
||||||
|
switch src := src.(type) {
|
||||||
|
case time.Time:
|
||||||
|
d.Time = src
|
||||||
|
case string:
|
||||||
|
t, err := time.ParseInLocation("2006-01-02", src, loc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*d = Date{Time: t}
|
||||||
|
case []byte:
|
||||||
|
d.Time, err = time.ParseInLocation("2006-01-02", string(src), loc)
|
||||||
|
return err
|
||||||
|
case nil:
|
||||||
|
d = nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("该数据类型不支持解析到日期: %T", src)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Marshaler = (*Date)(nil)
|
||||||
|
|
||||||
|
func (d Date) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(d.Format("2006-01-02"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Unmarshaler = (*Date)(nil)
|
||||||
|
|
||||||
|
func (d *Date) UnmarshalJSON(data []byte) error {
|
||||||
|
var str string
|
||||||
|
if err := json.Unmarshal(data, &str); err != nil {
|
||||||
|
return fmt.Errorf("不能解析指定的日期时间值: %w", err)
|
||||||
|
}
|
||||||
|
t, err := time.ParseInLocation("2006-01-02", str, loc)
|
||||||
|
d.Time = t
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) DifferenceInMonth(d2 *Date) int {
|
||||||
|
var differYear, differMonth int
|
||||||
|
differYear = d.Year() - d2.Year()
|
||||||
|
differMonth = int(d.Month() - d2.Month())
|
||||||
|
return differYear*12 + differMonth
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) IsNextMonth(d2 *Date) bool {
|
||||||
|
return d.DifferenceInMonth(d2) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) ToBeginningOfDate() DateTime {
|
||||||
|
return FromTime(time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, loc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) ToEndingOfDate() DateTime {
|
||||||
|
return FromTime(time.Date(d.Year(), d.Month(), d.Day(), 23, 59, 59, 999999, loc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) IsEmpty() bool {
|
||||||
|
return d.Time.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) ToString() string {
|
||||||
|
return d.Time.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) ToDateTime() DateTime {
|
||||||
|
return FromTime(d.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Date) Log(fieldName string) zap.Field {
|
||||||
|
return zap.String(fieldName, d.ToString())
|
||||||
|
}
|
118
types/datetime.go
Normal file
118
types/datetime.go
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var loc *time.Location = time.FixedZone("+0800", 8*60*60)
|
||||||
|
|
||||||
|
type DateTime struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func Now() DateTime {
|
||||||
|
return DateTime{
|
||||||
|
Time: time.Now().In(loc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Timestamp() int64 {
|
||||||
|
startline := time.Date(2022, 2, 22, 22, 22, 22, 0, loc).Unix()
|
||||||
|
return Now().Unix() - startline
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromTime(t time.Time) DateTime {
|
||||||
|
return DateTime{
|
||||||
|
Time: t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Valuer = (*DateTime)(nil)
|
||||||
|
|
||||||
|
func (dt DateTime) Value() (driver.Value, error) {
|
||||||
|
return dt.In(loc).Format("2006-01-02 15:04:05"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ sql.Scanner = (*DateTime)(nil)
|
||||||
|
|
||||||
|
func (dt *DateTime) Scan(src interface{}) (err error) {
|
||||||
|
switch src := src.(type) {
|
||||||
|
case time.Time:
|
||||||
|
dt.Time = src
|
||||||
|
case string:
|
||||||
|
t, err := time.ParseInLocation("2006-01-02 15:04:05", src, loc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*dt = DateTime{Time: t}
|
||||||
|
case []byte:
|
||||||
|
dt.Time, err = time.ParseInLocation("2006-01-02 15:04:05", string(src), loc)
|
||||||
|
return err
|
||||||
|
case nil:
|
||||||
|
dt = nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("该数据类型不支持解析到日期时间: %T", src)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Marshaler = (*DateTime)(nil)
|
||||||
|
|
||||||
|
func (dt DateTime) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(dt.Format("2006-01-02 15:04:05"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Unmarshaler = (*DateTime)(nil)
|
||||||
|
|
||||||
|
func (dt *DateTime) UnmarshalJSON(data []byte) error {
|
||||||
|
var str string
|
||||||
|
if err := json.Unmarshal(data, &str); err != nil {
|
||||||
|
return fmt.Errorf("不能解析指定的日期时间值: %w", err)
|
||||||
|
}
|
||||||
|
t, err := time.ParseInLocation("2006-01-02 15:04:05", str, loc)
|
||||||
|
dt.Time = t
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) DifferenceInMonth(d DateTime) int {
|
||||||
|
var differYear, differMonth int
|
||||||
|
differYear = dt.Year() - d.Year()
|
||||||
|
differMonth = int(dt.Month() - d.Month())
|
||||||
|
return differYear*12 + differMonth
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) IsNextMonth(target DateTime) bool {
|
||||||
|
return dt.DifferenceInMonth(target) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt *DateTime) ToBeginningOfDate() {
|
||||||
|
dt.Time = time.Date(dt.Year(), dt.Month(), dt.Day(), 0, 0, 0, 0, loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt *DateTime) ToEndingOfDate() {
|
||||||
|
dt.Time = time.Date(dt.Year(), dt.Month(), dt.Day(), 23, 59, 59, 999999, loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) Date() Date {
|
||||||
|
return Date{
|
||||||
|
Time: time.Date(dt.Year(), dt.Month(), dt.Day(), 0, 0, 0, 0, loc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) IsEmpty() bool {
|
||||||
|
return dt.Time.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) ToString() string {
|
||||||
|
return dt.Time.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dt DateTime) Log(fieldName string) zap.Field {
|
||||||
|
return zap.String(fieldName, dt.ToString())
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package vo
|
||||||
import (
|
import (
|
||||||
"electricity_bill_calc/model"
|
"electricity_bill_calc/model"
|
||||||
"electricity_bill_calc/tools/time"
|
"electricity_bill_calc/tools/time"
|
||||||
|
"electricity_bill_calc/types"
|
||||||
st "time"
|
st "time"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
@ -29,6 +30,7 @@ func (u MGTAndOPSAccountCreationForm) IntoUser() *model.User {
|
||||||
|
|
||||||
func (u MGTAndOPSAccountCreationForm) IntoUserDetail() *model.UserDetail {
|
func (u MGTAndOPSAccountCreationForm) IntoUserDetail() *model.UserDetail {
|
||||||
return &model.UserDetail{
|
return &model.UserDetail{
|
||||||
|
Id: "",
|
||||||
Name: &u.Name,
|
Name: &u.Name,
|
||||||
Abbr: nil,
|
Abbr: nil,
|
||||||
Region: nil,
|
Region: nil,
|
||||||
|
@ -36,7 +38,7 @@ func (u MGTAndOPSAccountCreationForm) IntoUserDetail() *model.UserDetail {
|
||||||
Contact: u.Contact,
|
Contact: u.Contact,
|
||||||
Phone: u.Phone,
|
Phone: u.Phone,
|
||||||
UnitServiceFee: decimal.Zero,
|
UnitServiceFee: decimal.Zero,
|
||||||
ServiceExpiration: model.SpecificDate(2099, st.December, 31),
|
ServiceExpiration: types.NewDate(2099, st.December, 31),
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
CreatedBy: nil,
|
CreatedBy: nil,
|
||||||
LastModifiedAt: time.Now(),
|
LastModifiedAt: time.Now(),
|
||||||
|
@ -80,7 +82,7 @@ func (u EnterpriseAccountCreationForm) IntoUserDetail() (*model.UserDetail, erro
|
||||||
Contact: u.Contact,
|
Contact: u.Contact,
|
||||||
Phone: u.Phone,
|
Phone: u.Phone,
|
||||||
UnitServiceFee: unitServiceFee,
|
UnitServiceFee: unitServiceFee,
|
||||||
ServiceExpiration: model.SpecificDate(2000, st.January, 1),
|
ServiceExpiration: types.NewDate(2000, st.January, 1),
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
CreatedBy: nil,
|
CreatedBy: nil,
|
||||||
LastModifiedAt: time.Now(),
|
LastModifiedAt: time.Now(),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user