From 6a9de038b70a4d57b83895159a2693b6ffce067e Mon Sep 17 00:00:00 2001 From: coward Date: Wed, 12 Jan 2022 14:11:27 +0800 Subject: [PATCH] :tada: --- .idea/.gitignore | 8 ++ .idea/dateparse_tag.iml | 9 +++ .idea/misc.xml | 4 + .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ .idea/watcherTasks.xml | 8 ++ README.md | 37 +++++++++ go.mod | 5 ++ go.sum | 11 +++ parse.go | 161 ++++++++++++++++++++++++++++++++++++++++ parse_test.go | 26 +++++++ tool.go | 36 +++++++++ 12 files changed, 319 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/dateparse_tag.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/watcherTasks.xml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 parse.go create mode 100644 parse_test.go create mode 100644 tool.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/dateparse_tag.iml b/.idea/dateparse_tag.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/dateparse_tag.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..019aa83 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..911ef2d --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml new file mode 100644 index 0000000..4aabca4 --- /dev/null +++ b/.idea/watcherTasks.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e2ea51f..808b776 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,39 @@ # dateparse_tag dateparse time by struct tag + +## 简介 +WithTagName() // 自定义你想要使用的tag名称,默认为dateFormat +WithDefaultTagValue() // 定义这个tag的默认值,默认为 default +WithDefaultFormat() // 定义时间格式化样式,默认为 2006-01-02 15:04:05 +WithEmptyValue() // 定义一个空值返回,当指定结构体的指定字段为空值时,返回你想要的空值,默认为 `""` + +## install&安装 +```go + go get github.com/cowardmrx/dateparse_tag +``` +## use&使用 +```go +type User struct { + Name string `json:"name"` + BirthDay string `json:"birth_day" format_date:"default"` +} + +func TestNewDateParseTag(t *testing.T) { + u := new(User) + + u.Name = "张三" + u.BirthDay = time.Now().String() + + t.Logf("user : %v", u) + + dp := NewDateParseTag(WithTagName("format_date")) + + dp.Parse(u, u) + + t.Logf("user new %v", u) +} + +// old user : &{张三 2022-01-12 14:10:17.1867047 +0800 CST m=+0.003444301} +// new user &{张三 2022-01-12 14:10:17} + +``` \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5826062 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/cowardmrx/dateparse_tag + +go 1.17 + +require github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6436794 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= +github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/parse.go b/parse.go new file mode 100644 index 0000000..a79c2d0 --- /dev/null +++ b/parse.go @@ -0,0 +1,161 @@ +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 { + Parse(in, out interface{}) +} + +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 +// @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 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 +} diff --git a/parse_test.go b/parse_test.go new file mode 100644 index 0000000..a253eba --- /dev/null +++ b/parse_test.go @@ -0,0 +1,26 @@ +package dateparse_tag + +import ( + "testing" + "time" +) + +type User struct { + Name string `json:"name"` + BirthDay string `json:"birth_day" format_date:"default"` +} + +func TestNewDateParseTag(t *testing.T) { + u := new(User) + + u.Name = "张三" + u.BirthDay = time.Now().String() + + t.Logf("old user : %v", u) + + dp := NewDateParseTag(WithTagName("format_date")) + + dp.Parse(u, u) + + t.Logf("new user %v", u) +} diff --git a/tool.go b/tool.go new file mode 100644 index 0000000..13cdd28 --- /dev/null +++ b/tool.go @@ -0,0 +1,36 @@ +package dateparse_tag + +import ( + "fmt" + "github.com/araddon/dateparse" +) + +// @method validateDateFormat +// @description: validate date layout +// @param layout string +// @return string +// @return error +func validateDateFormat(layout string) (string, error) { + tFormat, err := dateparse.ParseFormat(layout) + + if err != nil { + return "", err + } + + return tFormat, nil +} + +// @method parseTime +// @description: parse time +// @param layout string +// @param times string +// @return string +func parseTime(layout, times string) string { + t1, err := dateparse.ParseLocal(times) + + if err != nil { + panic(fmt.Sprintf("time parse failed: %v : %v", times, err.Error())) + } + + return t1.Format(layout) +}