Add datetime validation

pull/575/head
Pantelis Sampaziotis 5 years ago
parent b7430f8e39
commit 14f963703b
  1. 19
      baked_in.go
  2. 7
      doc.go
  3. 15
      translations/en/en.go
  4. 9
      translations/en/en_test.go
  5. 38
      validator_test.go

@ -171,6 +171,7 @@ var (
"hostname_port": isHostnamePort, "hostname_port": isHostnamePort,
"lowercase": isLowercase, "lowercase": isLowercase,
"uppercase": isUppercase, "uppercase": isUppercase,
"datetime": isDatetime,
} }
) )
@ -2021,6 +2022,7 @@ func isJSON(fl FieldLevel) bool {
val := field.String() val := field.String()
return json.Valid([]byte(val)) return json.Valid([]byte(val))
} }
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
@ -2070,3 +2072,20 @@ func isUppercase(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
// isDatetime is the validation function for validating if the current field's value is a valid datetime string.
func isDatetime(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
if field.Kind() == reflect.String {
_, err := time.Parse(param, field.String())
if err != nil {
return false
}
return true
}
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}

@ -1062,6 +1062,13 @@ can be used to valiate fields typically passed to sockets and connections.
Usage: hostname_port Usage: hostname_port
Datetime
This validates that a string value is a valid datetime based on the supplied datetime format.
Supplied format must match the official Go time format layout as documented in https://golang.org/pkg/time/
Usage: datetime=2006-01-02
Alias Validators and Tags Alias Validators and Tags
NOTE: When returning an error, the tag returned in "FieldError" will be NOTE: When returning an error, the tag returned in "FieldError" will be

@ -1336,6 +1336,21 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be an uppercase string", translation: "{0} must be an uppercase string",
override: false, override: false,
}, },
{
tag: "datetime",
translation: "{0} does not match the {1} format",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
return fe.(error).Error()
}
return t
},
},
} }
for _, t := range translations { for _, t := range translations {

@ -141,9 +141,13 @@ func TestTranslations(t *testing.T) {
UniqueSlice []string `validate:"unique"` UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
<<<<<<< HEAD
JSONString string `validate:"json"` JSONString string `validate:"json"`
LowercaseString string `validate:"lowercase"` LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"` UppercaseString string `validate:"uppercase"`
=======
Datetime string `validate:"datetime=2006-01-02"`
>>>>>>> Add datetime validation
} }
var test Test var test Test
@ -195,6 +199,7 @@ func TestTranslations(t *testing.T) {
test.UniqueSlice = []string{"1234", "1234"} test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test) err = validate.Struct(test)
NotEqual(t, err, nil) NotEqual(t, err, nil)
@ -650,6 +655,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.UppercaseString", ns: "Test.UppercaseString",
expected: "UppercaseString must be an uppercase string", expected: "UppercaseString must be an uppercase string",
}, },
{
ns: "Test.Datetime",
expected: "Datetime does not match the 2006-01-02 format",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -9155,4 +9155,42 @@ func TestUppercaseValidation(t *testing.T) {
PanicMatches(t, func() { PanicMatches(t, func() {
_ = validate.Var(2, "uppercase") _ = validate.Var(2, "uppercase")
}, "Bad field type int") }, "Bad field type int")
}
func TestDatetimeValidation(t *testing.T) {
tests := []struct {
value string `validate:"datetime=2006-01-02"`
tag string
expected bool
}{
{"2008-02-01", `datetime=2006-01-02`, true},
{"2008-Feb-01", `datetime=2006-01-02`, false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.value, test.tag)
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d datetime failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d datetime failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "datetime" {
t.Fatalf("Index: %d datetime failed Error: %s", i, errs)
}
}
}
}
PanicMatches(t, func() {
_ = validate.Var(2, "datetime")
}, "Bad field type int")
} }
Loading…
Cancel
Save