Repository: go-playground/validator
Pull request #613 (2020-05-21 17:31:47)

Added Translation for pt
Transpations to portuguese (from Portugal)

Change Details:
- added pt package containing the translations and corresponding tests


@go-playground/admins


Patch:
diff --git a/.gitignore b/.gitignore
index 792ca00..6e43fac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 # Folders
 _obj
 _test
+bin
 
 # Architecture specific extensions/prefixes
 *.[568vq]
@@ -26,4 +27,4 @@ _testmain.go
 *.out
 *.txt
 cover.html
-README.html
\ No newline at end of file
+README.html
diff --git a/.travis.yml b/.travis.yml
index f6484f3..85a7be3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: go
 go:
-  - 1.13.7
+  - 1.15.2
   - tip
 matrix:
   allow_failures:
@@ -25,5 +25,5 @@ script:
   - go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
 
 after_success: |
-  [ $TRAVIS_GO_VERSION = 1.13.7 ] &&
-  goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
\ No newline at end of file
+  [ $TRAVIS_GO_VERSION = 1.15.2 ] &&
+  goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
diff --git a/README.md b/README.md
index f552826..054f294 100644
--- a/README.md
+++ b/README.md
@@ -129,6 +129,7 @@ Baked-in Validations
 | contains | Contains |
 | containsany | Contains Any |
 | containsrune | Contains Rune |
+| endswith | Ends With |
 | lowercase | Lowercase |
 | multibyte | Multi-Byte Characters |
 | number | NOT DOCUMENTED IN doc.go |
@@ -145,6 +146,7 @@ Baked-in Validations
 | btc_addr | Bitcoin Address |
 | btc_addr_bech32 | Bitcoin Bech32 Address (segwit) |
 | datetime | Datetime |
+| e164 | e164 formatted phone number |
 | email | E-mail String
 | eth_addr | Ethereum Address |
 | hexadecimal | Hexadecimal String |
@@ -185,7 +187,6 @@ Baked-in Validations
 | Tag | Description |
 | - | - |
 | dir | Directory |
-| e164 | NOT DOCUMENTED IN doc.go |
 | endswith | Ends With |
 | excludes | Excludes |
 | excludesall | Excludes All |
@@ -197,10 +198,16 @@ Baked-in Validations
 | min | Minimum |
 | oneof | One Of |
 | required | Required |
+| required_if | Required If |
+| required_unless | Required Unless |
 | required_with | Required With |
 | required_with_all | Required With All |
 | required_without | Required Without |
 | required_without_all | Required Without All |
+| excluded_with | Excluded With |
+| excluded_with_all | Excluded With All |
+| excluded_without | Excluded Without |
+| excluded_without_all | Excluded Without All |
 | unique | Unique |
 
 Benchmarks
diff --git a/baked_in.go b/baked_in.go
index 36e8057..ca3d3b9 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"context"
 	"crypto/sha256"
+	"encoding/hex"
 	"encoding/json"
 	"fmt"
 	"net"
@@ -16,6 +17,8 @@ import (
 	"time"
 	"unicode/utf8"
 
+	"golang.org/x/crypto/sha3"
+
 	urn "github.com/leodido/go-urn"
 )
 
@@ -56,7 +59,8 @@ var (
 	// defines a common or complex set of validation(s) to simplify
 	// adding validation to structs.
 	bakedInAliases = map[string]string{
-		"iscolor": "hexcolor|rgb|rgba|hsl|hsla",
+		"iscolor":      "hexcolor|rgb|rgba|hsl|hsla",
+		"country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric",
 	}
 
 	// BakedInValidators is the default map of ValidationFunc
@@ -64,10 +68,16 @@ var (
 	// or even disregard and use your own map if so desired.
 	bakedInValidators = map[string]Func{
 		"required":             hasValue,
+		"required_if":          requiredIf,
+		"required_unless":      requiredUnless,
 		"required_with":        requiredWith,
 		"required_with_all":    requiredWithAll,
 		"required_without":     requiredWithout,
 		"required_without_all": requiredWithoutAll,
+		"excluded_with":        excludedWith,
+		"excluded_with_all":    excludedWithAll,
+		"excluded_without":     excludedWithout,
+		"excluded_without_all": excludedWithoutAll,
 		"isdefault":            isDefault,
 		"len":                  hasLengthOf,
 		"min":                  hasMinOf,
@@ -174,6 +184,10 @@ var (
 		"lowercase":            isLowercase,
 		"uppercase":            isUppercase,
 		"datetime":             isDatetime,
+		"timezone":             isTimeZone,
+    "iso3166_1_alpha2":        isIso3166Alpha2,
+		"iso3166_1_alpha3":        isIso3166Alpha3,
+		"iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
 	}
 )
 
@@ -241,23 +255,33 @@ func isUnique(fl FieldLevel) bool {
 
 	switch field.Kind() {
 	case reflect.Slice, reflect.Array:
+		elem := field.Type().Elem()
+		if elem.Kind() == reflect.Ptr {
+			elem = elem.Elem()
+		}
+
 		if param == "" {
-			m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
+			m := reflect.MakeMap(reflect.MapOf(elem, v.Type()))
 
 			for i := 0; i < field.Len(); i++ {
-				m.SetMapIndex(field.Index(i), v)
+				m.SetMapIndex(reflect.Indirect(field.Index(i)), v)
 			}
 			return field.Len() == m.Len()
 		}
 
-		sf, ok := field.Type().Elem().FieldByName(param)
+		sf, ok := elem.FieldByName(param)
 		if !ok {
 			panic(fmt.Sprintf("Bad field name %s", param))
 		}
 
-		m := reflect.MakeMap(reflect.MapOf(sf.Type, v.Type()))
+		sfTyp := sf.Type
+		if sfTyp.Kind() == reflect.Ptr {
+			sfTyp = sfTyp.Elem()
+		}
+
+		m := reflect.MakeMap(reflect.MapOf(sfTyp, v.Type()))
 		for i := 0; i < field.Len(); i++ {
-			m.SetMapIndex(field.Index(i).FieldByName(param), v)
+			m.SetMapIndex(reflect.Indirect(reflect.Indirect(field.Index(i)).FieldByName(param)), v)
 		}
 		return field.Len() == m.Len()
 	case reflect.Map:
@@ -515,7 +539,7 @@ func isISBN10(fl FieldLevel) bool {
 	return checksum%11 == 0
 }
 
-// IsEthereumAddress is the validation function for validating if the field's value is a valid ethereum address based currently only on the format
+// IsEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address.
 func isEthereumAddress(fl FieldLevel) bool {
 	address := fl.Field().String()
 
@@ -527,7 +551,21 @@ func isEthereumAddress(fl FieldLevel) bool {
 		return true
 	}
 
-	// checksum validation is blocked by https://github.com/golang/crypto/pull/28
+	// Checksum validation. Reference: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
+	address = address[2:] // Skip "0x" prefix.
+	h := sha3.NewLegacyKeccak256()
+	// hash.Hash's io.Writer implementation says it never returns an error. https://golang.org/pkg/hash/#Hash
+	_, _ = h.Write([]byte(strings.ToLower(address)))
+	hash := hex.EncodeToString(h.Sum(nil))
+
+	for i := 0; i < len(address); i++ {
+		if address[i] <= '9' { // Skip 0-9 digits: they don't have upper/lower-case.
+			continue
+		}
+		if hash[i] > '7' && address[i] >= 'a' || hash[i] <= '7' && address[i] <= 'F' {
+			return false
+		}
+	}
 
 	return true
 }
@@ -1129,7 +1167,7 @@ func isEq(fl FieldLevel) bool {
 		return int64(field.Len()) == p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() == p
 
@@ -1383,6 +1421,75 @@ func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue boo
 	}
 }
 
+// requireCheckFieldValue is a func for check field value
+func requireCheckFieldValue(fl FieldLevel, param string, value string, defaultNotFoundValue bool) bool {
+	field, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), param)
+	if !found {
+		return defaultNotFoundValue
+	}
+
+	switch kind {
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return field.Int() == asInt(value)
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return field.Uint() == asUint(value)
+
+	case reflect.Float32, reflect.Float64:
+		return field.Float() == asFloat(value)
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		return int64(field.Len()) == asInt(value)
+	}
+
+	// default reflect.String:
+	return field.String() == value
+}
+
+// requiredIf is the validation function
+// The field under validation must be present and not empty only if all the other specified fields are equal to the value following with the specified field.
+func requiredIf(fl FieldLevel) bool {
+	params := parseOneOfParam2(fl.Param())
+	if len(params)%2 != 0 {
+		panic(fmt.Sprintf("Bad param number for required_if %s", fl.FieldName()))
+	}
+	for i := 0; i < len(params); i += 2 {
+		if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
+			return true
+		}
+	}
+	return hasValue(fl)
+}
+
+// requiredUnless is the validation function
+// The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.
+func requiredUnless(fl FieldLevel) bool {
+	params := parseOneOfParam2(fl.Param())
+	if len(params)%2 != 0 {
+		panic(fmt.Sprintf("Bad param number for required_unless %s", fl.FieldName()))
+	}
+
+	for i := 0; i < len(params); i += 2 {
+		if requireCheckFieldValue(fl, params[i], params[i+1], false) {
+			return true
+		}
+	}
+	return hasValue(fl)
+}
+
+// ExcludedWith is the validation function
+// The field under validation must not be present or is empty if any of the other specified fields are present.
+func excludedWith(fl FieldLevel) bool {
+	params := parseOneOfParam2(fl.Param())
+	for _, param := range params {
+		if !requireCheckFieldKind(fl, param, true) {
+			return !hasValue(fl)
+		}
+	}
+	return true
+}
+
 // RequiredWith is the validation function
 // The field under validation must be present and not empty only if any of the other specified fields are present.
 func requiredWith(fl FieldLevel) bool {
@@ -1395,6 +1502,18 @@ func requiredWith(fl FieldLevel) bool {
 	return true
 }
 
+// ExcludedWithAll is the validation function
+// The field under validation must not be present or is empty if all of the other specified fields are present.
+func excludedWithAll(fl FieldLevel) bool {
+	params := parseOneOfParam2(fl.Param())
+	for _, param := range params {
+		if requireCheckFieldKind(fl, param, true) {
+			return true
+		}
+	}
+	return !hasValue(fl)
+}
+
 // RequiredWithAll is the validation function
 // The field under validation must be present and not empty only if all of the other specified fields are present.
 func requiredWithAll(fl FieldLevel) bool {
@@ -1407,6 +1526,15 @@ func requiredWithAll(fl FieldLevel) bool {
 	return hasValue(fl)
 }
 
+// ExcludedWithout is the validation function
+// The field under validation must not be present or is empty when any of the other specified fields are not present.
+func excludedWithout(fl FieldLevel) bool {
+	if requireCheckFieldKind(fl, strings.TrimSpace(fl.Param()), true) {
+		return !hasValue(fl)
+	}
+	return true
+}
+
 // RequiredWithout is the validation function
 // The field under validation must be present and not empty only when any of the other specified fields are not present.
 func requiredWithout(fl FieldLevel) bool {
@@ -1416,6 +1544,18 @@ func requiredWithout(fl FieldLevel) bool {
 	return true
 }
 
+// RequiredWithoutAll is the validation function
+// The field under validation must not be present or is empty when all of the other specified fields are not present.
+func excludedWithoutAll(fl FieldLevel) bool {
+	params := parseOneOfParam2(fl.Param())
+	for _, param := range params {
+		if !requireCheckFieldKind(fl, param, true) {
+			return true
+		}
+	}
+	return !hasValue(fl)
+}
+
 // RequiredWithoutAll is the validation function
 // The field under validation must be present and not empty only when all of the other specified fields are not present.
 func requiredWithoutAll(fl FieldLevel) bool {
@@ -1541,7 +1681,7 @@ func isGte(fl FieldLevel) bool {
 		return int64(field.Len()) >= p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() >= p
 
@@ -1588,7 +1728,7 @@ func isGt(fl FieldLevel) bool {
 		return int64(field.Len()) > p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() > p
 
@@ -1631,7 +1771,7 @@ func hasLengthOf(fl FieldLevel) bool {
 		return int64(field.Len()) == p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() == p
 
@@ -1767,7 +1907,7 @@ func isLte(fl FieldLevel) bool {
 		return int64(field.Len()) <= p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() <= p
 
@@ -1814,7 +1954,7 @@ func isLt(fl FieldLevel) bool {
 		return int64(field.Len()) < p
 
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p := asInt(param)
+		p := asIntFromType(field.Type(), param)
 
 		return field.Int() < p
 
@@ -2087,6 +2227,29 @@ func isDatetime(fl FieldLevel) bool {
 
 	if field.Kind() == reflect.String {
 		_, err := time.Parse(param, field.String())
+
+		return err == nil
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
+}
+
+// isTimeZone is the validation function for validating if the current field's value is a valid time zone string.
+func isTimeZone(fl FieldLevel) bool {
+	field := fl.Field()
+
+	if field.Kind() == reflect.String {
+		// empty value is converted to UTC by time.LoadLocation but disallow it as it is not a valid time zone name
+		if field.String() == "" {
+			return false
+		}
+
+		// 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
+		if strings.ToLower(field.String()) == "local" {
+			return false
+		}
+
+		_, err := time.LoadLocation(field.String())
 		if err != nil {
 			return false
 		}
@@ -2096,3 +2259,31 @@ func isDatetime(fl FieldLevel) bool {
 
 	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
 }
+
+// isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 country code.
+func isIso3166Alpha2(fl FieldLevel) bool {
+	val := fl.Field().String()
+	return iso3166_1_alpha2[val]
+}
+
+// isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 country code.
+func isIso3166Alpha3(fl FieldLevel) bool {
+	val := fl.Field().String()
+	return iso3166_1_alpha3[val]
+}
+
+// isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric country code.
+func isIso3166AlphaNumeric(fl FieldLevel) bool {
+	field := fl.Field()
+
+	var code int
+	switch field.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		code = int(field.Int() % 1000)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		code = int(field.Uint() % 1000)
+	default:
+		panic(fmt.Sprintf("Bad field type %T", field.Interface()))
+	}
+	return iso3166_1_alpha_numeric[code]
+}
diff --git a/country_codes.go b/country_codes.go
new file mode 100644
index 0000000..ef81ead
--- /dev/null
+++ b/country_codes.go
@@ -0,0 +1,162 @@
+package validator
+
+var iso3166_1_alpha2 = map[string]bool{
+	// see: https://www.iso.org/iso-3166-country-codes.html
+	"AF": true, "AX": true, "AL": true, "DZ": true, "AS": true,
+	"AD": true, "AO": true, "AI": true, "AQ": true, "AG": true,
+	"AR": true, "AM": true, "AW": true, "AU": true, "AT": true,
+	"AZ": true, "BS": true, "BH": true, "BD": true, "BB": true,
+	"BY": true, "BE": true, "BZ": true, "BJ": true, "BM": true,
+	"BT": true, "BO": true, "BQ": true, "BA": true, "BW": true,
+	"BV": true, "BR": true, "IO": true, "BN": true, "BG": true,
+	"BF": true, "BI": true, "KH": true, "CM": true, "CA": true,
+	"CV": true, "KY": true, "CF": true, "TD": true, "CL": true,
+	"CN": true, "CX": true, "CC": true, "CO": true, "KM": true,
+	"CG": true, "CD": true, "CK": true, "CR": true, "CI": true,
+	"HR": true, "CU": true, "CW": true, "CY": true, "CZ": true,
+	"DK": true, "DJ": true, "DM": true, "DO": true, "EC": true,
+	"EG": true, "SV": true, "GQ": true, "ER": true, "EE": true,
+	"ET": true, "FK": true, "FO": true, "FJ": true, "FI": true,
+	"FR": true, "GF": true, "PF": true, "TF": true, "GA": true,
+	"GM": true, "GE": true, "DE": true, "GH": true, "GI": true,
+	"GR": true, "GL": true, "GD": true, "GP": true, "GU": true,
+	"GT": true, "GG": true, "GN": true, "GW": true, "GY": true,
+	"HT": true, "HM": true, "VA": true, "HN": true, "HK": true,
+	"HU": true, "IS": true, "IN": true, "ID": true, "IR": true,
+	"IQ": true, "IE": true, "IM": true, "IL": true, "IT": true,
+	"JM": true, "JP": true, "JE": true, "JO": true, "KZ": true,
+	"KE": true, "KI": true, "KP": true, "KR": true, "KW": true,
+	"KG": true, "LA": true, "LV": true, "LB": true, "LS": true,
+	"LR": true, "LY": true, "LI": true, "LT": true, "LU": true,
+	"MO": true, "MK": true, "MG": true, "MW": true, "MY": true,
+	"MV": true, "ML": true, "MT": true, "MH": true, "MQ": true,
+	"MR": true, "MU": true, "YT": true, "MX": true, "FM": true,
+	"MD": true, "MC": true, "MN": true, "ME": true, "MS": true,
+	"MA": true, "MZ": true, "MM": true, "NA": true, "NR": true,
+	"NP": true, "NL": true, "NC": true, "NZ": true, "NI": true,
+	"NE": true, "NG": true, "NU": true, "NF": true, "MP": true,
+	"NO": true, "OM": true, "PK": true, "PW": true, "PS": true,
+	"PA": true, "PG": true, "PY": true, "PE": true, "PH": true,
+	"PN": true, "PL": true, "PT": true, "PR": true, "QA": true,
+	"RE": true, "RO": true, "RU": true, "RW": true, "BL": true,
+	"SH": true, "KN": true, "LC": true, "MF": true, "PM": true,
+	"VC": true, "WS": true, "SM": true, "ST": true, "SA": true,
+	"SN": true, "RS": true, "SC": true, "SL": true, "SG": true,
+	"SX": true, "SK": true, "SI": true, "SB": true, "SO": true,
+	"ZA": true, "GS": true, "SS": true, "ES": true, "LK": true,
+	"SD": true, "SR": true, "SJ": true, "SZ": true, "SE": true,
+	"CH": true, "SY": true, "TW": true, "TJ": true, "TZ": true,
+	"TH": true, "TL": true, "TG": true, "TK": true, "TO": true,
+	"TT": true, "TN": true, "TR": true, "TM": true, "TC": true,
+	"TV": true, "UG": true, "UA": true, "AE": true, "GB": true,
+	"US": true, "UM": true, "UY": true, "UZ": true, "VU": true,
+	"VE": true, "VN": true, "VG": true, "VI": true, "WF": true,
+	"EH": true, "YE": true, "ZM": true, "ZW": true,
+}
+
+var iso3166_1_alpha3 = map[string]bool{
+	// see: https://www.iso.org/iso-3166-country-codes.html
+	"AFG": true, "ALB": true, "DZA": true, "ASM": true, "AND": true,
+	"AGO": true, "AIA": true, "ATA": true, "ATG": true, "ARG": true,
+	"ARM": true, "ABW": true, "AUS": true, "AUT": true, "AZE": true,
+	"BHS": true, "BHR": true, "BGD": true, "BRB": true, "BLR": true,
+	"BEL": true, "BLZ": true, "BEN": true, "BMU": true, "BTN": true,
+	"BOL": true, "BES": true, "BIH": true, "BWA": true, "BVT": true,
+	"BRA": true, "IOT": true, "BRN": true, "BGR": true, "BFA": true,
+	"BDI": true, "CPV": true, "KHM": true, "CMR": true, "CAN": true,
+	"CYM": true, "CAF": true, "TCD": true, "CHL": true, "CHN": true,
+	"CXR": true, "CCK": true, "COL": true, "COM": true, "COD": true,
+	"COG": true, "COK": true, "CRI": true, "HRV": true, "CUB": true,
+	"CUW": true, "CYP": true, "CZE": true, "CIV": true, "DNK": true,
+	"DJI": true, "DMA": true, "DOM": true, "ECU": true, "EGY": true,
+	"SLV": true, "GNQ": true, "ERI": true, "EST": true, "SWZ": true,
+	"ETH": true, "FLK": true, "FRO": true, "FJI": true, "FIN": true,
+	"FRA": true, "GUF": true, "PYF": true, "ATF": true, "GAB": true,
+	"GMB": true, "GEO": true, "DEU": true, "GHA": true, "GIB": true,
+	"GRC": true, "GRL": true, "GRD": true, "GLP": true, "GUM": true,
+	"GTM": true, "GGY": true, "GIN": true, "GNB": true, "GUY": true,
+	"HTI": true, "HMD": true, "VAT": true, "HND": true, "HKG": true,
+	"HUN": true, "ISL": true, "IND": true, "IDN": true, "IRN": true,
+	"IRQ": true, "IRL": true, "IMN": true, "ISR": true, "ITA": true,
+	"JAM": true, "JPN": true, "JEY": true, "JOR": true, "KAZ": true,
+	"KEN": true, "KIR": true, "PRK": true, "KOR": true, "KWT": true,
+	"KGZ": true, "LAO": true, "LVA": true, "LBN": true, "LSO": true,
+	"LBR": true, "LBY": true, "LIE": true, "LTU": true, "LUX": true,
+	"MAC": true, "MDG": true, "MWI": true, "MYS": true, "MDV": true,
+	"MLI": true, "MLT": true, "MHL": true, "MTQ": true, "MRT": true,
+	"MUS": true, "MYT": true, "MEX": true, "FSM": true, "MDA": true,
+	"MCO": true, "MNG": true, "MNE": true, "MSR": true, "MAR": true,
+	"MOZ": true, "MMR": true, "NAM": true, "NRU": true, "NPL": true,
+	"NLD": true, "NCL": true, "NZL": true, "NIC": true, "NER": true,
+	"NGA": true, "NIU": true, "NFK": true, "MKD": true, "MNP": true,
+	"NOR": true, "OMN": true, "PAK": true, "PLW": true, "PSE": true,
+	"PAN": true, "PNG": true, "PRY": true, "PER": true, "PHL": true,
+	"PCN": true, "POL": true, "PRT": true, "PRI": true, "QAT": true,
+	"ROU": true, "RUS": true, "RWA": true, "REU": true, "BLM": true,
+	"SHN": true, "KNA": true, "LCA": true, "MAF": true, "SPM": true,
+	"VCT": true, "WSM": true, "SMR": true, "STP": true, "SAU": true,
+	"SEN": true, "SRB": true, "SYC": true, "SLE": true, "SGP": true,
+	"SXM": true, "SVK": true, "SVN": true, "SLB": true, "SOM": true,
+	"ZAF": true, "SGS": true, "SSD": true, "ESP": true, "LKA": true,
+	"SDN": true, "SUR": true, "SJM": true, "SWE": true, "CHE": true,
+	"SYR": true, "TWN": true, "TJK": true, "TZA": true, "THA": true,
+	"TLS": true, "TGO": true, "TKL": true, "TON": true, "TTO": true,
+	"TUN": true, "TUR": true, "TKM": true, "TCA": true, "TUV": true,
+	"UGA": true, "UKR": true, "ARE": true, "GBR": true, "UMI": true,
+	"USA": true, "URY": true, "UZB": true, "VUT": true, "VEN": true,
+	"VNM": true, "VGB": true, "VIR": true, "WLF": true, "ESH": true,
+	"YEM": true, "ZMB": true, "ZWE": true, "ALA": true,
+}
+var iso3166_1_alpha_numeric = map[int]bool{
+	// see: https://www.iso.org/iso-3166-country-codes.html
+	4: true, 8: true, 12: true, 16: true, 20: true,
+	24: true, 660: true, 10: true, 28: true, 32: true,
+	51: true, 533: true, 36: true, 40: true, 31: true,
+	44: true, 48: true, 50: true, 52: true, 112: true,
+	56: true, 84: true, 204: true, 60: true, 64: true,
+	68: true, 535: true, 70: true, 72: true, 74: true,
+	76: true, 86: true, 96: true, 100: true, 854: true,
+	108: true, 132: true, 116: true, 120: true, 124: true,
+	136: true, 140: true, 148: true, 152: true, 156: true,
+	162: true, 166: true, 170: true, 174: true, 180: true,
+	178: true, 184: true, 188: true, 191: true, 192: true,
+	531: true, 196: true, 203: true, 384: true, 208: true,
+	262: true, 212: true, 214: true, 218: true, 818: true,
+	222: true, 226: true, 232: true, 233: true, 748: true,
+	231: true, 238: true, 234: true, 242: true, 246: true,
+	250: true, 254: true, 258: true, 260: true, 266: true,
+	270: true, 268: true, 276: true, 288: true, 292: true,
+	300: true, 304: true, 308: true, 312: true, 316: true,
+	320: true, 831: true, 324: true, 624: true, 328: true,
+	332: true, 334: true, 336: true, 340: true, 344: true,
+	348: true, 352: true, 356: true, 360: true, 364: true,
+	368: true, 372: true, 833: true, 376: true, 380: true,
+	388: true, 392: true, 832: true, 400: true, 398: true,
+	404: true, 296: true, 408: true, 410: true, 414: true,
+	417: true, 418: true, 428: true, 422: true, 426: true,
+	430: true, 434: true, 438: true, 440: true, 442: true,
+	446: true, 450: true, 454: true, 458: true, 462: true,
+	466: true, 470: true, 584: true, 474: true, 478: true,
+	480: true, 175: true, 484: true, 583: true, 498: true,
+	492: true, 496: true, 499: true, 500: true, 504: true,
+	508: true, 104: true, 516: true, 520: true, 524: true,
+	528: true, 540: true, 554: true, 558: true, 562: true,
+	566: true, 570: true, 574: true, 807: true, 580: true,
+	578: true, 512: true, 586: true, 585: true, 275: true,
+	591: true, 598: true, 600: true, 604: true, 608: true,
+	612: true, 616: true, 620: true, 630: true, 634: true,
+	642: true, 643: true, 646: true, 638: true, 652: true,
+	654: true, 659: true, 662: true, 663: true, 666: true,
+	670: true, 882: true, 674: true, 678: true, 682: true,
+	686: true, 688: true, 690: true, 694: true, 702: true,
+	534: true, 703: true, 705: true, 90: true, 706: true,
+	710: true, 239: true, 728: true, 724: true, 144: true,
+	729: true, 740: true, 744: true, 752: true, 756: true,
+	760: true, 158: true, 762: true, 834: true, 764: true,
+	626: true, 768: true, 772: true, 776: true, 780: true,
+	788: true, 792: true, 795: true, 796: true, 798: true,
+	800: true, 804: true, 784: true, 826: true, 581: true,
+	840: true, 858: true, 860: true, 548: true, 862: true,
+	704: true, 92: true, 850: true, 876: true, 732: true,
+	887: true, 894: true, 716: true, 248: true,
+}
diff --git a/doc.go b/doc.go
index 4aba75f..a816c20 100644
--- a/doc.go
+++ b/doc.go
@@ -245,6 +245,40 @@ ensures the value is not nil.
 
 	Usage: required
 
+Required If
+
+The field under validation must be present and not empty only if all
+the other specified fields are equal to the value following the specified
+field. For strings ensures value is not "". For slices, maps, pointers,
+interfaces, channels and functions ensures the value is not nil.
+
+	Usage: required_if
+
+Examples:
+
+	// require the field if the Field1 is equal to the parameter given:
+	Usage: required_if=Field1 foobar
+
+	// require the field if the Field1 and Field2 is equal to the value respectively:
+	Usage: required_if=Field1 foo Field2 bar
+
+Required Unless
+
+The field under validation must be present and not empty unless all
+the other specified fields are equal to the value following the specified
+field. For strings ensures value is not "". For slices, maps, pointers,
+interfaces, channels and functions ensures the value is not nil.
+
+	Usage: required_unless
+
+Examples:
+
+	// require the field unless the Field1 is equal to the parameter given:
+	Usage: required_unless=Field1 foobar
+
+	// require the field unless the Field1 and Field2 is equal to the value respectively:
+	Usage: required_unless=Field1 foo Field2 bar
+
 Required With
 
 The field under validation must be present and not empty only if any
@@ -321,8 +355,17 @@ equal to the parameter given. For strings, it checks that
 the string length is exactly that number of characters. For slices,
 arrays, and maps, validates the number of items.
 
+Example #1
+
 	Usage: len=10
 
+Example #2 (time.Duration)
+
+For time.Duration, len will ensure that the value is equal to the duration given
+in the parameter.
+
+	Usage: len=1h30m
+
 Maximum
 
 For numbers, max will ensure that the value is
@@ -330,8 +373,17 @@ less than or equal to the parameter given. For strings, it checks
 that the string length is at most that number of characters. For
 slices, arrays, and maps, validates the number of items.
 
+Example #1
+
 	Usage: max=10
 
+Example #2 (time.Duration)
+
+For time.Duration, max will ensure that the value is less than or equal to the
+duration given in the parameter.
+
+	Usage: max=1h30m
+
 Minimum
 
 For numbers, min will ensure that the value is
@@ -339,24 +391,51 @@ greater or equal to the parameter given. For strings, it checks that
 the string length is at least that number of characters. For slices,
 arrays, and maps, validates the number of items.
 
+Example #1
+
 	Usage: min=10
 
+Example #2 (time.Duration)
+
+For time.Duration, min will ensure that the value is greater than or equal to
+the duration given in the parameter.
+
+	Usage: min=1h30m
+
 Equals
 
 For strings & numbers, eq will ensure that the value is
 equal to the parameter given. For slices, arrays, and maps,
 validates the number of items.
 
+Example #1
+
 	Usage: eq=10
 
+Example #2 (time.Duration)
+
+For time.Duration, eq will ensure that the value is equal to the duration given
+in the parameter.
+
+	Usage: eq=1h30m
+
 Not Equal
 
 For strings & numbers, ne will ensure that the value is not
 equal to the parameter given. For slices, arrays, and maps,
 validates the number of items.
 
+Example #1
+
 	Usage: ne=10
 
+Example #2 (time.Duration)
+
+For time.Duration, ne will ensure that the value is not equal to the duration
+given in the parameter.
+
+	Usage: ne=1h30m
+
 One Of
 
 For strings, ints, and uints, oneof will ensure that the value
@@ -386,11 +465,17 @@ For time.Time ensures the time value is greater than time.Now.UTC().
 
 	Usage: gt
 
+Example #3 (time.Duration)
+
+For time.Duration, gt will ensure that the value is greater than the duration
+given in the parameter.
+
+	Usage: gt=1h30m
+
 Greater Than or Equal
 
 Same as 'min' above. Kept both to make terminology with 'len' easier.
 
-
 Example #1
 
 	Usage: gte=10
@@ -401,6 +486,13 @@ For time.Time ensures the time value is greater than or equal to time.Now.UTC().
 
 	Usage: gte
 
+Example #3 (time.Duration)
+
+For time.Duration, gte will ensure that the value is greater than or equal to
+the duration given in the parameter.
+
+	Usage: gte=1h30m
+
 Less Than
 
 For numbers, this will ensure that the value is less than the parameter given.
@@ -412,10 +504,18 @@ Example #1
 	Usage: lt=10
 
 Example #2 (time.Time)
+
 For time.Time ensures the time value is less than time.Now.UTC().
 
 	Usage: lt
 
+Example #3 (time.Duration)
+
+For time.Duration, lt will ensure that the value is less than the duration given
+in the parameter.
+
+	Usage: lt=1h30m
+
 Less Than or Equal
 
 Same as 'max' above. Kept both to make terminology with 'len' easier.
@@ -430,6 +530,13 @@ For time.Time ensures the time value is less than or equal to time.Now.UTC().
 
 	Usage: lte
 
+Example #3 (time.Duration)
+
+For time.Duration, lte will ensure that the value is less than or equal to the
+duration given in the parameter.
+
+	Usage: lte=1h30m
+
 Field Equals Another Field
 
 This will validate the field value against another fields value either within
@@ -476,9 +583,9 @@ relative to the top level struct.
 
 Field Greater Than Another Field
 
-Only valid for Numbers and time.Time types, this will validate the field value
-against another fields value either within a struct or passed in field.
-usage examples are for validation of a Start and End date:
+Only valid for Numbers, time.Duration and time.Time types, this will validate
+the field value against another fields value either within a struct or passed in
+field. usage examples are for validation of a Start and End date:
 
 Example #1:
 
@@ -490,7 +597,6 @@ Example #2:
 	// Validating by field:
 	validate.VarWithValue(start, end, "gtfield")
 
-
 Field Greater Than Another Relative Field
 
 This does the same as gtfield except that it validates the field provided
@@ -500,9 +606,9 @@ relative to the top level struct.
 
 Field Greater Than or Equal To Another Field
 
-Only valid for Numbers and time.Time types, this will validate the field value
-against another fields value either within a struct or passed in field.
-usage examples are for validation of a Start and End date:
+Only valid for Numbers, time.Duration and time.Time types, this will validate
+the field value against another fields value either within a struct or passed in
+field. usage examples are for validation of a Start and End date:
 
 Example #1:
 
@@ -523,9 +629,9 @@ to the top level struct.
 
 Less Than Another Field
 
-Only valid for Numbers and time.Time types, this will validate the field value
-against another fields value either within a struct or passed in field.
-usage examples are for validation of a Start and End date:
+Only valid for Numbers, time.Duration and time.Time types, this will validate
+the field value against another fields value either within a struct or passed in
+field. usage examples are for validation of a Start and End date:
 
 Example #1:
 
@@ -546,9 +652,9 @@ to the top level struct.
 
 Less Than or Equal To Another Field
 
-Only valid for Numbers and time.Time types, this will validate the field value
-against another fields value either within a struct or passed in field.
-usage examples are for validation of a Start and End date:
+Only valid for Numbers, time.Duration and time.Time types, this will validate
+the field value against another fields value either within a struct or passed in
+field. usage examples are for validation of a Start and End date:
 
 Example #1:
 
@@ -684,6 +790,13 @@ This validates that a string value contains a valid hsla color
 
 	Usage: hsla
 
+E.164 Phone Number String
+
+This validates that a string value contains a valid E.164 Phone number
+https://en.wikipedia.org/wiki/E.164 (ex. +1123456789)
+
+	Usage: e164
+
 E-mail String
 
 This validates that a string value contains a valid email
@@ -766,8 +879,7 @@ Special thanks to Pieter Wuille for providng reference implementations.
 Ethereum Address
 
 This validates that a string value contains a valid ethereum address.
-The format of the string is checked to ensure it matches the standard Ethereum address format
-Full validation is blocked by https://github.com/golang/crypto/pull/28
+The format of the string is checked to ensure it matches the standard Ethereum address format.
 
 	Usage: eth_addr
 
@@ -1088,6 +1200,36 @@ Supplied format must match the official Go time format layout as documented in h
 
 	Usage: datetime=2006-01-02
 
+Iso3166-1 alpha-2
+
+This validates that a string value is a valid country code based on iso3166-1 alpha-2 standard.
+see: https://www.iso.org/iso-3166-country-codes.html
+
+	Usage: iso3166_1_alpha2
+
+Iso3166-1 alpha-3
+
+This validates that a string value is a valid country code based on iso3166-1 alpha-3 standard.
+see: https://www.iso.org/iso-3166-country-codes.html
+
+	Usage: iso3166_1_alpha3
+
+Iso3166-1 alpha-numeric
+
+This validates that a string value is a valid country code based on iso3166-1 alpha-numeric standard.
+see: https://www.iso.org/iso-3166-country-codes.html
+
+	Usage: iso3166_1_alpha3
+
+TimeZone
+
+This validates that a string value is a valid time zone based on the time zone database present on the system.
+Although empty value and Local value are allowed by time.LoadLocation golang function, they are not allowed by this validator.
+More information on https://golang.org/pkg/time/#LoadLocation
+
+	Usage: timezone
+  
+
 Alias Validators and Tags
 
 NOTE: When returning an error, the tag returned in "FieldError" will be
@@ -1099,6 +1241,8 @@ Here is a list of the current built in alias tags:
 
 	"iscolor"
 		alias is "hexcolor|rgb|rgba|hsl|hsla" (Usage: iscolor)
+	"country_code"
+		alias is "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric" (Usage: country_code)
 
 Validator notes:
 
diff --git a/errors.go b/errors.go
index 86420b9..63293cf 100644
--- a/errors.go
+++ b/errors.go
@@ -155,6 +155,9 @@ type FieldError interface {
 	// NOTE: if no registered translator can be found it returns the same as
 	// calling fe.Error()
 	Translate(ut ut.Translator) string
+
+	// Error returns the FieldError's message
+	Error() string
 }
 
 // compile time interface checks
@@ -254,8 +257,8 @@ func (fe *fieldError) Error() string {
 // Translate returns the FieldError's translated error
 // from the provided 'ut.Translator' and registered 'TranslationFunc'
 //
-// NOTE: is not registered translation can be found it returns the same
-// as calling fe.Error()
+// NOTE: if no registered translation can be found, it returns the original
+// untranslated error message.
 func (fe *fieldError) Translate(ut ut.Translator) string {
 
 	m, ok := fe.v.transTagFunc[ut]
diff --git a/go.mod b/go.mod
index 21316b3..d457100 100644
--- a/go.mod
+++ b/go.mod
@@ -7,4 +7,5 @@ require (
 	github.com/go-playground/locales v0.13.0
 	github.com/go-playground/universal-translator v0.17.0
 	github.com/leodido/go-urn v1.2.0
+	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
 )
diff --git a/go.sum b/go.sum
index dc7dec4..0152642 100644
--- a/go.sum
+++ b/go.sum
@@ -13,6 +13,13 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
diff --git a/regexes.go b/regexes.go
index 188d1ad..b741f4e 100644
--- a/regexes.go
+++ b/regexes.go
@@ -9,7 +9,7 @@ const (
 	alphaUnicodeNumericRegexString   = "^[\\p{L}\\p{N}]+$"
 	numericRegexString               = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
 	numberRegexString                = "^[0-9]+$"
-	hexadecimalRegexString           = "^[0-9a-fA-F]+$"
+	hexadecimalRegexString           = "^(0[xX])?[0-9a-fA-F]+$"
 	hexcolorRegexString              = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
 	rgbRegexString                   = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*\\)$"
 	rgbaRegexString                  = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
@@ -36,7 +36,7 @@ const (
 	latitudeRegexString              = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
 	longitudeRegexString             = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
 	sSNRegexString                   = `^[0-9]{3}[ -]?(0[1-9]|[1-9][0-9])[ -]?([1-9][0-9]{3}|[0-9][1-9][0-9]{2}|[0-9]{2}[1-9][0-9]|[0-9]{3}[1-9])$`
-  hostnameRegexStringRFC952        = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`                                                                      // https://tools.ietf.org/html/rfc952
+	hostnameRegexStringRFC952        = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`                                                                      // https://tools.ietf.org/html/rfc952
 	hostnameRegexStringRFC1123       = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*?$`                                 // accepts hostname starting with a digit https://tools.ietf.org/html/rfc1123
 	fqdnRegexStringRFC1123           = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62})(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*?(\.[a-zA-Z]{1}[a-zA-Z0-9]{0,62})\.?$` // same as hostnameRegexStringRFC1123 but must contain a non numerical TLD (possibly ending with '.')
 	btcAddressRegexString            = `^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$`                                                                                // bitcoin address
diff --git a/translations/pt/pt.go b/translations/pt/pt.go
new file mode 100644
index 0000000..9dbaf5f
--- /dev/null
+++ b/translations/pt/pt.go
@@ -0,0 +1,1405 @@
+package pt
+
+import (
+	"fmt"
+	"log"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/go-playground/locales"
+	ut "github.com/go-playground/universal-translator"
+	"github.com/go-playground/validator/v10"
+)
+
+// RegisterDefaultTranslations registers a set of default translations
+// for all built in tag's in validator; you may add your own as desired.
+func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) {
+
+	translations := []struct {
+		tag             string
+		translation     string
+		override        bool
+		customRegisFunc validator.RegisterTranslationsFunc
+		customTransFunc validator.TranslationFunc
+	}{
+		{
+			tag:         "required",
+			translation: "{0} é obrigatório",
+			override:    false,
+		},
+		{
+			tag: "len",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("len-string", "{0} deve ter {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("len-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("len-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("len-number", "{0} deve ser igual a {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("len-items", "{0} deve conter {1}", false); err != nil {
+					return
+				}
+				if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("len-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
+
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+
+				var digits uint64
+				var kind reflect.Kind
+
+				if idx := strings.Index(fe.Param(), "."); idx != -1 {
+					digits = uint64(len(fe.Param()[idx+1:]))
+				}
+
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
+				if err != nil {
+					goto END
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("len-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("len-items", fe.Field(), c)
+
+				default:
+					t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "min",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("min-string", "{0} deve ter pelo menos {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("min-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("min-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("min-number", "{0} deve ser {1} ou superior", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("min-items", "{0} deve conter pelo menos {1}", false); err != nil {
+					return
+				}
+				if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("min-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
+
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+
+				var digits uint64
+				var kind reflect.Kind
+
+				if idx := strings.Index(fe.Param(), "."); idx != -1 {
+					digits = uint64(len(fe.Param()[idx+1:]))
+				}
+
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
+				if err != nil {
+					goto END
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("min-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("min-items", fe.Field(), c)
+
+				default:
+					t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "max",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("max-string", "{0} deve ter no máximo {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("max-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("max-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("max-number", "{0} deve ser {1} ou menos", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("max-items", "{0} deve conter no máximo {1}", false); err != nil {
+					return
+				}
+				if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("max-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
+
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+
+				var digits uint64
+				var kind reflect.Kind
+
+				if idx := strings.Index(fe.Param(), "."); idx != -1 {
+					digits = uint64(len(fe.Param()[idx+1:]))
+				}
+
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
+				if err != nil {
+					goto END
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("max-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("max-items", fe.Field(), c)
+
+				default:
+					t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag:         "eq",
+			translation: "{0} não é igual a {1}",
+			override:    false,
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %#v", fe)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag:         "ne",
+			translation: "{0} não deve ser igual a {1}",
+			override:    false,
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %#v", fe)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "lt",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("lt-string", "{0} deve ter menos de {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lt-number", "{0} deve ser menor que {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lt-items", "{0} deve conter menos de {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lt-datetime", "{0} deve ser anterior à data / hora atual", false); err != nil {
+					return
+				}
+
+				return
+
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+				var f64 float64
+				var digits uint64
+				var kind reflect.Kind
+
+				fn := func() (err error) {
+
+					if idx := strings.Index(fe.Param(), "."); idx != -1 {
+						digits = uint64(len(fe.Param()[idx+1:]))
+					}
+
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lt-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lt-items", fe.Field(), c)
+
+				case reflect.Struct:
+					if fe.Type() != reflect.TypeOf(time.Time{}) {
+						err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag())
+						goto END
+					}
+
+					t, err = ut.T("lt-datetime", fe.Field())
+
+				default:
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "lte",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("lte-string", "{0} deve ter no máximo {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lte-number", "{0} deve ser menor ou igual a {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lte-items", "{0} deve conter no máximo {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("lte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("lte-datetime", "{0} deve ser anterior ou igual à data/hora atual", false); err != nil {
+					return
+				}
+
+				return
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+				var f64 float64
+				var digits uint64
+				var kind reflect.Kind
+
+				fn := func() (err error) {
+
+					if idx := strings.Index(fe.Param(), "."); idx != -1 {
+						digits = uint64(len(fe.Param()[idx+1:]))
+					}
+
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lte-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lte-items", fe.Field(), c)
+
+				case reflect.Struct:
+					if fe.Type() != reflect.TypeOf(time.Time{}) {
+						err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag())
+						goto END
+					}
+
+					t, err = ut.T("lte-datetime", fe.Field())
+
+				default:
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "gt",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("gt-string", "{0} deve conter mais de {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gt-number", "{0} deve ser maior que {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gt-items", "{0} deve conter mais de {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gt-datetime", "{0} deve ser posterior à data/hora atual", false); err != nil {
+					return
+				}
+
+				return
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+				var f64 float64
+				var digits uint64
+				var kind reflect.Kind
+
+				fn := func() (err error) {
+
+					if idx := strings.Index(fe.Param(), "."); idx != -1 {
+						digits = uint64(len(fe.Param()[idx+1:]))
+					}
+
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gt-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gt-items", fe.Field(), c)
+
+				case reflect.Struct:
+					if fe.Type() != reflect.TypeOf(time.Time{}) {
+						err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag())
+						goto END
+					}
+
+					t, err = ut.T("gt-datetime", fe.Field())
+
+				default:
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag: "gte",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+
+				if err = ut.Add("gte-string", "{0} deve ter pelo menos {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gte-number", "{0} deve ser maior ou igual a {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gte-items", "{0} deve conter pelo menos {1}", false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil {
+					return
+				}
+
+				if err = ut.AddCardinal("gte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				if err = ut.Add("gte-datetime", "{0} deve ser posterior ou igual à data/hora atual", false); err != nil {
+					return
+				}
+
+				return
+			},
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+
+				var err error
+				var t string
+				var f64 float64
+				var digits uint64
+				var kind reflect.Kind
+
+				fn := func() (err error) {
+
+					if idx := strings.Index(fe.Param(), "."); idx != -1 {
+						digits = uint64(len(fe.Param()[idx+1:]))
+					}
+
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
+				}
+
+				kind = fe.Kind()
+				if kind == reflect.Ptr {
+					kind = fe.Type().Elem().Kind()
+				}
+
+				switch kind {
+				case reflect.String:
+
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gte-string", fe.Field(), c)
+
+				case reflect.Slice, reflect.Map, reflect.Array:
+					var c string
+
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gte-items", fe.Field(), c)
+
+				case reflect.Struct:
+					if fe.Type() != reflect.TypeOf(time.Time{}) {
+						err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag())
+						goto END
+					}
+
+					t, err = ut.T("gte-datetime", fe.Field())
+
+				default:
+					err = fn()
+					if err != nil {
+						goto END
+					}
+
+					t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
+				if err != nil {
+					fmt.Printf("warning: error translating FieldError: %s", err)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag:         "eqfield",
+			translation: "{0} deve ser igual a {1}",
+			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
+			},
+		},
+		{
+			tag:         "eqcsfield",
+			translation: "{0} deve ser igual a {1}",
+			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
+			},
+		},
+		{
+			tag:         "necsfield",
+			translation: "{0} não deve ser igual a {1}",
+			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
+			},
+		},
+		{
+			tag:         "gtcsfield",
+			translation: "{0} deve ser maior que {1}",
+			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
+			},
+		},
+		{
+			tag:         "gtecsfield",
+			translation: "{0} deve ser maior ou igual que {1}",
+			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
+			},
+		},
+		{
+			tag:         "ltcsfield",
+			translation: "{0} deve ser menor que {1}",
+			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
+			},
+		},
+		{
+			tag:         "ltecsfield",
+			translation: "{0} deve ser menor ou igual que {1}",
+			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
+			},
+		},
+		{
+			tag:         "nefield",
+			translation: "{0} não deve ser igual a {1}",
+			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
+			},
+		},
+		{
+			tag:         "gtfield",
+			translation: "{0} deve ser maior que {1}",
+			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
+			},
+		},
+		{
+			tag:         "gtefield",
+			translation: "{0} deve ser maior ou igual que {1}",
+			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
+			},
+		},
+		{
+			tag:         "ltfield",
+			translation: "{0} deve ser menor que {1}",
+			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
+			},
+		},
+		{
+			tag:         "ltefield",
+			translation: "{0} deve ser menor ou igual que {1}",
+			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
+			},
+		},
+		{
+			tag:         "alpha",
+			translation: "{0} deve conter apenas caracteres alfabéticos",
+			override:    false,
+		},
+		{
+			tag:         "alphanum",
+			translation: "{0} deve conter apenas caracteres alfanuméricos",
+			override:    false,
+		},
+		{
+			tag:         "numeric",
+			translation: "{0} deve ser um valor numérico válido",
+			override:    false,
+		},
+		{
+			tag:         "number",
+			translation: "{0} deve ser um número válido",
+			override:    false,
+		},
+		{
+			tag:         "hexadecimal",
+			translation: "{0} deve ser um hexadecimal válido",
+			override:    false,
+		},
+		{
+			tag:         "hexcolor",
+			translation: "{0} deve ser uma cor HEX válida",
+			override:    false,
+		},
+		{
+			tag:         "rgb",
+			translation: "{0} deve ser uma cor RGB válida",
+			override:    false,
+		},
+		{
+			tag:         "rgba",
+			translation: "{0} deve ser uma cor RGBA válida",
+			override:    false,
+		},
+		{
+			tag:         "hsl",
+			translation: "{0} deve ser uma cor HSL válida",
+			override:    false,
+		},
+		{
+			tag:         "hsla",
+			translation: "{0} deve ser uma cor HSLA válida",
+			override:    false,
+		},
+		{
+			tag:         "e164",
+			translation: "{0} deve ser um número de telefone válido no formato E.164",
+			override:    false,
+		},
+		{
+			tag:         "email",
+			translation: "{0} deve ser um endereço de e-mail válido",
+			override:    false,
+		},
+		{
+			tag:         "url",
+			translation: "{0} deve ser um URL válido",
+			override:    false,
+		},
+		{
+			tag:         "uri",
+			translation: "{0} deve ser um URI válido",
+			override:    false,
+		},
+		{
+			tag:         "base64",
+			translation: "{0} deve ser uma string Base64 válida",
+			override:    false,
+		},
+		{
+			tag:         "contains",
+			translation: "{0} deve conter o texto '{1}'",
+			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
+			},
+		},
+		{
+			tag:         "containsany",
+			translation: "{0} deve conter pelo menos um dos seguintes caracteres '{1}'",
+			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
+			},
+		},
+		{
+			tag:         "excludes",
+			translation: "{0} não deve conter o texto '{1}'",
+			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
+			},
+		},
+		{
+			tag:         "excludesall",
+			translation: "{0} não deve conter os seguintes caracteres '{1}'",
+			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
+			},
+		},
+		{
+			tag:         "excludesrune",
+			translation: "{0} não pode conter o seguinte '{1}'",
+			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
+			},
+		},
+		{
+			tag:         "isbn",
+			translation: "{0} deve ser um número de ISBN válido",
+			override:    false,
+		},
+		{
+			tag:         "isbn10",
+			translation: "{0} deve ser um número ISBN-10 válido",
+			override:    false,
+		},
+		{
+			tag:         "isbn13",
+			translation: "{0} deve ser um número ISBN-13 válido",
+			override:    false,
+		},
+		{
+			tag:         "uuid",
+			translation: "{0} deve ser um UUID válido",
+			override:    false,
+		},
+		{
+			tag:         "uuid3",
+			translation: "{0} deve ser um UUID versão 3 válido",
+			override:    false,
+		},
+		{
+			tag:         "uuid4",
+			translation: "{0} deve ser um UUID versão 4 válido",
+			override:    false,
+		},
+		{
+			tag:         "uuid5",
+			translation: "{0} deve ser um UUID versão 5 válido",
+			override:    false,
+		},
+		{
+			tag:         "ascii",
+			translation: "{0} deve conter apenas caracteres ascii",
+			override:    false,
+		},
+		{
+			tag:         "printascii",
+			translation: "{0} deve conter apenas caracteres ascii imprimíveis",
+			override:    false,
+		},
+		{
+			tag:         "multibyte",
+			translation: "{0} deve conter caracteres multibyte",
+			override:    false,
+		},
+		{
+			tag:         "datauri",
+			translation: "{0} deve conter um Data URI válido",
+			override:    false,
+		},
+		{
+			tag:         "latitude",
+			translation: "{0} deve conter uma coordenada de latitude válida",
+			override:    false,
+		},
+		{
+			tag:         "longitude",
+			translation: "{0} deve conter uma coordenada de longitude válida",
+			override:    false,
+		},
+		{
+			tag:         "ssn",
+			translation: "{0} deve ser um número SSN válido",
+			override:    false,
+		},
+		{
+			tag:         "ipv4",
+			translation: "{0} deve ser um endereço IPv4 válido",
+			override:    false,
+		},
+		{
+			tag:         "ipv6",
+			translation: "{0} deve ser um endereço IPv6 válido",
+			override:    false,
+		},
+		{
+			tag:         "ip",
+			translation: "{0} deve ser um endereço IP válido",
+			override:    false,
+		},
+		{
+			tag:         "cidr",
+			translation: "{0} não respeita a notação CIDR",
+			override:    false,
+		},
+		{
+			tag:         "cidrv4",
+			translation: "{0} não respeita a notação CIDR para um endereço IPv4",
+			override:    false,
+		},
+		{
+			tag:         "cidrv6",
+			translation: "{0} não respeita a notação CIDR para um endereço IPv6",
+			override:    false,
+		},
+		{
+			tag:         "tcp_addr",
+			translation: "{0} deve ser um endereço TCP válido",
+			override:    false,
+		},
+		{
+			tag:         "tcp4_addr",
+			translation: "{0} deve ser um endereço TCP IPv4 válido",
+			override:    false,
+		},
+		{
+			tag:         "tcp6_addr",
+			translation: "{0} deve ser um endereço TCP IPv6 válido",
+			override:    false,
+		},
+		{
+			tag:         "udp_addr",
+			translation: "{0} deve ser um endereço UDP válido",
+			override:    false,
+		},
+		{
+			tag:         "udp4_addr",
+			translation: "{0} deve ser um endereço UDP IPv4 válido",
+			override:    false,
+		},
+		{
+			tag:         "udp6_addr",
+			translation: "{0} deve ser um endereço UDP IPv6 válido",
+			override:    false,
+		},
+		{
+			tag:         "ip_addr",
+			translation: "{0} deve ser um endereço IP resolvível",
+			override:    false,
+		},
+		{
+			tag:         "ip4_addr",
+			translation: "{0} deve ser um endereço IPv4 resolvível",
+			override:    false,
+		},
+		{
+			tag:         "ip6_addr",
+			translation: "{0} deve ser um endereço IPv6 resolvível",
+			override:    false,
+		},
+		{
+			tag:         "unix_addr",
+			translation: "{0} deve ser um endereço UNIX resolvível",
+			override:    false,
+		},
+		{
+			tag:         "mac",
+			translation: "{0} deve conter um endereço MAC válido",
+			override:    false,
+		},
+		{
+			tag:         "unique",
+			translation: "{0} deve conter valores únicos",
+			override:    false,
+		},
+		{
+			tag:         "iscolor",
+			translation: "{0} deve ser uma cor válida",
+			override:    false,
+		},
+		{
+			tag:         "oneof",
+			translation: "{0} deve ser um de [{1}]",
+			override:    false,
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				s, 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 s
+			},
+		},
+		{
+			tag:         "json",
+			translation: "{0} deve ser uma string json válida",
+			override:    false,
+		},
+		{
+			tag:         "lowercase",
+			translation: "{0} deve estar em minuscúlas",
+			override:    false,
+		},
+		{
+			tag:         "uppercase",
+			translation: "{0} deve estar em maiúsculas",
+			override:    false,
+		},
+		{
+			tag:         "datetime",
+			translation: "{0} não está no formato {1}",
+			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 {
+
+		if t.customTransFunc != nil && t.customRegisFunc != nil {
+
+			err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc)
+
+		} else if t.customTransFunc != nil && t.customRegisFunc == nil {
+
+			err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc)
+
+		} else if t.customTransFunc == nil && t.customRegisFunc != nil {
+
+			err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc)
+
+		} else {
+			err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc)
+		}
+
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc {
+
+	return func(ut ut.Translator) (err error) {
+
+		if err = ut.Add(tag, translation, override); err != nil {
+			return
+		}
+
+		return
+
+	}
+
+}
+
+func translateFunc(ut ut.Translator, fe validator.FieldError) string {
+
+	t, err := ut.T(fe.Tag(), fe.Field())
+	if err != nil {
+		log.Printf("warning: error translating FieldError: %#v", fe)
+		return fe.(error).Error()
+	}
+
+	return t
+}
diff --git a/util.go b/util.go
index 0d3a181..6e568f8 100644
--- a/util.go
+++ b/util.go
@@ -4,6 +4,7 @@ import (
 	"reflect"
 	"strconv"
 	"strings"
+	"time"
 )
 
 // extractTypeInternal gets the actual underlying type of field value.
@@ -229,6 +230,26 @@ func asInt(param string) int64 {
 	return i
 }
 
+// asIntFromTimeDuration parses param as time.Duration and returns it as int64
+// or panics on error.
+func asIntFromTimeDuration(param string) int64 {
+	d, err := time.ParseDuration(param)
+	panicIf(err)
+
+	return int64(d)
+}
+
+// asIntFromType calls the proper function to parse param as int64,
+// given a field's Type t.
+func asIntFromType(t reflect.Type, param string) int64 {
+	switch t {
+	case timeDurationType:
+		return asIntFromTimeDuration(param)
+	default:
+		return asInt(param)
+	}
+}
+
 // asUint returns the parameter as a uint64
 // or panics if it can't convert
 func asUint(param string) uint64 {
diff --git a/validator.go b/validator.go
index 342e72e..f097f39 100644
--- a/validator.go
+++ b/validator.go
@@ -249,7 +249,7 @@ OUTER:
 			v.cf = cf
 			v.ct = ct
 
-			if !v.fldIsPointer && !hasValue(v) {
+			if !hasValue(v) {
 				return
 			}
 
diff --git a/validator_instance.go b/validator_instance.go
index 4a89d40..fe6a487 100644
--- a/validator_instance.go
+++ b/validator_instance.go
@@ -27,6 +27,8 @@ const (
 	requiredWithoutTag    = "required_without"
 	requiredWithTag       = "required_with"
 	requiredWithAllTag    = "required_with_all"
+	requiredIfTag         = "required_if"
+	requiredUnlessTag     = "required_unless"
 	skipValidationTag     = "-"
 	diveTag               = "dive"
 	keysTag               = "keys"
@@ -41,7 +43,9 @@ const (
 )
 
 var (
-	timeType      = reflect.TypeOf(time.Time{})
+	timeDurationType = reflect.TypeOf(time.Duration(0))
+	timeType         = reflect.TypeOf(time.Time{})
+
 	defaultCField = &cField{namesEqual: true}
 )
 
@@ -107,7 +111,7 @@ func New() *Validate {
 
 		switch k {
 		// these require that even if the value is nil that the validation should run, omitempty still overrides this behaviour
-		case requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag:
+		case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag:
 			_ = v.registerValidation(k, wrapFunc(val), true, true)
 		default:
 			// no need to error check here, baked in will always be valid


Test patch:
diff --git a/translations/pt/pt_test.go b/translations/pt/pt_test.go
new file mode 100644
index 0000000..ceec15f
--- /dev/null
+++ b/translations/pt/pt_test.go
@@ -0,0 +1,677 @@
+package pt
+
+import (
+	"testing"
+	"time"
+
+	. "github.com/go-playground/assert/v2"
+	"github.com/go-playground/locales/pt"
+	ut "github.com/go-playground/universal-translator"
+
+	"github.com/go-playground/validator/v10"
+)
+
+func TestTranslations(t *testing.T) {
+
+	pt := pt.New()
+	uni := ut.New(pt, pt)
+	trans, _ := uni.GetTranslator("pt")
+
+	validate := validator.New()
+
+	err := RegisterDefaultTranslations(validate, trans)
+	Equal(t, err, nil)
+
+	type Inner struct {
+		EqCSFieldString  string
+		NeCSFieldString  string
+		GtCSFieldString  string
+		GteCSFieldString string
+		LtCSFieldString  string
+		LteCSFieldString string
+	}
+
+	type Test struct {
+		Inner             Inner
+		RequiredString    string            `validate:"required"`
+		RequiredNumber    int               `validate:"required"`
+		RequiredMultiple  []string          `validate:"required"`
+		LenString         string            `validate:"len=1"`
+		LenNumber         float64           `validate:"len=1113.00"`
+		LenMultiple       []string          `validate:"len=7"`
+		MinString         string            `validate:"min=1"`
+		MinNumber         float64           `validate:"min=1113.00"`
+		MinMultiple       []string          `validate:"min=7"`
+		MaxString         string            `validate:"max=3"`
+		MaxNumber         float64           `validate:"max=1113.00"`
+		MaxMultiple       []string          `validate:"max=7"`
+		EqString          string            `validate:"eq=3"`
+		EqNumber          float64           `validate:"eq=2.33"`
+		EqMultiple        []string          `validate:"eq=7"`
+		NeString          string            `validate:"ne="`
+		NeNumber          float64           `validate:"ne=0.00"`
+		NeMultiple        []string          `validate:"ne=0"`
+		LtString          string            `validate:"lt=3"`
+		LtNumber          float64           `validate:"lt=5.56"`
+		LtMultiple        []string          `validate:"lt=2"`
+		LtTime            time.Time         `validate:"lt"`
+		LteString         string            `validate:"lte=3"`
+		LteNumber         float64           `validate:"lte=5.56"`
+		LteMultiple       []string          `validate:"lte=2"`
+		LteTime           time.Time         `validate:"lte"`
+		GtString          string            `validate:"gt=3"`
+		GtNumber          float64           `validate:"gt=5.56"`
+		GtMultiple        []string          `validate:"gt=2"`
+		GtTime            time.Time         `validate:"gt"`
+		GteString         string            `validate:"gte=3"`
+		GteNumber         float64           `validate:"gte=5.56"`
+		GteMultiple       []string          `validate:"gte=2"`
+		GteTime           time.Time         `validate:"gte"`
+		EqFieldString     string            `validate:"eqfield=MaxString"`
+		EqCSFieldString   string            `validate:"eqcsfield=Inner.EqCSFieldString"`
+		NeCSFieldString   string            `validate:"necsfield=Inner.NeCSFieldString"`
+		GtCSFieldString   string            `validate:"gtcsfield=Inner.GtCSFieldString"`
+		GteCSFieldString  string            `validate:"gtecsfield=Inner.GteCSFieldString"`
+		LtCSFieldString   string            `validate:"ltcsfield=Inner.LtCSFieldString"`
+		LteCSFieldString  string            `validate:"ltecsfield=Inner.LteCSFieldString"`
+		NeFieldString     string            `validate:"nefield=EqFieldString"`
+		GtFieldString     string            `validate:"gtfield=MaxString"`
+		GteFieldString    string            `validate:"gtefield=MaxString"`
+		LtFieldString     string            `validate:"ltfield=MaxString"`
+		LteFieldString    string            `validate:"ltefield=MaxString"`
+		AlphaString       string            `validate:"alpha"`
+		AlphanumString    string            `validate:"alphanum"`
+		NumericString     string            `validate:"numeric"`
+		NumberString      string            `validate:"number"`
+		HexadecimalString string            `validate:"hexadecimal"`
+		HexColorString    string            `validate:"hexcolor"`
+		RGBColorString    string            `validate:"rgb"`
+		RGBAColorString   string            `validate:"rgba"`
+		HSLColorString    string            `validate:"hsl"`
+		HSLAColorString   string            `validate:"hsla"`
+		Email             string            `validate:"email"`
+		URL               string            `validate:"url"`
+		URI               string            `validate:"uri"`
+		Base64            string            `validate:"base64"`
+		Contains          string            `validate:"contains=purpose"`
+		ContainsAny       string            `validate:"containsany=!@#$"`
+		Excludes          string            `validate:"excludes=text"`
+		ExcludesAll       string            `validate:"excludesall=!@#$"`
+		ExcludesRune      string            `validate:"excludesrune=☻"`
+		ISBN              string            `validate:"isbn"`
+		ISBN10            string            `validate:"isbn10"`
+		ISBN13            string            `validate:"isbn13"`
+		UUID              string            `validate:"uuid"`
+		UUID3             string            `validate:"uuid3"`
+		UUID4             string            `validate:"uuid4"`
+		UUID5             string            `validate:"uuid5"`
+		ASCII             string            `validate:"ascii"`
+		PrintableASCII    string            `validate:"printascii"`
+		MultiByte         string            `validate:"multibyte"`
+		DataURI           string            `validate:"datauri"`
+		Latitude          string            `validate:"latitude"`
+		Longitude         string            `validate:"longitude"`
+		SSN               string            `validate:"ssn"`
+		IP                string            `validate:"ip"`
+		IPv4              string            `validate:"ipv4"`
+		IPv6              string            `validate:"ipv6"`
+		CIDR              string            `validate:"cidr"`
+		CIDRv4            string            `validate:"cidrv4"`
+		CIDRv6            string            `validate:"cidrv6"`
+		TCPAddr           string            `validate:"tcp_addr"`
+		TCPAddrv4         string            `validate:"tcp4_addr"`
+		TCPAddrv6         string            `validate:"tcp6_addr"`
+		UDPAddr           string            `validate:"udp_addr"`
+		UDPAddrv4         string            `validate:"udp4_addr"`
+		UDPAddrv6         string            `validate:"udp6_addr"`
+		IPAddr            string            `validate:"ip_addr"`
+		IPAddrv4          string            `validate:"ip4_addr"`
+		IPAddrv6          string            `validate:"ip6_addr"`
+		UinxAddr          string            `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
+		MAC               string            `validate:"mac"`
+		IsColor           string            `validate:"iscolor"`
+		StrPtrMinLen      *string           `validate:"min=10"`
+		StrPtrMaxLen      *string           `validate:"max=1"`
+		StrPtrLen         *string           `validate:"len=2"`
+		StrPtrLt          *string           `validate:"lt=1"`
+		StrPtrLte         *string           `validate:"lte=1"`
+		StrPtrGt          *string           `validate:"gt=10"`
+		StrPtrGte         *string           `validate:"gte=10"`
+		OneOfString       string            `validate:"oneof=red green"`
+		OneOfInt          int               `validate:"oneof=5 63"`
+		UniqueSlice       []string          `validate:"unique"`
+		UniqueArray       [3]string         `validate:"unique"`
+		UniqueMap         map[string]string `validate:"unique"`
+		JSONString        string            `validate:"json"`
+		LowercaseString   string            `validate:"lowercase"`
+		UppercaseString   string            `validate:"uppercase"`
+		Datetime          string            `validate:"datetime=2006-01-02"`
+	}
+
+	var test Test
+
+	test.Inner.EqCSFieldString = "1234"
+	test.Inner.GtCSFieldString = "1234"
+	test.Inner.GteCSFieldString = "1234"
+
+	test.MaxString = "1234"
+	test.MaxNumber = 2000
+	test.MaxMultiple = make([]string, 9)
+
+	test.LtString = "1234"
+	test.LtNumber = 6
+	test.LtMultiple = make([]string, 3)
+	test.LtTime = time.Now().Add(time.Hour * 24)
+
+	test.LteString = "1234"
+	test.LteNumber = 6
+	test.LteMultiple = make([]string, 3)
+	test.LteTime = time.Now().Add(time.Hour * 24)
+
+	test.LtFieldString = "12345"
+	test.LteFieldString = "12345"
+
+	test.LtCSFieldString = "1234"
+	test.LteCSFieldString = "1234"
+
+	test.AlphaString = "abc3"
+	test.AlphanumString = "abc3!"
+	test.NumericString = "12E.00"
+	test.NumberString = "12E"
+
+	test.Excludes = "this is some test text"
+	test.ExcludesAll = "This is Great!"
+	test.ExcludesRune = "Love it ☻"
+
+	test.ASCII = "ｶﾀｶﾅ"
+	test.PrintableASCII = "ｶﾀｶﾅ"
+
+	test.MultiByte = "1234feerf"
+
+	test.LowercaseString = "ABCDEFG"
+	test.UppercaseString = "abcdefg"
+
+	s := "toolong"
+	test.StrPtrMaxLen = &s
+	test.StrPtrLen = &s
+
+	test.UniqueSlice = []string{"1234", "1234"}
+	test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
+	test.Datetime = "2008-Feb-01"
+
+	err = validate.Struct(test)
+	NotEqual(t, err, nil)
+
+	errs, ok := err.(validator.ValidationErrors)
+	Equal(t, ok, true)
+
+	tests := []struct {
+		ns       string
+		expected string
+	}{
+		{
+			ns:       "Test.IsColor",
+			expected: "IsColor deve ser uma cor válida",
+		},
+		{
+			ns:       "Test.MAC",
+			expected: "MAC deve conter um endereço MAC válido",
+		},
+		{
+			ns:       "Test.IPAddr",
+			expected: "IPAddr deve ser um endereço IP resolvível",
+		},
+		{
+			ns:       "Test.IPAddrv4",
+			expected: "IPAddrv4 deve ser um endereço IPv4 resolvível",
+		},
+		{
+			ns:       "Test.IPAddrv6",
+			expected: "IPAddrv6 deve ser um endereço IPv6 resolvível",
+		},
+		{
+			ns:       "Test.UDPAddr",
+			expected: "UDPAddr deve ser um endereço UDP válido",
+		},
+		{
+			ns:       "Test.UDPAddrv4",
+			expected: "UDPAddrv4 deve ser um endereço UDP IPv4 válido",
+		},
+		{
+			ns:       "Test.UDPAddrv6",
+			expected: "UDPAddrv6 deve ser um endereço UDP IPv6 válido",
+		},
+		{
+			ns:       "Test.TCPAddr",
+			expected: "TCPAddr deve ser um endereço TCP válido",
+		},
+		{
+			ns:       "Test.TCPAddrv4",
+			expected: "TCPAddrv4 deve ser um endereço TCP IPv4 válido",
+		},
+		{
+			ns:       "Test.TCPAddrv6",
+			expected: "TCPAddrv6 deve ser um endereço TCP IPv6 válido",
+		},
+		{
+			ns:       "Test.CIDR",
+			expected: "CIDR não respeita a notação CIDR",
+		},
+		{
+			ns:       "Test.CIDRv4",
+			expected: "CIDRv4 não respeita a notação CIDR para um endereço IPv4",
+		},
+		{
+			ns:       "Test.CIDRv6",
+			expected: "CIDRv6 não respeita a notação CIDR para um endereço IPv6",
+		},
+		{
+			ns:       "Test.SSN",
+			expected: "SSN deve ser um número SSN válido",
+		},
+		{
+			ns:       "Test.IP",
+			expected: "IP deve ser um endereço IP válido",
+		},
+		{
+			ns:       "Test.IPv4",
+			expected: "IPv4 deve ser um endereço IPv4 válido",
+		},
+		{
+			ns:       "Test.IPv6",
+			expected: "IPv6 deve ser um endereço IPv6 válido",
+		},
+		{
+			ns:       "Test.DataURI",
+			expected: "DataURI deve conter um Data URI válido",
+		},
+		{
+			ns:       "Test.Latitude",
+			expected: "Latitude deve conter uma coordenada de latitude válida",
+		},
+		{
+			ns:       "Test.Longitude",
+			expected: "Longitude deve conter uma coordenada de longitude válida",
+		},
+		{
+			ns:       "Test.MultiByte",
+			expected: "MultiByte deve conter caracteres multibyte",
+		},
+		{
+			ns:       "Test.ASCII",
+			expected: "ASCII deve conter apenas caracteres ascii",
+		},
+		{
+			ns:       "Test.PrintableASCII",
+			expected: "PrintableASCII deve conter apenas caracteres ascii imprimíveis",
+		},
+		{
+			ns:       "Test.UUID",
+			expected: "UUID deve ser um UUID válido",
+		},
+		{
+			ns:       "Test.UUID3",
+			expected: "UUID3 deve ser um UUID versão 3 válido",
+		},
+		{
+			ns:       "Test.UUID4",
+			expected: "UUID4 deve ser um UUID versão 4 válido",
+		},
+		{
+			ns:       "Test.UUID5",
+			expected: "UUID5 deve ser um UUID versão 5 válido",
+		},
+		{
+			ns:       "Test.ISBN",
+			expected: "ISBN deve ser um número de ISBN válido",
+		},
+		{
+			ns:       "Test.ISBN10",
+			expected: "ISBN10 deve ser um número ISBN-10 válido",
+		},
+		{
+			ns:       "Test.ISBN13",
+			expected: "ISBN13 deve ser um número ISBN-13 válido",
+		},
+		{
+			ns:       "Test.Excludes",
+			expected: "Excludes não deve conter o texto 'text'",
+		},
+		{
+			ns:       "Test.ExcludesAll",
+			expected: "ExcludesAll não deve conter os seguintes caracteres '!@#$'",
+		},
+		{
+			ns:       "Test.ExcludesRune",
+			expected: "ExcludesRune não pode conter o seguinte '☻'",
+		},
+		{
+			ns:       "Test.ContainsAny",
+			expected: "ContainsAny deve conter pelo menos um dos seguintes caracteres '!@#$'",
+		},
+		{
+			ns:       "Test.Contains",
+			expected: "Contains deve conter o texto 'purpose'",
+		},
+		{
+			ns:       "Test.Base64",
+			expected: "Base64 deve ser uma string Base64 válida",
+		},
+		{
+			ns:       "Test.Email",
+			expected: "Email deve ser um endereço de e-mail válido",
+		},
+		{
+			ns:       "Test.URL",
+			expected: "URL deve ser um URL válido",
+		},
+		{
+			ns:       "Test.URI",
+			expected: "URI deve ser um URI válido",
+		},
+		{
+			ns:       "Test.RGBColorString",
+			expected: "RGBColorString deve ser uma cor RGB válida",
+		},
+		{
+			ns:       "Test.RGBAColorString",
+			expected: "RGBAColorString deve ser uma cor RGBA válida",
+		},
+		{
+			ns:       "Test.HSLColorString",
+			expected: "HSLColorString deve ser uma cor HSL válida",
+		},
+		{
+			ns:       "Test.HSLAColorString",
+			expected: "HSLAColorString deve ser uma cor HSLA válida",
+		},
+		{
+			ns:       "Test.HexadecimalString",
+			expected: "HexadecimalString deve ser um hexadecimal válido",
+		},
+		{
+			ns:       "Test.HexColorString",
+			expected: "HexColorString deve ser uma cor HEX válida",
+		},
+		{
+			ns:       "Test.NumberString",
+			expected: "NumberString deve ser um número válido",
+		},
+		{
+			ns:       "Test.NumericString",
+			expected: "NumericString deve ser um valor numérico válido",
+		},
+		{
+			ns:       "Test.AlphanumString",
+			expected: "AlphanumString deve conter apenas caracteres alfanuméricos",
+		},
+		{
+			ns:       "Test.AlphaString",
+			expected: "AlphaString deve conter apenas caracteres alfabéticos",
+		},
+		{
+			ns:       "Test.LtFieldString",
+			expected: "LtFieldString deve ser menor que MaxString",
+		},
+		{
+			ns:       "Test.LteFieldString",
+			expected: "LteFieldString deve ser menor ou igual que MaxString",
+		},
+		{
+			ns:       "Test.GtFieldString",
+			expected: "GtFieldString deve ser maior que MaxString",
+		},
+		{
+			ns:       "Test.GteFieldString",
+			expected: "GteFieldString deve ser maior ou igual que MaxString",
+		},
+		{
+			ns:       "Test.NeFieldString",
+			expected: "NeFieldString não deve ser igual a EqFieldString",
+		},
+		{
+			ns:       "Test.LtCSFieldString",
+			expected: "LtCSFieldString deve ser menor que Inner.LtCSFieldString",
+		},
+		{
+			ns:       "Test.LteCSFieldString",
+			expected: "LteCSFieldString deve ser menor ou igual que Inner.LteCSFieldString",
+		},
+		{
+			ns:       "Test.GtCSFieldString",
+			expected: "GtCSFieldString deve ser maior que Inner.GtCSFieldString",
+		},
+		{
+			ns:       "Test.GteCSFieldString",
+			expected: "GteCSFieldString deve ser maior ou igual que Inner.GteCSFieldString",
+		},
+		{
+			ns:       "Test.NeCSFieldString",
+			expected: "NeCSFieldString não deve ser igual a Inner.NeCSFieldString",
+		},
+		{
+			ns:       "Test.EqCSFieldString",
+			expected: "EqCSFieldString deve ser igual a Inner.EqCSFieldString",
+		},
+		{
+			ns:       "Test.EqFieldString",
+			expected: "EqFieldString deve ser igual a MaxString",
+		},
+		{
+			ns:       "Test.GteString",
+			expected: "GteString deve ter pelo menos 3 caracteres",
+		},
+		{
+			ns:       "Test.GteNumber",
+			expected: "GteNumber deve ser maior ou igual a 5,56",
+		},
+		{
+			ns:       "Test.GteMultiple",
+			expected: "GteMultiple deve conter pelo menos 2 items",
+		},
+		{
+			ns:       "Test.GteTime",
+			expected: "GteTime deve ser posterior ou igual à data/hora atual",
+		},
+		{
+			ns:       "Test.GtString",
+			expected: "GtString deve conter mais de 3 caracteres",
+		},
+		{
+			ns:       "Test.GtNumber",
+			expected: "GtNumber deve ser maior que 5,56",
+		},
+		{
+			ns:       "Test.GtMultiple",
+			expected: "GtMultiple deve conter mais de 2 items",
+		},
+		{
+			ns:       "Test.GtTime",
+			expected: "GtTime deve ser posterior à data/hora atual",
+		},
+		{
+			ns:       "Test.LteString",
+			expected: "LteString deve ter no máximo 3 caracteres",
+		},
+		{
+			ns:       "Test.LteNumber",
+			expected: "LteNumber deve ser menor ou igual a 5,56",
+		},
+		{
+			ns:       "Test.LteMultiple",
+			expected: "LteMultiple deve conter no máximo 2 items",
+		},
+		{
+			ns:       "Test.LteTime",
+			expected: "LteTime deve ser anterior ou igual à data/hora atual",
+		},
+		{
+			ns:       "Test.LtString",
+			expected: "LtString deve ter menos de 3 caracteres",
+		},
+		{
+			ns:       "Test.LtNumber",
+			expected: "LtNumber deve ser menor que 5,56",
+		},
+		{
+			ns:       "Test.LtMultiple",
+			expected: "LtMultiple deve conter menos de 2 items",
+		},
+		{
+			ns:       "Test.LtTime",
+			expected: "LtTime deve ser anterior à data / hora atual",
+		},
+		{
+			ns:       "Test.NeString",
+			expected: "NeString não deve ser igual a ",
+		},
+		{
+			ns:       "Test.NeNumber",
+			expected: "NeNumber não deve ser igual a 0.00",
+		},
+		{
+			ns:       "Test.NeMultiple",
+			expected: "NeMultiple não deve ser igual a 0",
+		},
+		{
+			ns:       "Test.EqString",
+			expected: "EqString não é igual a 3",
+		},
+		{
+			ns:       "Test.EqNumber",
+			expected: "EqNumber não é igual a 2.33",
+		},
+		{
+			ns:       "Test.EqMultiple",
+			expected: "EqMultiple não é igual a 7",
+		},
+		{
+			ns:       "Test.MaxString",
+			expected: "MaxString deve ter no máximo 3 caracteres",
+		},
+		{
+			ns:       "Test.MaxNumber",
+			expected: "MaxNumber deve ser 1.113,00 ou menos",
+		},
+		{
+			ns:       "Test.MaxMultiple",
+			expected: "MaxMultiple deve conter no máximo 7 items",
+		},
+		{
+			ns:       "Test.MinString",
+			expected: "MinString deve ter pelo menos 1 caractere",
+		},
+		{
+			ns:       "Test.MinNumber",
+			expected: "MinNumber deve ser 1.113,00 ou superior",
+		},
+		{
+			ns:       "Test.MinMultiple",
+			expected: "MinMultiple deve conter pelo menos 7 items",
+		},
+		{
+			ns:       "Test.LenString",
+			expected: "LenString deve ter 1 caractere",
+		},
+		{
+			ns:       "Test.LenNumber",
+			expected: "LenNumber deve ser igual a 1.113,00",
+		},
+		{
+			ns:       "Test.LenMultiple",
+			expected: "LenMultiple deve conter 7 items",
+		},
+		{
+			ns:       "Test.RequiredString",
+			expected: "RequiredString é obrigatório",
+		},
+		{
+			ns:       "Test.RequiredNumber",
+			expected: "RequiredNumber é obrigatório",
+		},
+		{
+			ns:       "Test.RequiredMultiple",
+			expected: "RequiredMultiple é obrigatório",
+		},
+		{
+			ns:       "Test.StrPtrMinLen",
+			expected: "StrPtrMinLen deve ter pelo menos 10 caracteres",
+		},
+		{
+			ns:       "Test.StrPtrMaxLen",
+			expected: "StrPtrMaxLen deve ter no máximo 1 caractere",
+		},
+		{
+			ns:       "Test.StrPtrLen",
+			expected: "StrPtrLen deve ter 2 caracteres",
+		},
+		{
+			ns:       "Test.StrPtrLt",
+			expected: "StrPtrLt deve ter menos de 1 caractere",
+		},
+		{
+			ns:       "Test.StrPtrLte",
+			expected: "StrPtrLte deve ter no máximo 1 caractere",
+		},
+		{
+			ns:       "Test.StrPtrGt",
+			expected: "StrPtrGt deve conter mais de 10 caracteres",
+		},
+		{
+			ns:       "Test.StrPtrGte",
+			expected: "StrPtrGte deve ter pelo menos 10 caracteres",
+		},
+		{
+			ns:       "Test.OneOfString",
+			expected: "OneOfString deve ser um de [red green]",
+		},
+		{
+			ns:       "Test.OneOfInt",
+			expected: "OneOfInt deve ser um de [5 63]",
+		},
+		{
+			ns:       "Test.UniqueSlice",
+			expected: "UniqueSlice deve conter valores únicos",
+		},
+		{
+			ns:       "Test.UniqueArray",
+			expected: "UniqueArray deve conter valores únicos",
+		},
+		{
+			ns:       "Test.UniqueMap",
+			expected: "UniqueMap deve conter valores únicos",
+		},
+		{
+			ns:       "Test.JSONString",
+			expected: "JSONString deve ser uma string json válida",
+		},
+		{
+			ns:       "Test.LowercaseString",
+			expected: "LowercaseString deve estar em minuscúlas",
+		},
+		{
+			ns:       "Test.UppercaseString",
+			expected: "UppercaseString deve estar em maiúsculas",
+		},
+		{
+			ns:       "Test.Datetime",
+			expected: "Datetime não está no formato 2006-01-02",
+		},
+	}
+
+	for _, tt := range tests {
+
+		var fe validator.FieldError
+
+		for _, e := range errs {
+			if tt.ns == e.Namespace() {
+				fe = e
+				break
+			}
+		}
+
+		NotEqual(t, fe, nil)
+		Equal(t, tt.expected, fe.Translate(trans))
+	}
+
+}
diff --git a/validator_test.go b/validator_test.go
index e76a3cd..a918bce 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -346,6 +346,18 @@ func StructLevelInvalidError(sl StructLevel) {
 	}
 }
 
+func stringPtr(v string) *string {
+	return &v
+}
+
+func intPtr(v int) *int {
+	return &v
+}
+
+func float64Ptr(v float64) *float64 {
+	return &v
+}
+
 func TestStructLevelInvalidError(t *testing.T) {
 
 	validate := New()
@@ -940,6 +952,8 @@ func TestStructPartial(t *testing.T) {
 }
 
 func TestCrossStructLteFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -982,8 +996,7 @@ func TestCrossStructLteFieldValidation(t *testing.T) {
 		Array:     []string{"val1"},
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	test.CreatedAt = &then
@@ -1046,9 +1059,68 @@ func TestCrossStructLteFieldValidation(t *testing.T) {
 	errs = validate.Struct(tst)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltecsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "ltecsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltecsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltecsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltecsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"ltecsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltecsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,ltecsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{-time.Minute}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossStructLtFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -1091,8 +1163,7 @@ func TestCrossStructLtFieldValidation(t *testing.T) {
 		Array:     []string{"val1"},
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	test.CreatedAt = &then
@@ -1142,9 +1213,70 @@ func TestCrossStructLtFieldValidation(t *testing.T) {
 	errs = validate.Struct(tst)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltcsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "ltcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltcsfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltcsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltcsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"ltcsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield")
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,ltcsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{-time.Minute}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossStructGteFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -1187,8 +1319,7 @@ func TestCrossStructGteFieldValidation(t *testing.T) {
 		Array:     []string{"val1", "val2", "val3"},
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	test.CreatedAt = &then
@@ -1250,9 +1381,68 @@ func TestCrossStructGteFieldValidation(t *testing.T) {
 	errs = validate.Struct(tst)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtecsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "gtecsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtecsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtecsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtecsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"gtecsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtecsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,gtecsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossStructGtFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -1295,8 +1485,7 @@ func TestCrossStructGtFieldValidation(t *testing.T) {
 		Array:     []string{"val1", "val2", "val3"},
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	test.CreatedAt = &then
@@ -1346,9 +1535,70 @@ func TestCrossStructGtFieldValidation(t *testing.T) {
 	errs = validate.Struct(tst)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtcsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "gtcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtcsfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtcsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtcsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"gtcsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield")
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,gtcsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossStructNeFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -1371,8 +1621,7 @@ func TestCrossStructNeFieldValidation(t *testing.T) {
 		CreatedAt: &now,
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	test.CreatedAt = &then
@@ -1454,9 +1703,68 @@ func TestCrossStructNeFieldValidation(t *testing.T) {
 	errs = validate.VarWithValue(nil, 1, "necsfield")
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "", "", "", "", "necsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "necsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "necsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "necsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "necsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,necsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"necsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "necsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,necsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{time.Duration(0)}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossStructEqFieldValidation(t *testing.T) {
+	var errs error
+	validate := New()
 
 	type Inner struct {
 		CreatedAt *time.Time
@@ -1478,8 +1786,7 @@ func TestCrossStructEqFieldValidation(t *testing.T) {
 		CreatedAt: &now,
 	}
 
-	validate := New()
-	errs := validate.Struct(test)
+	errs = validate.Struct(test)
 	Equal(t, errs, nil)
 
 	newTime := time.Now().UTC()
@@ -1559,6 +1866,65 @@ func TestCrossStructEqFieldValidation(t *testing.T) {
 	errs = validate.VarWithValue(nil, 1, "eqcsfield")
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "", "", "", "", "eqcsfield")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "eqcsfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eqcsfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqcsfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eqcsfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqcsfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct and an inner struct with time.Duration type fields.
+
+	type TimeDurationInner struct {
+		Duration time.Duration
+	}
+	var timeDurationInner *TimeDurationInner
+
+	type TimeDurationTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"eqcsfield=Inner.Duration"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationInner = &TimeDurationInner{time.Hour - time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield")
+
+	timeDurationInner = &TimeDurationInner{time.Hour + time.Minute}
+	timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield")
+
+	type TimeDurationOmitemptyTest struct {
+		Inner    *TimeDurationInner
+		Duration time.Duration `validate:"omitempty,eqcsfield=Inner.Duration"`
+	}
+	var timeDurationOmitemptyTest *TimeDurationOmitemptyTest
+
+	timeDurationInner = &TimeDurationInner{time.Hour}
+	timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestCrossNamespaceFieldValidation(t *testing.T) {
@@ -4182,7 +4548,7 @@ func TestContainsValidation(t *testing.T) {
 }
 
 func TestIsNeFieldValidation(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	var j uint64
@@ -4204,7 +4570,7 @@ func TestIsNeFieldValidation(t *testing.T) {
 	arr3 := []string{"test"}
 	now2 := now
 
-	errs := validate.VarWithValue(s, s2, "nefield")
+	errs = validate.VarWithValue(s, s2, "nefield")
 	Equal(t, errs, nil)
 
 	errs = validate.VarWithValue(i2, i, "nefield")
@@ -4287,10 +4653,57 @@ func TestIsNeFieldValidation(t *testing.T) {
 
 	errs = validate.Struct(tst)
 	Equal(t, errs, nil)
+
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "nefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "nefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "nefield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "nefield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,nefield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"nefield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "nefield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,nefield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestIsNeValidation(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	var j uint64
@@ -4302,7 +4715,7 @@ func TestIsNeValidation(t *testing.T) {
 	arr := []string{"test"}
 	now := time.Now().UTC()
 
-	errs := validate.Var(s, "ne=abcd")
+	errs = validate.Var(s, "ne=abcd")
 	Equal(t, errs, nil)
 
 	errs = validate.Var(i, "ne=1")
@@ -4322,10 +4735,55 @@ func TestIsNeValidation(t *testing.T) {
 	AssertError(t, errs, "", "", "", "", "ne")
 
 	PanicMatches(t, func() { _ = validate.Var(now, "ne=now") }, "Bad field type time.Time")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour-time.Minute, "ne=1h")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+time.Minute, "ne=1h")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour, "ne=1h")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ne")
+
+	errs = validate.Var(time.Duration(0), "omitempty,ne=0")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"ne=1h"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ne")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,ne=0"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestIsEqFieldValidation(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	var j uint64
@@ -4347,7 +4805,7 @@ func TestIsEqFieldValidation(t *testing.T) {
 	arr3 := []string{"test", "test2"}
 	now2 := now
 
-	errs := validate.VarWithValue(s, s2, "eqfield")
+	errs = validate.VarWithValue(s, s2, "eqfield")
 	Equal(t, errs, nil)
 
 	errs = validate.VarWithValue(i2, i, "eqfield")
@@ -4441,26 +4899,75 @@ func TestIsEqFieldValidation(t *testing.T) {
 	errs = validate.Struct(test)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield")
-}
-
-func TestIsEqValidation(t *testing.T) {
 
-	validate := New()
+	// Tests for time.Duration type.
 
-	var j uint64
-	var k float64
-	s := "abcd"
-	i := 1
-	j = 1
-	k = 1.543
-	arr := []string{"test"}
-	now := time.Now().UTC()
+	// -- Validations for variables of time.Duration type.
 
-	errs := validate.Var(s, "eq=abcd")
+	errs = validate.VarWithValue(time.Hour, time.Hour, "eqfield")
 	Equal(t, errs, nil)
 
-	errs = validate.Var(i, "eq=1")
-	Equal(t, errs, nil)
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eqfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eqfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"eqfield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield")
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,eqfield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestIsEqValidation(t *testing.T) {
+	var errs error
+	validate := New()
+
+	var j uint64
+	var k float64
+	s := "abcd"
+	i := 1
+	j = 1
+	k = 1.543
+	arr := []string{"test"}
+	now := time.Now().UTC()
+
+	errs = validate.Var(s, "eq=abcd")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(i, "eq=1")
+	Equal(t, errs, nil)
 
 	errs = validate.Var(j, "eq=1")
 	Equal(t, errs, nil)
@@ -4476,6 +4983,53 @@ func TestIsEqValidation(t *testing.T) {
 	AssertError(t, errs, "", "", "", "", "eq")
 
 	PanicMatches(t, func() { _ = validate.Var(now, "eq=now") }, "Bad field type time.Time")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "eq=1h")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-time.Minute, "eq=1h")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eq")
+
+	errs = validate.Var(time.Hour+time.Minute, "eq=1h")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "eq")
+
+	errs = validate.Var(time.Duration(0), "omitempty,eq=1h")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"eq=1h"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq")
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,eq=1h"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestOneOfValidation(t *testing.T) {
@@ -4653,11 +5207,29 @@ func TestEthereumAddressValidation(t *testing.T) {
 		param    string
 		expected bool
 	}{
-		{"", false},
-		{"0x02F9AE5f22EA3fA88F05780B30385bEC", false},
-		{"123f681646d4a755815f9cb19e1acc8565a0c2ac", false},
-		{"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true},
+		// All caps.
+		{"0x52908400098527886E0F7030069857D2E4169EE7", true},
+		{"0x8617E340B3D01FA5F11F306F4090FD50E238070D", true},
+
+		// All lower.
+		{"0xde709f2102306220921060314715629080e2fb77", true},
+		{"0x27b1fdb04752bbc536007a920d24acb045561c26", true},
 		{"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true},
+
+		// Mixed case: runs checksum validation.
+		{"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true},
+		{"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", true},
+		{"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", true},
+		{"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", true},
+		{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", true},
+		{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB", false}, // Invalid checksum.
+
+		// Other.
+		{"", false},
+		{"D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", false},    // Missing "0x" prefix.
+		{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDbc", false}, // More than 40 hex digits.
+		{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aD", false},   // Less than 40 hex digits.
+		{"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDw", false},  // Invalid hex digit "w".
 	}
 
 	for i, test := range tests {
@@ -4952,7 +5524,7 @@ func TestStructOnlyValidation(t *testing.T) {
 }
 
 func TestGtField(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	type TimeTest struct {
@@ -4969,7 +5541,7 @@ func TestGtField(t *testing.T) {
 		End:   &end,
 	}
 
-	errs := validate.Struct(timeTest)
+	errs = validate.Struct(timeTest)
 	Equal(t, errs, nil)
 
 	timeTest = &TimeTest{
@@ -4997,6 +5569,57 @@ func TestGtField(t *testing.T) {
 	errs = validate.VarWithValue("test bigger", "test", "gtfield")
 	Equal(t, errs, nil)
 
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "gtfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtfield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"gtfield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield")
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,gtfield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+
+	// Tests for Ints types.
+
 	type IntTest struct {
 		Val1 int `validate:"required"`
 		Val2 int `validate:"required,gtfield=Val1"`
@@ -5130,7 +5753,7 @@ func TestGtField(t *testing.T) {
 }
 
 func TestLtField(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	type TimeTest struct {
@@ -5147,7 +5770,7 @@ func TestLtField(t *testing.T) {
 		End:   &end,
 	}
 
-	errs := validate.Struct(timeTest)
+	errs = validate.Struct(timeTest)
 	Equal(t, errs, nil)
 
 	timeTest = &TimeTest{
@@ -5173,6 +5796,57 @@ func TestLtField(t *testing.T) {
 	errs = validate.VarWithValue("tes", "test", "ltfield")
 	Equal(t, errs, nil)
 
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltfield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "ltfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltfield")
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltfield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltfield")
+
+	errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltfield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"ltfield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield")
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,ltfield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+
+	// Tests for Ints types.
+
 	type IntTest struct {
 		Val1 int `validate:"required"`
 		Val2 int `validate:"required,ltfield=Val1"`
@@ -5411,7 +6085,7 @@ func TestContainsAndExcludes(t *testing.T) {
 }
 
 func TestLteField(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	type TimeTest struct {
@@ -5428,7 +6102,7 @@ func TestLteField(t *testing.T) {
 		End:   &end,
 	}
 
-	errs := validate.Struct(timeTest)
+	errs = validate.Struct(timeTest)
 	Equal(t, errs, nil)
 
 	timeTest = &TimeTest{
@@ -5457,6 +6131,55 @@ func TestLteField(t *testing.T) {
 	errs = validate.VarWithValue("test", "test", "ltefield")
 	Equal(t, errs, nil)
 
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "ltefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltefield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "ltefield")
+
+	errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltefield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"ltefield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltefield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,ltefield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+
+	// Tests for Ints types.
+
 	type IntTest struct {
 		Val1 int `validate:"required"`
 		Val2 int `validate:"required,ltefield=Val1"`
@@ -5572,7 +6295,7 @@ func TestLteField(t *testing.T) {
 }
 
 func TestGteField(t *testing.T) {
-
+	var errs error
 	validate := New()
 
 	type TimeTest struct {
@@ -5589,7 +6312,7 @@ func TestGteField(t *testing.T) {
 		End:   &end,
 	}
 
-	errs := validate.Struct(timeTest)
+	errs = validate.Struct(timeTest)
 	Equal(t, errs, nil)
 
 	timeTest = &TimeTest{
@@ -5618,6 +6341,55 @@ func TestGteField(t *testing.T) {
 	errs = validate.VarWithValue("test bigger", "test", "gtefield")
 	Equal(t, errs, nil)
 
+	// Tests for time.Duration type.
+
+	// -- Validations for variables of time.Duration type.
+
+	errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour, "gtefield")
+	Equal(t, errs, nil)
+
+	errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtefield")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gtefield")
+
+	errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtefield")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with time.Duration type fields.
+
+	type TimeDurationTest struct {
+		First  time.Duration `validate:"gtefield=Second"`
+		Second time.Duration
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtefield")
+
+	type TimeDurationOmitemptyTest struct {
+		First  time.Duration `validate:"omitempty,gtefield=Second"`
+		Second time.Duration
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+
+	// Tests for Ints types.
+
 	type IntTest struct {
 		Val1 int `validate:"required"`
 		Val2 int `validate:"required,gtefield=Val1"`
@@ -5853,9 +6625,11 @@ func TestLength(t *testing.T) {
 }
 
 func TestIsGt(t *testing.T) {
+	var errs error
 	validate := New()
+
 	myMap := map[string]string{}
-	errs := validate.Var(myMap, "gt=0")
+	errs = validate.Var(myMap, "gt=0")
 	NotEqual(t, errs, nil)
 
 	f := 1.23
@@ -5900,17 +6674,66 @@ func TestIsGt(t *testing.T) {
 	errs = validate.Struct(s)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "gt=59m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-time.Minute, "gt=59m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gt")
+
+	errs = validate.Var(time.Hour-2*time.Minute, "gt=59m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gt")
+
+	errs = validate.Var(time.Duration(0), "omitempty,gt=59m")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"gt=59m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt")
+
+	timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,gt=59m"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestIsGte(t *testing.T) {
+	var errs error
 	validate := New()
+
 	i := true
 	PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool")
 
 	t1 := time.Now().UTC()
 	t1 = t1.Add(time.Hour * 24)
 
-	errs := validate.Var(t1, "gte")
+	errs = validate.Var(t1, "gte")
 	Equal(t, errs, nil)
 
 	t2 := time.Now().UTC().Add(-time.Hour)
@@ -5936,74 +6759,386 @@ func TestIsGte(t *testing.T) {
 	errs = validate.Struct(s)
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte")
-}
 
-func TestIsLt(t *testing.T) {
-	validate := New()
-	myMap := map[string]string{}
-	errs := validate.Var(myMap, "lt=0")
-	NotEqual(t, errs, nil)
-	AssertError(t, errs, "", "", "", "", "lt")
+	// Tests for time.Duration type.
 
-	f := 1.23
-	errs = validate.Var(f, "lt=0")
-	NotEqual(t, errs, nil)
-	AssertError(t, errs, "", "", "", "", "lt")
+	// -- Validations for a variable of time.Duration type.
 
-	var ui uint = 5
-	errs = validate.Var(ui, "lt=0")
-	NotEqual(t, errs, nil)
-	AssertError(t, errs, "", "", "", "", "lt")
+	errs = validate.Var(time.Hour, "gte=59m")
+	Equal(t, errs, nil)
 
-	i := true
-	PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool")
+	errs = validate.Var(time.Hour-time.Minute, "gte=59m")
+	Equal(t, errs, nil)
 
-	t1 := time.Now().UTC().Add(-time.Hour)
+	errs = validate.Var(time.Hour-2*time.Minute, "gte=59m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "gte")
 
-	errs = validate.Var(t1, "lt")
+	errs = validate.Var(time.Duration(0), "omitempty,gte=59m")
 	Equal(t, errs, nil)
 
-	t2 := time.Now().UTC()
-	t2 = t2.Add(time.Hour * 24)
-
-	errs = validate.Var(t2, "lt")
-	NotEqual(t, errs, nil)
-	AssertError(t, errs, "", "", "", "", "lt")
+	// -- Validations for a struct with a time.Duration type field.
 
-	type Test struct {
-		Now *time.Time `validate:"lt"`
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"gte=59m"`
 	}
+	var timeDurationTest *TimeDurationTest
 
-	s := &Test{
-		Now: &t1,
-	}
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
 
-	errs = validate.Struct(s)
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
 	Equal(t, errs, nil)
 
-	s = &Test{
-		Now: &t2,
+	timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gte")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,gte=59m"`
 	}
 
-	errs = validate.Struct(s)
-	NotEqual(t, errs, nil)
-	AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt")
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
-func TestIsLte(t *testing.T) {
-
+func TestMinValidation(t *testing.T) {
+	var errs error
 	validate := New()
 
-	i := true
-	PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool")
+	// Tests for time.Duration type.
 
-	t1 := time.Now().UTC().Add(-time.Hour)
+	// -- Validations for a variable of time.Duration type.
 
-	errs := validate.Var(t1, "lte")
+	errs = validate.Var(time.Hour, "min=59m")
 	Equal(t, errs, nil)
 
-	t2 := time.Now().UTC()
-	t2 = t2.Add(time.Hour * 24)
+	errs = validate.Var(time.Hour-time.Minute, "min=59m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-2*time.Minute, "min=59m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "min")
+
+	errs = validate.Var(time.Duration(0), "omitempty,min=59m")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"min=59m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,min=59m"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestMaxValidation(t *testing.T) {
+	var errs error
+	validate := New()
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "max=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+time.Minute, "max=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+2*time.Minute, "max=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "max")
+
+	errs = validate.Var(time.Duration(0), "omitempty,max=-1s")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"max=1h1m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,max=-1s"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestMinMaxValidation(t *testing.T) {
+	var errs error
+	validate := New()
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "min=59m,max=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-time.Minute, "min=59m,max=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+time.Minute, "min=59m,max=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-2*time.Minute, "min=59m,max=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "min")
+
+	errs = validate.Var(time.Hour+2*time.Minute, "min=59m,max=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "max")
+
+	errs = validate.Var(time.Duration(0), "omitempty,min=59m,max=1h1m")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"min=59m,max=1h1m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min")
+
+	timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,min=59m,max=1h1m"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestLenValidation(t *testing.T) {
+	var errs error
+	validate := New()
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "len=1h")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour-time.Minute, "len=1h")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "len")
+
+	errs = validate.Var(time.Hour+time.Minute, "len=1h")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "len")
+
+	errs = validate.Var(time.Duration(0), "omitempty,len=1h")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"len=1h"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour - time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len")
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,len=1h"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestIsLt(t *testing.T) {
+	var errs error
+	validate := New()
+
+	myMap := map[string]string{}
+	errs = validate.Var(myMap, "lt=0")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	f := 1.23
+	errs = validate.Var(f, "lt=0")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	var ui uint = 5
+	errs = validate.Var(ui, "lt=0")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	i := true
+	PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool")
+
+	t1 := time.Now().UTC().Add(-time.Hour)
+
+	errs = validate.Var(t1, "lt")
+	Equal(t, errs, nil)
+
+	t2 := time.Now().UTC()
+	t2 = t2.Add(time.Hour * 24)
+
+	errs = validate.Var(t2, "lt")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	type Test struct {
+		Now *time.Time `validate:"lt"`
+	}
+
+	s := &Test{
+		Now: &t1,
+	}
+
+	errs = validate.Struct(s)
+	Equal(t, errs, nil)
+
+	s = &Test{
+		Now: &t2,
+	}
+
+	errs = validate.Struct(s)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt")
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "lt=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+time.Minute, "lt=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	errs = validate.Var(time.Hour+2*time.Minute, "lt=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lt")
+
+	errs = validate.Var(time.Duration(0), "omitempty,lt=0")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"lt=1h1m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt")
+
+	timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,lt=0"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
+}
+
+func TestIsLte(t *testing.T) {
+	var errs error
+	validate := New()
+
+	i := true
+	PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool")
+
+	t1 := time.Now().UTC().Add(-time.Hour)
+
+	errs = validate.Var(t1, "lte")
+	Equal(t, errs, nil)
+
+	t2 := time.Now().UTC()
+	t2 = t2.Add(time.Hour * 24)
 
 	errs = validate.Var(t2, "lte")
 	NotEqual(t, errs, nil)
@@ -6026,6 +7161,51 @@ func TestIsLte(t *testing.T) {
 
 	errs = validate.Struct(s)
 	NotEqual(t, errs, nil)
+
+	// Tests for time.Duration type.
+
+	// -- Validations for a variable of time.Duration type.
+
+	errs = validate.Var(time.Hour, "lte=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+time.Minute, "lte=1h1m")
+	Equal(t, errs, nil)
+
+	errs = validate.Var(time.Hour+2*time.Minute, "lte=1h1m")
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "", "", "", "", "lte")
+
+	errs = validate.Var(time.Duration(0), "omitempty,lte=-1s")
+	Equal(t, errs, nil)
+
+	// -- Validations for a struct with a time.Duration type field.
+
+	type TimeDurationTest struct {
+		Duration time.Duration `validate:"lte=1h1m"`
+	}
+	var timeDurationTest *TimeDurationTest
+
+	timeDurationTest = &TimeDurationTest{time.Hour}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	Equal(t, errs, nil)
+
+	timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute}
+	errs = validate.Struct(timeDurationTest)
+	NotEqual(t, errs, nil)
+	AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lte")
+
+	type TimeDurationOmitemptyTest struct {
+		Duration time.Duration `validate:"omitempty,lte=-1s"`
+	}
+
+	timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)}
+	errs = validate.Struct(timeDurationOmitemptyTest)
+	Equal(t, errs, nil)
 }
 
 func TestUrnRFC2141(t *testing.T) {
@@ -6585,6 +7765,14 @@ func TestHexadecimal(t *testing.T) {
 	errs := validate.Var(s, "hexadecimal")
 	Equal(t, errs, nil)
 
+	s = "0xff0044"
+	errs = validate.Var(s, "hexadecimal")
+	Equal(t, errs, nil)
+
+	s = "0Xff0044"
+	errs = validate.Var(s, "hexadecimal")
+	Equal(t, errs, nil)
+
 	s = "abcdefg"
 	errs = validate.Var(s, "hexadecimal")
 	NotEqual(t, errs, nil)
@@ -8144,6 +9332,12 @@ func TestUniqueValidation(t *testing.T) {
 		{[2]string{"a", "a"}, false},
 		{[2]interface{}{"a", "a"}, false},
 		{[4]interface{}{"a", 1, "b", 1}, false},
+		{[2]*string{stringPtr("a"), stringPtr("b")}, true},
+		{[2]*int{intPtr(1), intPtr(2)}, true},
+		{[2]*float64{float64Ptr(1), float64Ptr(2)}, true},
+		{[2]*string{stringPtr("a"), stringPtr("a")}, false},
+		{[2]*float64{float64Ptr(1), float64Ptr(1)}, false},
+		{[2]*int{intPtr(1), intPtr(1)}, false},
 		// Slices
 		{[]string{"a", "b"}, true},
 		{[]int{1, 2}, true},
@@ -8155,6 +9349,12 @@ func TestUniqueValidation(t *testing.T) {
 		{[]string{"a", "a"}, false},
 		{[]interface{}{"a", "a"}, false},
 		{[]interface{}{"a", 1, "b", 1}, false},
+		{[]*string{stringPtr("a"), stringPtr("b")}, true},
+		{[]*int{intPtr(1), intPtr(2)}, true},
+		{[]*float64{float64Ptr(1), float64Ptr(2)}, true},
+		{[]*string{stringPtr("a"), stringPtr("a")}, false},
+		{[]*float64{float64Ptr(1), float64Ptr(1)}, false},
+		{[]*int{intPtr(1), intPtr(1)}, false},
 		// Maps
 		{map[string]string{"one": "a", "two": "b"}, true},
 		{map[string]int{"one": 1, "two": 2}, true},
@@ -8232,42 +9432,85 @@ func TestUniqueValidationStructSlice(t *testing.T) {
 			}
 		}
 	}
-	PanicMatches(t, func() { validate.Var(testStructs, "unique=C") }, "Bad field name C")
+	PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C")
 }
 
-func TestHTMLValidation(t *testing.T) {
+func TestUniqueValidationStructPtrSlice(t *testing.T) {
+	testStructs := []*struct {
+		A *string
+		B *string
+	}{
+		{A: stringPtr("one"), B: stringPtr("two")},
+		{A: stringPtr("one"), B: stringPtr("three")},
+	}
+
 	tests := []struct {
+		target   interface{}
 		param    string
 		expected bool
 	}{
-		{"<html>", true},
-		{"<script>", true},
-		{"<stillworks>", true},
-		{"</html", false},
-		{"</script>", true},
-		{"<//script>", false},
-		{"<123nonsense>", false},
-		{"test", false},
-		{"&example", false},
+		{testStructs, "unique", true},
+		{testStructs, "unique=A", false},
+		{testStructs, "unique=B", true},
 	}
 
 	validate := New()
 
 	for i, test := range tests {
 
-		errs := validate.Var(test.param, "html")
+		errs := validate.Var(test.target, test.param)
 
 		if test.expected {
 			if !IsEqual(errs, nil) {
-				t.Fatalf("Index: %d html failed Error: %v", i, errs)
+				t.Fatalf("Index: %d unique failed Error: %v", i, errs)
 			}
 		} else {
 			if IsEqual(errs, nil) {
-				t.Fatalf("Index: %d html failed Error: %v", i, errs)
+				t.Fatalf("Index: %d unique failed Error: %v", i, errs)
 			} else {
 				val := getError(errs, "", "")
-				if val.Tag() != "html" {
-					t.Fatalf("Index: %d html failed Error: %v", i, errs)
+				if val.Tag() != "unique" {
+					t.Fatalf("Index: %d unique failed Error: %v", i, errs)
+				}
+			}
+		}
+	}
+	PanicMatches(t, func() { validate.Var(testStructs, "unique=C") }, "Bad field name C")
+}
+
+func TestHTMLValidation(t *testing.T) {
+	tests := []struct {
+		param    string
+		expected bool
+	}{
+		{"<html>", true},
+		{"<script>", true},
+		{"<stillworks>", true},
+		{"</html", false},
+		{"</script>", true},
+		{"<//script>", false},
+		{"<123nonsense>", false},
+		{"test", false},
+		{"&example", false},
+	}
+
+	validate := New()
+
+	for i, test := range tests {
+
+		errs := validate.Var(test.param, "html")
+
+		if test.expected {
+			if !IsEqual(errs, nil) {
+				t.Fatalf("Index: %d html failed Error: %v", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d html failed Error: %v", i, errs)
+			} else {
+				val := getError(errs, "", "")
+				if val.Tag() != "html" {
+					t.Fatalf("Index: %d html failed Error: %v", i, errs)
 				}
 			}
 		}
@@ -8695,6 +9938,151 @@ func TestEndsWithValidation(t *testing.T) {
 	}
 }
 
+func TestRequiredIf(t *testing.T) {
+	type Inner struct {
+		Field *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner   *Inner
+		FieldE  string            `validate:"omitempty" json:"field_e"`
+		FieldER string            `validate:"required_if=FieldE test" json:"field_er"`
+		Field1  string            `validate:"omitempty" json:"field_1"`
+		Field2  *string           `validate:"required_if=Field1 test" json:"field_2"`
+		Field3  map[string]string `validate:"required_if=Field2 test" json:"field_3"`
+		Field4  interface{}       `validate:"required_if=Field3 1" json:"field_4"`
+		Field5  int               `validate:"required_if=Inner.Field test" json:"field_5"`
+		Field6  uint              `validate:"required_if=Field5 1" json:"field_6"`
+		Field7  float32           `validate:"required_if=Field6 1" json:"field_7"`
+		Field8  float64           `validate:"required_if=Field7 1.0" json:"field_8"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: 2,
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner   *Inner
+		Inner2  *Inner
+		FieldE  string            `validate:"omitempty" json:"field_e"`
+		FieldER string            `validate:"required_if=FieldE test" json:"field_er"`
+		Field1  string            `validate:"omitempty" json:"field_1"`
+		Field2  *string           `validate:"required_if=Field1 test" json:"field_2"`
+		Field3  map[string]string `validate:"required_if=Field2 test" json:"field_3"`
+		Field4  interface{}       `validate:"required_if=Field2 test" json:"field_4"`
+		Field5  string            `validate:"required_if=Field3 1" json:"field_5"`
+		Field6  string            `validate:"required_if=Inner.Field test" json:"field_6"`
+		Field7  string            `validate:"required_if=Inner2.Field test" json:"field_7"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field2: &fieldVal,
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 3)
+	AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_if")
+	AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_if")
+	AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_if")
+
+	defer func() {
+		if r := recover(); r == nil {
+			t.Errorf("test3 should have panicked!")
+		}
+	}()
+
+	test3 := struct {
+		Inner  *Inner
+		Field1 string `validate:"required_if=Inner.Field" json:"field_1"`
+	}{
+		Inner: &Inner{Field: &fieldVal},
+	}
+	_ = validate.Struct(test3)
+}
+
+func TestRequiredUnless(t *testing.T) {
+	type Inner struct {
+		Field *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner   *Inner
+		FieldE  string            `validate:"omitempty" json:"field_e"`
+		FieldER string            `validate:"required_unless=FieldE test" json:"field_er"`
+		Field1  string            `validate:"omitempty" json:"field_1"`
+		Field2  *string           `validate:"required_unless=Field1 test" json:"field_2"`
+		Field3  map[string]string `validate:"required_unless=Field2 test" json:"field_3"`
+		Field4  interface{}       `validate:"required_unless=Field3 1" json:"field_4"`
+		Field5  int               `validate:"required_unless=Inner.Field test" json:"field_5"`
+		Field6  uint              `validate:"required_unless=Field5 2" json:"field_6"`
+		Field7  float32           `validate:"required_unless=Field6 0" json:"field_7"`
+		Field8  float64           `validate:"required_unless=Field7 0.0" json:"field_8"`
+	}{
+		FieldE: "test",
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: 2,
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner   *Inner
+		Inner2  *Inner
+		FieldE  string            `validate:"omitempty" json:"field_e"`
+		FieldER string            `validate:"required_unless=FieldE test" json:"field_er"`
+		Field1  string            `validate:"omitempty" json:"field_1"`
+		Field2  *string           `validate:"required_unless=Field1 test" json:"field_2"`
+		Field3  map[string]string `validate:"required_unless=Field2 test" json:"field_3"`
+		Field4  interface{}       `validate:"required_unless=Field2 test" json:"field_4"`
+		Field5  string            `validate:"required_unless=Field3 0" json:"field_5"`
+		Field6  string            `validate:"required_unless=Inner.Field test" json:"field_6"`
+		Field7  string            `validate:"required_unless=Inner2.Field test" json:"field_7"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		FieldE: "test",
+		Field1: "test",
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 3)
+	AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_unless")
+	AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_unless")
+	AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_unless")
+
+	defer func() {
+		if r := recover(); r == nil {
+			t.Errorf("test3 should have panicked!")
+		}
+	}()
+
+	test3 := struct {
+		Inner  *Inner
+		Field1 string `validate:"required_unless=Inner.Field" json:"field_1"`
+	}{
+		Inner: &Inner{Field: &fieldVal},
+	}
+	_ = validate.Struct(test3)
+}
+
 func TestRequiredWith(t *testing.T) {
 	type Inner struct {
 		Field *string
@@ -8750,6 +10138,268 @@ func TestRequiredWith(t *testing.T) {
 	AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_with")
 }
 
+func TestExcludedWith(t *testing.T) {
+	type Inner struct {
+		FieldE string
+		Field  *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_with=FieldE" json:"field_1"`
+		Field2 *string           `validate:"excluded_with=FieldE" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_with=FieldE" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_with=FieldE" json:"field_4"`
+		Field5 string            `validate:"excluded_with=Inner.FieldE" json:"field_5"`
+		Field6 string            `validate:"excluded_with=Inner2.FieldE" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_with=Field" json:"field_1"`
+		Field2 *string           `validate:"excluded_with=Field" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_with=Field" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_with=Field" json:"field_4"`
+		Field5 string            `validate:"excluded_with=Inner.Field" json:"field_5"`
+		Field6 string            `validate:"excluded_with=Inner2.Field" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field:  "populated",
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 5)
+	for i := 1; i <= 5; i++ {
+		name := fmt.Sprintf("Field%d", i)
+		AssertError(t, errs, name, name, name, name, "excluded_with")
+	}
+}
+
+func TestExcludedWithout(t *testing.T) {
+	type Inner struct {
+		FieldE string
+		Field  *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_without=Field" json:"field_1"`
+		Field2 *string           `validate:"excluded_without=Field" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_without=Field" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_without=Field" json:"field_4"`
+		Field5 string            `validate:"excluded_without=Inner.Field" json:"field_5"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field:  "populated",
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_without=FieldE" json:"field_1"`
+		Field2 *string           `validate:"excluded_without=FieldE" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_without=FieldE" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_without=FieldE" json:"field_4"`
+		Field5 string            `validate:"excluded_without=Inner.FieldE" json:"field_5"`
+		Field6 string            `validate:"excluded_without=Inner2.FieldE" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 6)
+	for i := 1; i <= 6; i++ {
+		name := fmt.Sprintf("Field%d", i)
+		AssertError(t, errs, name, name, name, name, "excluded_without")
+	}
+}
+
+func TestExcludedWithAll(t *testing.T) {
+	type Inner struct {
+		FieldE string
+		Field  *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_with_all=FieldE Field" json:"field_1"`
+		Field2 *string           `validate:"excluded_with_all=FieldE Field" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_with_all=FieldE Field" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_with_all=FieldE Field" json:"field_4"`
+		Field5 string            `validate:"excluded_with_all=Inner.FieldE" json:"field_5"`
+		Field6 string            `validate:"excluded_with_all=Inner2.FieldE" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field:  fieldVal,
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_with_all=Field FieldE" json:"field_1"`
+		Field2 *string           `validate:"excluded_with_all=Field FieldE" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_with_all=Field FieldE" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_with_all=Field FieldE" json:"field_4"`
+		Field5 string            `validate:"excluded_with_all=Inner.Field" json:"field_5"`
+		Field6 string            `validate:"excluded_with_all=Inner2.Field" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field:  "populated",
+		FieldE: "populated",
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 5)
+	for i := 1; i <= 5; i++ {
+		name := fmt.Sprintf("Field%d", i)
+		AssertError(t, errs, name, name, name, name, "excluded_with_all")
+	}
+}
+
+func TestExcludedWithoutAll(t *testing.T) {
+	type Inner struct {
+		FieldE string
+		Field  *string
+	}
+
+	fieldVal := "test"
+	test := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_without_all=Field FieldE" json:"field_1"`
+		Field2 *string           `validate:"excluded_without_all=Field FieldE" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_without_all=Field FieldE" json:"field_4"`
+		Field5 string            `validate:"excluded_without_all=Inner.Field Inner.Field2" json:"field_5"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field:  "populated",
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+	}
+
+	validate := New()
+
+	errs := validate.Struct(test)
+	Equal(t, errs, nil)
+
+	test2 := struct {
+		Inner  *Inner
+		Inner2 *Inner
+		Field  string            `validate:"omitempty" json:"field"`
+		FieldE string            `validate:"omitempty" json:"field_e"`
+		Field1 string            `validate:"excluded_without_all=FieldE Field" json:"field_1"`
+		Field2 *string           `validate:"excluded_without_all=FieldE Field" json:"field_2"`
+		Field3 map[string]string `validate:"excluded_without_all=FieldE Field" json:"field_3"`
+		Field4 interface{}       `validate:"excluded_without_all=FieldE Field" json:"field_4"`
+		Field5 string            `validate:"excluded_without_all=Inner.FieldE" json:"field_5"`
+		Field6 string            `validate:"excluded_without_all=Inner2.FieldE" json:"field_6"`
+	}{
+		Inner:  &Inner{Field: &fieldVal},
+		Field1: fieldVal,
+		Field2: &fieldVal,
+		Field3: map[string]string{"key": "val"},
+		Field4: "test",
+		Field5: "test",
+		Field6: "test",
+	}
+
+	errs = validate.Struct(test2)
+	NotEqual(t, errs, nil)
+
+	ve := errs.(ValidationErrors)
+	Equal(t, len(ve), 6)
+	for i := 1; i <= 6; i++ {
+		name := fmt.Sprintf("Field%d", i)
+		AssertError(t, errs, name, name, name, name, "excluded_without_all")
+	}
+}
+
 func TestRequiredWithAll(t *testing.T) {
 	type Inner struct {
 		Field *string
@@ -8858,6 +10508,16 @@ func TestRequiredWithout(t *testing.T) {
 	AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_without")
 	AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_without")
 	AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_without")
+
+	test3 := struct {
+		Field1 *string `validate:"required_without=Field2,omitempty,min=1" json:"field_1"`
+		Field2 *string `validate:"required_without=Field1,omitempty,min=1" json:"field_2"`
+	}{
+		Field1: &fieldVal,
+	}
+
+	errs = validate.Struct(&test3)
+	Equal(t, errs, nil)
 }
 
 func TestRequiredWithoutAll(t *testing.T) {
@@ -9000,7 +10660,7 @@ func TestGetTag(t *testing.T) {
 	}
 
 	val := New()
-	val.RegisterValidation("mytag", func(fl FieldLevel) bool {
+	_ = val.RegisterValidation("mytag", func(fl FieldLevel) bool {
 		tag = fl.GetTag()
 		return true
 	})
@@ -9201,3 +10861,132 @@ func TestDatetimeValidation(t *testing.T) {
 		_ = validate.Var(2, "datetime")
 	}, "Bad field type int")
 }
+
+func TestIsIso3166Alpha2Validation(t *testing.T) {
+	tests := []struct {
+		value    string `validate:"iso3166_1_alpha2"`
+		expected bool
+	}{
+		{"PL", true},
+		{"POL", false},
+		{"AA", false},
+	}
+
+	validate := New()
+
+	for i, test := range tests {
+
+		errs := validate.Var(test.value, "iso3166_1_alpha2")
+
+		if test.expected {
+			if !IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs)
+			}
+		}
+	}
+}
+
+func TestIsIso3166Alpha3Validation(t *testing.T) {
+	tests := []struct {
+		value    string `validate:"iso3166_1_alpha3"`
+		expected bool
+	}{
+		{"POL", true},
+		{"PL", false},
+		{"AAA", false},
+	}
+
+	validate := New()
+
+	for i, test := range tests {
+
+		errs := validate.Var(test.value, "iso3166_1_alpha3")
+
+		if test.expected {
+			if !IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs)
+			}
+		}
+	}
+}
+
+func TestIsIso3166AlphaNumericValidation(t *testing.T) {
+	tests := []struct {
+		value    int
+		expected bool
+	}{
+		{248, true},
+		{0, false},
+		{1, false},
+	}
+
+	validate := New()
+
+	for i, test := range tests {
+
+		errs := validate.Var(test.value, "iso3166_1_alpha_numeric")
+
+		if test.expected {
+			if !IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs)
+			}
+		}
+	}
+
+	PanicMatches(t, func() {
+		_ = validate.Var("1", "iso3166_1_alpha_numeric")
+	}, "Bad field type string")
+}
+
+func TestTimeZoneValidation(t *testing.T) {
+	tests := []struct {
+		value    string `validate:"timezone"`
+		tag      string
+		expected bool
+	}{
+		// systems may have different time zone database, some systems time zone are case insensitive
+		{"America/New_York", `timezone`, true},
+		{"UTC", `timezone`, true},
+		{"", `timezone`, false},
+		{"Local", `timezone`, false},
+		{"Unknown", `timezone`, 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 time zone failed Error: %s", i, errs)
+			}
+		} else {
+			if IsEqual(errs, nil) {
+				t.Fatalf("Index: %d time zone failed Error: %s", i, errs)
+			} else {
+				val := getError(errs, "", "")
+				if val.Tag() != "timezone" {
+					t.Fatalf("Index: %d time zone failed Error: %s", i, errs)
+				}
+			}
+		}
+	}
+
+	PanicMatches(t, func() {
+		_ = validate.Var(2, "timezone")
+	}, "Bad field type int")
+}
\ No newline at end of file