add utils to pkg
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
var AsiaShanghai *time.Location
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
AsiaShanghai, err = time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
AsiaShanghai = time.FixedZone("CST", 8*3600)
|
||||
}
|
||||
}
|
||||
|
||||
// CustomTime 自定义时间类型
|
||||
type CustomTime struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// Now 获取当前时间
|
||||
func Now() CustomTime {
|
||||
return CustomTime{time.Now().In(AsiaShanghai)}
|
||||
}
|
||||
|
||||
// Format 返回 yyyy-mm-dd H:i:s 格式字符串
|
||||
|
||||
func (ct CustomTime) Format(layouts ...string) string {
|
||||
if ct.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
layout := time.DateTime // 默认格式:2006-01-02 15:04:05
|
||||
|
||||
if len(layouts) > 0 && layouts[0] != "" {
|
||||
layout = layouts[0]
|
||||
}
|
||||
|
||||
return ct.Time.Format(layout)
|
||||
}
|
||||
|
||||
// String 实现 Stringer 接口
|
||||
// func (ct CustomTime) String() string {
|
||||
// return ct.Format()
|
||||
// }
|
||||
|
||||
func (ct CustomTime) String() string {
|
||||
if ct.Time.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return ct.Time.Format(time.DateTime)
|
||||
}
|
||||
|
||||
// MarshalJSON 实现 JSON 序列化
|
||||
func (ct CustomTime) MarshalJSON() ([]byte, error) {
|
||||
if ct.IsZero() {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
return []byte(`"` + ct.Format() + `"`), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON 实现 JSON 反序列化
|
||||
func (ct *CustomTime) UnmarshalJSON(data []byte) error {
|
||||
str := string(data)
|
||||
if str == "null" || str == `""` {
|
||||
ct.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 去除引号
|
||||
str = strings.Trim(str, `"`)
|
||||
|
||||
// 尝试解析多种格式
|
||||
formats := []string{
|
||||
"2006-01-02",
|
||||
"2006-01-02 15:04:05",
|
||||
"2006-01-02T15:04:05Z07:00",
|
||||
time.RFC3339,
|
||||
time.RFC3339Nano,
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, layout := range formats {
|
||||
ct.Time, err = time.Parse(layout, str)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid time format: %s", str)
|
||||
}
|
||||
|
||||
// Value 实现 driver.Valuer 接口 (数据库写入)
|
||||
func (ct CustomTime) Value() (driver.Value, error) {
|
||||
if ct.IsZero() {
|
||||
return nil, nil
|
||||
}
|
||||
return ct.Time, nil
|
||||
}
|
||||
|
||||
// Scan 实现 sql.Scanner 接口 (数据库读取)
|
||||
func (ct *CustomTime) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ct.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case time.Time:
|
||||
ct.Time = v
|
||||
return nil
|
||||
case []byte:
|
||||
return ct.UnmarshalJSON(v)
|
||||
case string:
|
||||
return ct.UnmarshalJSON([]byte(v))
|
||||
default:
|
||||
return fmt.Errorf("unsupported type: %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
// GormDataType 定义 GORM 数据库类型
|
||||
func (CustomTime) GormDataType() string {
|
||||
return "datetime"
|
||||
}
|
||||
|
||||
// GormDBDataType 定义 GORM 数据库类型 (v2 版本)
|
||||
func (CustomTime) GormDBDataType(db *gorm.DB, field *schema.Field) string {
|
||||
switch db.Dialector.Name() {
|
||||
case "mysql", "sqlite":
|
||||
return "datetime"
|
||||
case "postgres":
|
||||
return "timestamp"
|
||||
default:
|
||||
return "datetime"
|
||||
}
|
||||
}
|
||||
|
||||
func ParseTime(s string) (time.Time, error) {
|
||||
formats := []string{
|
||||
"2006-01-02",
|
||||
"2006-01-02 15:04:05",
|
||||
}
|
||||
|
||||
var t time.Time
|
||||
var err error
|
||||
|
||||
for _, layout := range formats {
|
||||
t, err = time.ParseInLocation(layout, s, time.Local)
|
||||
if err == nil {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
|
||||
return time.Time{}, fmt.Errorf("invalid time format: %s", s)
|
||||
}
|
||||
|
||||
func dayBoundary(s string, h, m, sec int) (CustomTime, error) {
|
||||
t, err := ParseTime(s)
|
||||
if err != nil {
|
||||
return CustomTime{}, err
|
||||
}
|
||||
|
||||
return CustomTime{
|
||||
Time: time.Date(t.Year(), t.Month(), t.Day(), h, m, sec, 0, t.Location()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TimeStart(day int, timeStr string) string {
|
||||
// 2. 格式化开始时间:前一天 23:59:59
|
||||
startTime, err := time.Parse(time.DateOnly, timeStr)
|
||||
if err == nil {
|
||||
startTime = startTime.Add(time.Duration(-24*day) * time.Hour) // 减N天
|
||||
startResult := startTime.Format(time.DateOnly)
|
||||
return startResult + " 23:59:59"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func TimeEnd(day int, timeStr string) string {
|
||||
endTime, err := time.Parse(time.DateOnly, timeStr)
|
||||
if err == nil {
|
||||
endTime = endTime.Add(time.Duration(+24*day) * time.Hour) // 加一天
|
||||
endResult := endTime.Format(time.DateTime)
|
||||
return endResult
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func TimeToUnix(timeStr string, layout string) (int64, error) {
|
||||
t, err := time.ParseInLocation(layout, timeStr, time.FixedZone("CST", 8*3600))
|
||||
if err != nil {
|
||||
Logger.Error(err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 转 11 位时间戳(秒)
|
||||
return t.Unix(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user