提交 3b84dccb authored 作者: mooncake9527's avatar mooncake9527

add Date

上级 3c815f98
package xtime
import (
"database/sql/driver"
"fmt"
"strings"
"time"
)
type Date time.Time
func (d *Date) Scan(value interface{}) error {
switch v := value.(type) {
case []byte:
parsed, err := time.Parse("2006-01-02", string(v))
if err != nil {
return err
}
*d = Date(parsed)
case string:
parsed, err := time.Parse("2006-01-02", v)
if err != nil {
return err
}
*d = Date(parsed)
default:
return fmt.Errorf("unsupported type: %T", v)
}
return nil
}
func (d Date) Value() (driver.Value, error) {
return d.Time().Format("2006-01-02"), nil
}
// MarshalJSON 自定义JSON序列化
func (d Date) MarshalJSON() ([]byte, error) {
return []byte(`"` + d.Time().Format("2006-01-02") + `"`), nil
}
// UnmarshalJSON 自定义JSON反序列化
func (d *Date) UnmarshalJSON(data []byte) error {
str := strings.Trim(string(data), `"`)
parsed, err := time.Parse("2006-01-02", str)
if err != nil {
return err
}
*d = Date(parsed)
return nil
}
// MarshalYAML 自定义YAML序列化
func (d Date) MarshalYAML() (interface{}, error) {
return d.Time().Format("2006-01-02"), nil
}
func (d Date) Time() time.Time {
return time.Time(d)
}
// UnmarshalYAML 自定义YAML反序列化
func (d *Date) UnmarshalYAML(value interface{}) error {
str, ok := value.(string)
if !ok {
return fmt.Errorf("date must be a string")
}
parsed, err := time.Parse("2006-01-02", str)
if err != nil {
return err
}
*d = Date(parsed)
return nil
}
// String 返回日期字符串表示
func (d Date) String() string {
return d.Time().Format("2006-01-02")
}
// Today 返回当前日期
func TodayDate() Date {
now := time.Now()
return Date(time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()))
}
// ParseDate 从字符串解析日期
func ParseDate(s string) (Date, error) {
t, err := time.Parse("2006-01-02", s)
if err != nil {
return Date{}, err
}
return Date(t), nil
}
// MustParseDate 从字符串解析日期,如果解析失败会panic
func MustParseDate(s string) Date {
d, err := ParseDate(s)
if err != nil {
panic(err)
}
return d
}
package xtime
import (
"database/sql/driver"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestDate_Scan(t *testing.T) {
tests := []struct {
name string
input interface{}
want Date
wantErr bool
}{
{
name: "valid byte slice",
input: []byte("2023-05-15"),
want: MustParseDate("2023-05-15"),
wantErr: false,
},
{
name: "valid string",
input: "2023-05-15",
want: MustParseDate("2023-05-15"),
wantErr: false,
},
{
name: "invalid type",
input: 123,
want: Date{},
wantErr: true,
},
{
name: "invalid date format",
input: "15-05-2023",
want: Date{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var d Date
err := d.Scan(tt.input)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, d)
}
})
}
}
func TestDate_Value(t *testing.T) {
tests := []struct {
name string
date Date
want driver.Value
wantErr bool
}{
{
name: "valid date",
date: MustParseDate("2023-05-15"),
want: "2023-05-15",
wantErr: false,
},
{
name: "zero date",
date: Date{},
want: "0001-01-01",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.date.Value()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
}
})
}
}
func TestDate_MarshalJSON(t *testing.T) {
tests := []struct {
name string
date Date
want string
wantErr bool
}{
{
name: "valid date",
date: MustParseDate("2023-05-15"),
want: `"2023-05-15"`,
wantErr: false,
},
{
name: "zero date",
date: Date{},
want: `"0001-01-01"`,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.date.MarshalJSON()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, string(got))
}
})
}
}
func TestDate_UnmarshalJSON(t *testing.T) {
tests := []struct {
name string
input string
want Date
wantErr bool
}{
{
name: "valid date",
input: `"2023-05-15"`,
want: MustParseDate("2023-05-15"),
wantErr: false,
},
{
name: "invalid format",
input: `"15-05-2023"`,
want: Date{},
wantErr: true,
},
{
name: "not a string",
input: `123`,
want: Date{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var d Date
err := d.UnmarshalJSON([]byte(tt.input))
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, d)
}
})
}
}
func TestDate_MarshalYAML(t *testing.T) {
tests := []struct {
name string
date Date
want string
wantErr bool
}{
{
name: "valid date",
date: MustParseDate("2023-05-15"),
want: "2023-05-15",
wantErr: false,
},
{
name: "zero date",
date: Date{},
want: "0001-01-01",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.date.MarshalYAML()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
}
})
}
}
func TestDate_UnmarshalYAML(t *testing.T) {
tests := []struct {
name string
input interface{}
want Date
wantErr bool
}{
{
name: "valid date string",
input: "2023-05-15",
want: MustParseDate("2023-05-15"),
wantErr: false,
},
{
name: "invalid format",
input: "15-05-2023",
want: Date{},
wantErr: true,
},
{
name: "not a string",
input: 123,
want: Date{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var d Date
err := d.UnmarshalYAML(tt.input)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, d)
}
})
}
}
func TestDate_Time(t *testing.T) {
date := MustParseDate("2023-05-15")
expected := time.Date(2023, time.May, 15, 0, 0, 0, 0, time.UTC)
assert.Equal(t, expected, date.Time().UTC())
}
func TestDate_String(t *testing.T) {
date := MustParseDate("2023-05-15")
assert.Equal(t, "2023-05-15", date.String())
}
func TestToday(t *testing.T) {
now := time.Now()
expected := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
assert.Equal(t, expected, TodayDate().Time())
}
func TestParseDate(t *testing.T) {
tests := []struct {
name string
input string
want Date
wantErr bool
}{
{
name: "valid date",
input: "2023-05-15",
want: MustParseDate("2023-05-15"),
wantErr: false,
},
{
name: "invalid format",
input: "15-05-2023",
want: Date{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseDate(tt.input)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
}
})
}
}
func TestMustParseDate(t *testing.T) {
assert.NotPanics(t, func() {
_ = MustParseDate("2023-05-15")
})
assert.Panics(t, func() {
_ = MustParseDate("invalid-date")
})
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论