This commit is contained in:
coward 2022-01-12 14:11:27 +08:00
parent 1ce6d5dfe9
commit 6a9de038b7
12 changed files with 319 additions and 0 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@ -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/

9
.idea/dateparse_tag.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

4
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GOROOT" url="file://E:/golang/golang" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/dateparse_tag.iml" filepath="$PROJECT_DIR$/.idea/dateparse_tag.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

8
.idea/watcherTasks.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<enabled-global>
<option value="go fmt" />
</enabled-global>
</component>
</project>

View File

@ -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}
```

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/cowardmrx/dateparse_tag
go 1.17
require github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect

11
go.sum Normal file
View File

@ -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=

161
parse.go Normal file
View File

@ -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
}

26
parse_test.go Normal file
View File

@ -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)
}

36
tool.go Normal file
View File

@ -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)
}