mirror of
https://github.com/Fishwaldo/validator.git
synced 2025-03-15 11:41:32 +00:00
Fix support for aliased time.Time types (#890)
This commit is contained in:
parent
090afeb8ac
commit
f09500fca7
5 changed files with 128 additions and 108 deletions
202
baked_in.go
202
baked_in.go
|
@ -819,12 +819,7 @@ func isNeField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return true
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
|
@ -832,6 +827,10 @@ func isNeField(fl FieldLevel) bool {
|
|||
return !fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -872,18 +871,18 @@ func isLteCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
topTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
topTime := topField.Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -920,18 +919,18 @@ func isLtCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
topTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(topTime)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
topTime := topField.Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(topTime)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -967,18 +966,18 @@ func isGteCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
topTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(topTime) || fieldTime.Equal(topTime)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
topTime := topField.Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(topTime) || fieldTime.Equal(topTime)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -1014,18 +1013,18 @@ func isGtCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
topTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(topTime)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
topTime := topField.Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(topTime)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -1064,18 +1063,18 @@ func isNeCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := field.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return !fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return true
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := field.Interface().(time.Time)
|
||||
fieldTime := topField.Interface().(time.Time)
|
||||
|
||||
return !fieldTime.Equal(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -1114,18 +1113,18 @@ func isEqCrossStructField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := field.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := topField.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != topField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := field.Interface().(time.Time)
|
||||
fieldTime := topField.Interface().(time.Time)
|
||||
|
||||
return fieldTime.Equal(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -1164,19 +1163,18 @@ func isEqField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
t := currentField.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String:
|
||||
|
@ -1711,18 +1709,18 @@ func isGteField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := currentField.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(t) || fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(t) || fieldTime.Equal(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String
|
||||
|
@ -1758,18 +1756,18 @@ func isGtField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := currentField.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
|
||||
return fieldTime.After(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String
|
||||
|
@ -1811,10 +1809,10 @@ func isGte(fl FieldLevel) bool {
|
|||
|
||||
case reflect.Struct:
|
||||
|
||||
if field.Type() == timeType {
|
||||
if field.Type().ConvertibleTo(timeType) {
|
||||
|
||||
now := time.Now().UTC()
|
||||
t := field.Interface().(time.Time)
|
||||
t := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return t.After(now) || t.Equal(now)
|
||||
}
|
||||
|
@ -1857,9 +1855,9 @@ func isGt(fl FieldLevel) bool {
|
|||
return field.Float() > p
|
||||
case reflect.Struct:
|
||||
|
||||
if field.Type() == timeType {
|
||||
if field.Type().ConvertibleTo(timeType) {
|
||||
|
||||
return field.Interface().(time.Time).After(time.Now().UTC())
|
||||
return field.Convert(timeType).Interface().(time.Time).After(time.Now().UTC())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1937,18 +1935,18 @@ func isLteField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := currentField.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(t) || fieldTime.Equal(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(t) || fieldTime.Equal(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String
|
||||
|
@ -1984,18 +1982,18 @@ func isLtField(fl FieldLevel) bool {
|
|||
|
||||
fieldType := field.Type()
|
||||
|
||||
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
|
||||
|
||||
t := currentField.Convert(timeType).Interface().(time.Time)
|
||||
fieldTime := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(t)
|
||||
}
|
||||
|
||||
// Not Same underlying type i.e. struct and time
|
||||
if fieldType != currentField.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldType == timeType {
|
||||
|
||||
t := currentField.Interface().(time.Time)
|
||||
fieldTime := field.Interface().(time.Time)
|
||||
|
||||
return fieldTime.Before(t)
|
||||
}
|
||||
}
|
||||
|
||||
// default reflect.String
|
||||
|
@ -2037,10 +2035,10 @@ func isLte(fl FieldLevel) bool {
|
|||
|
||||
case reflect.Struct:
|
||||
|
||||
if field.Type() == timeType {
|
||||
if field.Type().ConvertibleTo(timeType) {
|
||||
|
||||
now := time.Now().UTC()
|
||||
t := field.Interface().(time.Time)
|
||||
t := field.Convert(timeType).Interface().(time.Time)
|
||||
|
||||
return t.Before(now) || t.Equal(now)
|
||||
}
|
||||
|
@ -2084,9 +2082,9 @@ func isLt(fl FieldLevel) bool {
|
|||
|
||||
case reflect.Struct:
|
||||
|
||||
if field.Type() == timeType {
|
||||
if field.Type().ConvertibleTo(timeType) {
|
||||
|
||||
return field.Interface().(time.Time).Before(time.Now().UTC())
|
||||
return field.Convert(timeType).Interface().(time.Time).Before(time.Now().UTC())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
util.go
2
util.go
|
@ -82,7 +82,7 @@ BEGIN:
|
|||
fld := namespace
|
||||
var ns string
|
||||
|
||||
if typ != timeType {
|
||||
if !typ.ConvertibleTo(timeType) {
|
||||
|
||||
idx := strings.Index(namespace, namespaceSeparator)
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
|
|||
|
||||
typ = current.Type()
|
||||
|
||||
if typ != timeType {
|
||||
if !typ.ConvertibleTo(timeType) {
|
||||
|
||||
if ct != nil {
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
|
|||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn Filt
|
|||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,7 @@ func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields .
|
|||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
|
@ -516,7 +516,7 @@ func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ..
|
|||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
|
|
|
@ -5021,6 +5021,28 @@ func TestIsEqFieldValidation(t *testing.T) {
|
|||
Equal(t, errs, nil)
|
||||
}
|
||||
|
||||
func TestIsEqFieldValidationWithAliasTime(t *testing.T) {
|
||||
var errs error
|
||||
validate := New()
|
||||
|
||||
type CustomTime time.Time
|
||||
|
||||
type Test struct {
|
||||
Start CustomTime `validate:"eqfield=End"`
|
||||
End *time.Time
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
sv := &Test{
|
||||
Start: CustomTime(now),
|
||||
End: &now,
|
||||
}
|
||||
|
||||
errs = validate.Struct(sv)
|
||||
Equal(t, errs, nil)
|
||||
}
|
||||
|
||||
func TestIsEqValidation(t *testing.T) {
|
||||
var errs error
|
||||
validate := New()
|
||||
|
|
Loading…
Add table
Reference in a new issue