diff --git a/compose/automation/expr_types.go b/compose/automation/expr_types.go index 5fb50827f..e121141ab 100644 --- a/compose/automation/expr_types.go +++ b/compose/automation/expr_types.go @@ -8,6 +8,7 @@ import ( "github.com/cortezaproject/corteza-server/pkg/expr" "github.com/spf13/cast" "strings" + "time" ) func CastToComposeNamespace(val interface{}) (out *types.Namespace, err error) { @@ -94,7 +95,6 @@ func (t ComposeRecord) SelectGVal(ctx context.Context, k string) (interface{}, e func CastToComposeRecordValues(val interface{}) (out types.RecordValueSet, err error) { out = types.RecordValueSet{} - switch val := val.(type) { case expr.Iterator: return out, val.Each(func(k string, v expr.TypedValue) error { @@ -212,10 +212,21 @@ func assignToComposeRecordValues(res *types.RecordValueSet, pp []string, val int if len(pp) < 1 { return fmt.Errorf("empty path used for assigning record values") } - k := pp[0] rv := &types.RecordValue{Name: k} - if rv.Value, err = cast.ToStringE(expr.UntypedValue(val)); err != nil { + + // @todo this needs to be implemented properly + // we're just guessing here and puting out fires + switch utval := expr.UntypedValue(val).(type) { + case time.Time: + rv.Value = utval.Format(time.RFC3339) + case *time.Time: + rv.Value = utval.Format(time.RFC3339) + default: + rv.Value, err = cast.ToStringE(utval) + } + + if err != nil { return } @@ -226,7 +237,7 @@ func assignToComposeRecordValues(res *types.RecordValueSet, pp []string, val int } *res = res.Set(rv) - //return fmt.Errorf("unknown field '%s'", k) + return nil } diff --git a/compose/service/values/sanitizer.go b/compose/service/values/sanitizer.go index a66d8f724..21c360170 100644 --- a/compose/service/values/sanitizer.go +++ b/compose/service/values/sanitizer.go @@ -175,16 +175,7 @@ func sDatetime(v interface{}, onlyDate, onlyTime bool) string { datetime = fmt.Sprintf("%v", v) ) - if onlyDate { - internalFormat = datetimeInternalFormatDate - inputFormats = []string{ - datetimeInternalFormatDate, - "02 Jan 06", - "Monday, 02-Jan-06", - "Mon, 02 Jan 2006", - "2006/_1/_2", - } - } else if onlyTime { + if onlyTime { internalFormat = datetimeIntenralFormatTime inputFormats = []string{ datetimeIntenralFormatTime, @@ -198,29 +189,44 @@ func sDatetime(v interface{}, onlyDate, onlyTime bool) string { time.Kitchen, } } else { - internalFormat = datetimeInternalFormatFull + if onlyDate { + // In case only date is used, make sure we format it properly + internalFormat = datetimeInternalFormatDate + } else { + internalFormat = datetimeInternalFormatFull + } + // date & time inputFormats = []string{ datetimeInternalFormatFull, + "2006-01-02T15:04:05", // iso8601 without timezone time.RFC1123Z, time.RFC1123, - time.RFC850, time.RFC822Z, time.RFC822, - time.RubyDate, - time.UnixDate, + time.RFC850, time.ANSIC, - "2006/_1/_2 15:04:05", - "2006/_1/_2 15:04", - } - - // if string looks like a RFC 3330 (ISO 8601), see if we need to suffix it with Z - if isoDaty.MatchString(datetime) && !hasTimezone.MatchString(datetime) { - // No timezone, add Z to satisfy parser - datetime = datetime + "Z" - - // Simplifiy list of rules - inputFormats = []string{time.RFC3339} + time.UnixDate, + time.RubyDate, + "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() + "2006-01-02", + "02 Jan 2006", + "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon + "2006-01-02 15:04:05 -07:00", + "2006-01-02 15:04:05 -0700", + "2006-01-02 15:04:05Z07:00", // RFC3339 without T + "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon + "2006-01-02 15:04:05", + time.Kitchen, + time.Stamp, + time.StampMilli, + time.StampMicro, + time.StampNano, + datetimeInternalFormatDate, + "02 Jan 06", + "Monday, 02-Jan-06", + "Mon, 02 Jan 2006", + "2006/_1/_2", } } diff --git a/compose/service/values/sanitizer_test.go b/compose/service/values/sanitizer_test.go index 478f3f71e..7491c682b 100644 --- a/compose/service/values/sanitizer_test.go +++ b/compose/service/values/sanitizer_test.go @@ -1,8 +1,11 @@ package values import ( + "fmt" + "github.com/stretchr/testify/assert" "reflect" "testing" + "time" "github.com/cortezaproject/corteza-server/compose/types" ) @@ -209,3 +212,22 @@ func TestSanitizerExpr(t *testing.T) { }) } } + +func TestDatetimeSanitizer(t *testing.T) { + tests := []struct { + input interface{} + onlyDate, onlyTime bool + rval string + }{ + {time.Date(1999, 9, 9, 9, 9, 9, 9, time.UTC), false, false, "1999-09-09T09:09:09Z"}, + {"2021-03-23T20:21:15Z", false, false, "2021-03-23T20:21:15Z"}, + {"2021-03-23T20:21:15+01:00", false, false, "2021-03-23T19:21:15Z"}, + {"2021-03-23", true, false, "2021-03-23"}, + } + + for _, tt := range tests { + t.Run(fmt.Sprintf("%v", tt.input), func(t *testing.T) { + assert.New(t).Equal(tt.rval, sDatetime(tt.input, tt.onlyDate, tt.onlyTime)) + }) + } +}