168 lines
4.4 KiB
Go
168 lines
4.4 KiB
Go
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)
|
|
datetimeLayouts = []string{
|
|
"2006-01-02 15:04:05", "2006-1-2 15:04:05", "2006/01/02 15:04:05", "06-1-2 15:04:05", "06-01-02 15:04:05", "01/02/06 15:04:05", "1/2/06 15:04:05", "2006年01月02日 15:04:05", "06年1月2日 15:04:05",
|
|
"2006-01-02 15:04", "2006-1-2 15:04", "2006/01/02 15:04", "06-1-2 15:04", "06-01-02 15:04", "01/02/06 15:04", "1/2/06 15:04", "2006年01月02日 15:04", "06年1月2日 15:04",
|
|
}
|
|
)
|
|
|
|
// 封装日期时间类型。
|
|
type DateTime struct {
|
|
time.Time
|
|
}
|
|
|
|
// 获取当前的日期时间。
|
|
func Now() DateTime {
|
|
return DateTime{
|
|
Time: time.Now().In(loc),
|
|
}
|
|
}
|
|
|
|
// 创建一个空白的日期时间类型实例。
|
|
func NewEmptyDateTime() DateTime {
|
|
return DateTime{
|
|
Time: time.Time{}.In(loc),
|
|
}
|
|
}
|
|
|
|
// 获取一个自`2022-02-22 22:22:22.0`以来的秒数时间戳。
|
|
func Timestamp() int64 {
|
|
startline := time.Date(2022, 2, 22, 22, 22, 22, 0, loc).Unix()
|
|
return Now().Unix() - startline
|
|
}
|
|
|
|
// 从指定的字符串中解析日期时间。如果无法解析则返回错误。
|
|
func ParseDateTime(t string) (DateTime, error) {
|
|
if len(t) == 0 {
|
|
return NewEmptyDateTime(), fmt.Errorf("不能解析空白的日期时间。")
|
|
}
|
|
for _, layout := range datetimeLayouts {
|
|
fmt.Printf("Parse: %s, Try layout: %s\n", t, layout)
|
|
d, err := time.ParseInLocation(layout, t, loc)
|
|
if err == nil {
|
|
return DateTime{
|
|
Time: d,
|
|
}, nil
|
|
}
|
|
}
|
|
return NewEmptyDateTime(), fmt.Errorf("无法解析给定的日期时间,格式不正确。")
|
|
}
|
|
|
|
// 封装一个标准库中的时间类型。
|
|
func FromTime(t time.Time) DateTime {
|
|
return DateTime{
|
|
Time: t,
|
|
}
|
|
}
|
|
|
|
// 解析一个Unix时间戳。
|
|
func FromUnixMicro(sec int64) DateTime {
|
|
return DateTime{
|
|
Time: time.UnixMicro(sec).In(loc),
|
|
}
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
// 以`YYYY-MM-DD HH:mm:ss`格式输出日期时间。
|
|
func (dt DateTime) ToString() string {
|
|
return dt.Time.Format("2006-01-02 15:04:05")
|
|
}
|
|
|
|
// 在Zap日志中以给定`fieldName`为字段名输出日期时间。
|
|
func (dt DateTime) Log(fieldName string) zap.Field {
|
|
return zap.String(fieldName, dt.ToString())
|
|
}
|