mirror of
https://github.com/cowardmrx/dateparse_tag.git
synced 2025-01-18 10:53:53 +08:00
242 lines
5.0 KiB
Go
242 lines
5.0 KiB
Go
package dateparse_tag
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
const (
|
|
DefaultFormatLayout = "2006-01-02 15:04:05"
|
|
DefaultTagName = "dateFormat"
|
|
DefaultTagValue = "default"
|
|
)
|
|
|
|
type dateParseTag struct {
|
|
TagName string // Define the tag you want , default tag is `dateFormat`
|
|
DefaultTagValue string // define the tag default value you want , default tag value `default`
|
|
DefaultFormatLayout string // date format default layout
|
|
EmptyValue string // Return when the value is null
|
|
}
|
|
|
|
type Options func(dp *dateParseTag)
|
|
|
|
func WithTagName(tagName string) Options {
|
|
return func(dp *dateParseTag) {
|
|
|
|
if tagName == "" || len(tagName) <= 0 {
|
|
dp.TagName = "dateFormat"
|
|
} else {
|
|
dp.TagName = tagName
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func WithDefaultTagValue(tagVal string) Options {
|
|
return func(dp *dateParseTag) {
|
|
if tagVal == "" || len(tagVal) <= 0 {
|
|
dp.DefaultTagValue = "default"
|
|
} else {
|
|
dp.DefaultTagValue = tagVal
|
|
}
|
|
}
|
|
}
|
|
|
|
func WithDefaultFormat(defaultFormatLayout string) Options {
|
|
return func(dp *dateParseTag) {
|
|
if defaultFormatLayout == "" || len(defaultFormatLayout) <= 0 {
|
|
dp.DefaultFormatLayout = DefaultFormatLayout
|
|
} else {
|
|
dp.DefaultFormatLayout = defaultFormatLayout
|
|
}
|
|
}
|
|
}
|
|
|
|
func WithEmptyValue(emptyValue string) Options {
|
|
return func(dp *dateParseTag) {
|
|
dp.EmptyValue = emptyValue
|
|
}
|
|
}
|
|
|
|
type DateParseTag interface {
|
|
//Deprecated
|
|
Parse(in, out interface{})
|
|
// Format 格式化
|
|
Format(in interface{})
|
|
|
|
// ForRange for range data
|
|
forRange(field reflect.StructField, val reflect.Value)
|
|
}
|
|
|
|
func NewDateParseTag(opts ...Options) DateParseTag {
|
|
dp := new(dateParseTag)
|
|
|
|
for _, v := range opts {
|
|
v(dp)
|
|
}
|
|
|
|
dp = dp.check()
|
|
|
|
return dp
|
|
}
|
|
|
|
func (dp *dateParseTag) check() *dateParseTag {
|
|
if dp.TagName == "" || len(dp.TagName) <= 0 {
|
|
dp.TagName = DefaultTagName
|
|
}
|
|
|
|
if dp.DefaultFormatLayout == "" || len(dp.DefaultFormatLayout) <= 0 {
|
|
dp.DefaultFormatLayout = DefaultFormatLayout
|
|
}
|
|
|
|
if dp.EmptyValue == "" || len(dp.EmptyValue) <= 0 {
|
|
dp.EmptyValue = ""
|
|
}
|
|
|
|
return dp
|
|
}
|
|
|
|
// @method Parse Deprecated
|
|
// @description: parse time
|
|
// @receiver dp
|
|
// @param in interface{}
|
|
// @param out interface{}
|
|
func (dp *dateParseTag) Parse(in, out interface{}) {
|
|
tType := reflect.TypeOf(in).Elem()
|
|
|
|
tValue := reflect.ValueOf(in).Elem()
|
|
|
|
for i := 0; i < tType.NumField(); i++ {
|
|
field := tType.Field(i)
|
|
|
|
tag, ok := field.Tag.Lookup(dp.TagName)
|
|
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
fieldVal := tValue.FieldByName(field.Name)
|
|
|
|
if fieldVal.String() == "" || len(fieldVal.String()) <= 0 {
|
|
|
|
// 校验是否为该空值返回是否为时间类型格式
|
|
tFormat, err := validateDateFormat(dp.EmptyValue)
|
|
|
|
// 如果不是时间类型格式那么直接返回emptyValue的值 反之按照layout格式化返回
|
|
if err != nil {
|
|
fieldVal.SetString(dp.EmptyValue)
|
|
} else {
|
|
fieldVal.SetString(parseTime(dp.dateFormatLayout(tFormat), dp.EmptyValue))
|
|
}
|
|
|
|
} else {
|
|
|
|
fieldVal.SetString(parseTime(dp.dateFormatLayout(tag), fieldVal.String()))
|
|
}
|
|
|
|
}
|
|
|
|
out = in
|
|
return
|
|
}
|
|
|
|
// @method Format
|
|
// @description: parse time
|
|
// @receiver dp
|
|
// @param in interface{}
|
|
func (dp *dateParseTag) Format(in interface{}) {
|
|
rt := reflect.TypeOf(in).Elem()
|
|
|
|
rv := reflect.ValueOf(in).Elem()
|
|
|
|
for i := 0; i < rt.NumField(); i++ {
|
|
field := rt.Field(i)
|
|
|
|
val := rv.Field(i)
|
|
|
|
dp.forRange(field, val)
|
|
}
|
|
}
|
|
|
|
// @method forRange
|
|
// @description: for range data
|
|
// @param field reflect.StructField
|
|
// @param val reflect.Value
|
|
func (dp *dateParseTag) forRange(field reflect.StructField, val reflect.Value) {
|
|
switch field.Type.Kind() {
|
|
case reflect.Ptr:
|
|
rt := field.Type.Elem()
|
|
rv := val.Elem()
|
|
for k := 0; k < rt.NumField(); k++ {
|
|
|
|
field := rt.Field(k)
|
|
|
|
val := rv.Field(k)
|
|
dp.forRange(field, val)
|
|
|
|
}
|
|
case reflect.Struct:
|
|
rt := field.Type
|
|
rv := val
|
|
for k := 0; k < rt.NumField(); k++ {
|
|
|
|
field := rt.Field(k)
|
|
|
|
val := rv.Field(k)
|
|
dp.forRange(field, val)
|
|
|
|
}
|
|
case reflect.String:
|
|
tag, ok := field.Tag.Lookup(dp.TagName)
|
|
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
fieldVal := val
|
|
|
|
if fieldVal.String() == "" || len(fieldVal.String()) <= 0 {
|
|
|
|
// 校验是否为该空值返回是否为时间类型格式
|
|
tFormat, err := validateDateFormat(dp.EmptyValue)
|
|
|
|
// 如果不是时间类型格式那么直接返回emptyValue的值 反之按照layout格式化返回
|
|
if err != nil {
|
|
fieldVal.SetString(dp.EmptyValue)
|
|
} else {
|
|
fieldVal.SetString(parseTime(dp.dateFormatLayout(tFormat), dp.EmptyValue))
|
|
}
|
|
|
|
} else {
|
|
|
|
fieldVal.SetString(parseTime(dp.dateFormatLayout(tag), fieldVal.String()))
|
|
}
|
|
}
|
|
}
|
|
|
|
// @method dateFormatLayout
|
|
// @description: get date format layout
|
|
// @receiver dp
|
|
// @param tag string
|
|
// @return string
|
|
func (dp *dateParseTag) dateFormatLayout(tag string) string {
|
|
if tag == dp.DefaultTagValue {
|
|
tag = dp.DefaultFormatLayout
|
|
} else {
|
|
|
|
if tag == DefaultTagValue {
|
|
tag = DefaultFormatLayout
|
|
}
|
|
|
|
tFormat, err := validateDateFormat(tag)
|
|
|
|
if err != nil {
|
|
panic(fmt.Sprintf("tag value can't parse: %v", tag))
|
|
}
|
|
|
|
tag = tFormat
|
|
}
|
|
|
|
return tag
|
|
}
|