Fix support for aliased time.Time types (#890)

pull/936/head
Lauris BH 3 years ago committed by GitHub
parent 090afeb8ac
commit f09500fca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 202
      baked_in.go
  2. 2
      util.go
  3. 2
      validator.go
  4. 8
      validator_instance.go
  5. 22
      validator_test.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()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
if fieldType == timeType {
fieldTime := field.Interface().(time.Time)
topTime := topField.Interface().(time.Time)
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
}
}
// default reflect.String:
@ -920,18 +919,18 @@ func isLtCrossStructField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := field.Interface().(time.Time)
topTime := topField.Interface().(time.Time)
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
}
}
// default reflect.String:
@ -967,18 +966,18 @@ func isGteCrossStructField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := field.Interface().(time.Time)
topTime := topField.Interface().(time.Time)
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
}
}
// default reflect.String:
@ -1014,18 +1013,18 @@ func isGtCrossStructField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
if fieldType == timeType {
fieldTime := field.Interface().(time.Time)
topTime := topField.Interface().(time.Time)
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
}
}
// default reflect.String:
@ -1064,18 +1063,18 @@ func isNeCrossStructField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return true
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
t := field.Interface().(time.Time)
fieldTime := topField.Interface().(time.Time)
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
}
}
// default reflect.String:
@ -1114,18 +1113,18 @@ func isEqCrossStructField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
t := field.Interface().(time.Time)
fieldTime := topField.Interface().(time.Time)
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
}
}
// 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()
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(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.After(t) || fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
@ -1758,18 +1756,18 @@ func isGtField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(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.After(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// 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()
// 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.Before(t) || fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
@ -1984,18 +1982,18 @@ func isLtField(fl FieldLevel) bool {
fieldType := field.Type()
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
if fieldType == timeType {
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(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.Before(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// 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())
}
}

@ -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…
Cancel
Save