2023-11-30 11:37:02 +08:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql/driver"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// 默认时间格式
|
|
|
|
const dateTimeFormat = "2006-01-02 15:04:05.000"
|
|
|
|
|
|
|
|
// 可能包含的时间格式
|
|
|
|
var formatMap = map[string]string{
|
|
|
|
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
|
|
|
|
"yyyy-mm-dd hh:mm": "2006-01-02 15:04",
|
|
|
|
"yyyy-mm-dd hh": "2006-01-02 15:04",
|
|
|
|
"yyyy-mm-dd": "2006-01-02",
|
|
|
|
"yyyy-mm": "2006-01",
|
|
|
|
"mm-dd": "01-02",
|
|
|
|
"dd-mm-yy hh:mm:ss": "02-01-06 15:04:05",
|
|
|
|
"yyyy/mm/dd hh:mm:ss": "2006/01/02 15:04:05",
|
|
|
|
"yyyy/mm/dd hh:mm": "2006/01/02 15:04",
|
|
|
|
"yyyy/mm/dd hh": "2006/01/02 15",
|
|
|
|
"yyyy/mm/dd": "2006/01/02",
|
|
|
|
"yyyy/mm": "2006/01",
|
|
|
|
"mm/dd": "01/02",
|
|
|
|
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
|
|
|
|
"yyyy": "2006",
|
|
|
|
"mm": "01",
|
|
|
|
"hh:mm:ss": "15:04:05",
|
|
|
|
"mm:ss": "04:05",
|
|
|
|
}
|
|
|
|
|
|
|
|
// DateTime 自定义时间类型
|
|
|
|
type DateTime time.Time
|
|
|
|
|
|
|
|
// Scan implements the Scanner interface.
|
|
|
|
func (dt *DateTime) Scan(value interface{}) error {
|
|
|
|
// mysql 内部日期的格式可能是 2006-01-02 15:04:05 +0800 CST 格式,所以检出的时候还需要进行一次格式化
|
|
|
|
tTime, _ := time.Parse("2006-01-02 15:04:05 +0800 CST", value.(time.Time).String())
|
|
|
|
*dt = DateTime(tTime)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value implements the driver Valuer interface.
|
|
|
|
func (dt DateTime) Value() (dv driver.Value, err error) {
|
|
|
|
// 0001-01-01 00:00:00 属于空值,遇到空值解析成 null 即可
|
|
|
|
if dt.String() == "0001-01-01 00:00:00.000" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
dv, err = []byte(dt.Format(dateTimeFormat)), nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 用于 fmt.Println 和后续验证场景
|
|
|
|
func (dt DateTime) String() string {
|
2023-11-30 17:31:50 +08:00
|
|
|
return dt.Format("2006-01-02 15:04:05")
|
2023-11-30 11:37:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Format 格式化
|
|
|
|
func (dt *DateTime) Format(fm string) string {
|
|
|
|
return time.Time(*dt).Format(fm)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AutoParse 假装是个自动解析时间的函数
|
|
|
|
func (dt DateTime) AutoParse(timeStr string) (t time.Time, err error) {
|
|
|
|
// 循环匹配预设的时间格式
|
|
|
|
for _, v := range formatMap {
|
|
|
|
// 尝试解析,没报错就是解析成功了
|
|
|
|
t, err = time.ParseInLocation(v, timeStr, time.Local)
|
|
|
|
if err == nil {
|
|
|
|
// 错误为空,表示匹配上了
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// After 时间比较
|
|
|
|
func (dt *DateTime) After(now time.Time) bool {
|
|
|
|
return time.Time(*dt).After(now)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Before 时间比较
|
|
|
|
func (dt *DateTime) Before(now time.Time) bool {
|
|
|
|
return time.Time(*dt).Before(now)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IBefore 时间比较
|
|
|
|
func (dt *DateTime) IBefore(now DateTime) bool {
|
|
|
|
return dt.Before(time.Time(now))
|
|
|
|
}
|
|
|
|
|
|
|
|
// SubTime 对比
|
|
|
|
func (dt DateTime) SubTime(t time.Time) time.Duration {
|
|
|
|
return dt.ToTime().Sub(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub 对比
|
|
|
|
func (dt DateTime) Sub(t DateTime) time.Duration {
|
|
|
|
return dt.ToTime().Sub(t.ToTime())
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToTime 转换为golang的时间类型
|
|
|
|
func (dt DateTime) ToTime() time.Time {
|
|
|
|
return time.Time(dt)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsNil 是否为空值
|
|
|
|
func (dt DateTime) IsNil() bool {
|
|
|
|
return dt.Format(dateTimeFormat) == "0001-01-01 00:00:00.000"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unix 实现Unix函数
|
|
|
|
func (dt DateTime) Unix() int64 {
|
|
|
|
return dt.ToTime().Unix()
|
|
|
|
}
|
|
|
|
|
|
|
|
// EndOfCentury 获取本世纪最后时间
|
|
|
|
func (dt DateTime) EndOfCentury() DateTime {
|
|
|
|
yearEnd := time.Now().Local().Year()/100*100 + 99
|
|
|
|
return DateTime(time.Date(yearEnd, 12, 31, 23, 59, 59, 999999999, time.Local))
|
|
|
|
}
|
|
|
|
|
|
|
|
// ======== 序列化 JSON ========
|
|
|
|
|
|
|
|
// MarshalJSON 时间到字符串
|
|
|
|
func (dt DateTime) MarshalJSON() ([]byte, error) {
|
|
|
|
// 过滤掉空数据
|
|
|
|
if dt.IsNil() {
|
|
|
|
return []byte("\"\""), nil
|
|
|
|
}
|
|
|
|
output := fmt.Sprintf(`"%s"`, dt.Format("2006-01-02 15:04:05"))
|
|
|
|
return []byte(output), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON 字符串到时间
|
|
|
|
func (dt *DateTime) UnmarshalJSON(b []byte) (err error) {
|
|
|
|
if len(b) == 2 {
|
|
|
|
*dt = DateTime{}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// 解析指定的格式
|
|
|
|
var now time.Time
|
|
|
|
if strings.HasPrefix(string(b), "\"") {
|
|
|
|
now, err = dt.AutoParse(string(b)[1 : len(b)-1])
|
|
|
|
} else {
|
|
|
|
now, err = dt.AutoParse(string(b))
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
*dt = DateTime(now)
|
|
|
|
return
|
|
|
|
}
|