Skip to content

Commit f0805c6

Browse files
author
Dean Karn
authored
Merge pull request #641 from math-nao/master
Add support for time zone validation
2 parents 76981cc + 7dbe685 commit f0805c6

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

baked_in.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ var (
180180
"lowercase": isLowercase,
181181
"uppercase": isUppercase,
182182
"datetime": isDatetime,
183+
"timezone": isTimeZone,
183184
}
184185
)
185186

@@ -2211,3 +2212,29 @@ func isDatetime(fl FieldLevel) bool {
22112212

22122213
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
22132214
}
2215+
2216+
// isTimeZone is the validation function for validating if the current field's value is a valid time zone string.
2217+
func isTimeZone(fl FieldLevel) bool {
2218+
field := fl.Field()
2219+
2220+
if field.Kind() == reflect.String {
2221+
// empty value is converted to UTC by time.LoadLocation but disallow it as it is not a valid time zone name
2222+
if field.String() == "" {
2223+
return false
2224+
}
2225+
2226+
// Local value is converted to the current system time zone by time.LoadLocation but disallow it as it is not a valid time zone name
2227+
if strings.ToLower(field.String()) == "local" {
2228+
return false
2229+
}
2230+
2231+
_, err := time.LoadLocation(field.String())
2232+
if err != nil {
2233+
return false
2234+
}
2235+
2236+
return true
2237+
}
2238+
2239+
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
2240+
}

doc.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,14 @@ Supplied format must match the official Go time format layout as documented in h
11941194
11951195
Usage: datetime=2006-01-02
11961196
1197+
TimeZone
1198+
1199+
This validates that a string value is a valid time zone based on the time zone database present on the system.
1200+
Although empty value and Local value are allowed by time.LoadLocation golang function, they are not allowed by this validator.
1201+
More information on https://golang.org/pkg/time/#LoadLocation
1202+
1203+
Usage: timezone
1204+
11971205
Alias Validators and Tags
11981206
11991207
NOTE: When returning an error, the tag returned in "FieldError" will be

validator_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10835,3 +10835,44 @@ func TestDatetimeValidation(t *testing.T) {
1083510835
_ = validate.Var(2, "datetime")
1083610836
}, "Bad field type int")
1083710837
}
10838+
10839+
func TestTimeZoneValidation(t *testing.T) {
10840+
tests := []struct {
10841+
value string `validate:"timezone"`
10842+
tag string
10843+
expected bool
10844+
}{
10845+
// systems may have different time zone database, some systems time zone are case insensitive
10846+
{"America/New_York", `timezone`, true},
10847+
{"UTC", `timezone`, true},
10848+
{"", `timezone`, false},
10849+
{"Local", `timezone`, false},
10850+
{"Unknown", `timezone`, false},
10851+
}
10852+
10853+
validate := New()
10854+
10855+
for i, test := range tests {
10856+
10857+
errs := validate.Var(test.value, test.tag)
10858+
10859+
if test.expected {
10860+
if !IsEqual(errs, nil) {
10861+
t.Fatalf("Index: %d time zone failed Error: %s", i, errs)
10862+
}
10863+
} else {
10864+
if IsEqual(errs, nil) {
10865+
t.Fatalf("Index: %d time zone failed Error: %s", i, errs)
10866+
} else {
10867+
val := getError(errs, "", "")
10868+
if val.Tag() != "timezone" {
10869+
t.Fatalf("Index: %d time zone failed Error: %s", i, errs)
10870+
}
10871+
}
10872+
}
10873+
}
10874+
10875+
PanicMatches(t, func() {
10876+
_ = validate.Var(2, "timezone")
10877+
}, "Bad field type int")
10878+
}

0 commit comments

Comments
 (0)