diff --git a/pkg/schema/field/timestamp.go b/pkg/schema/field/timestamp.go new file mode 100644 index 0000000000000000000000000000000000000000..66f6d4fbae015c9fef73e4dc7de367888288eadd --- /dev/null +++ b/pkg/schema/field/timestamp.go @@ -0,0 +1,70 @@ +package field + +import ( + "context" + "errors" + "fmt" + "reflect" + "strconv" + "strings" +) + +var timestampType = &TimestampType{} + +type TimestampParameters struct{} + +func (t TimestampParameters) Type() Type { return timestampType } +func (t *TimestampParameters) Clone(reset bool) Parameters { return t } + +type TimestampType struct{} + +func (t TimestampType) Name() string { + return "timestamp" +} + +func (TimestampType) NewParameters() Parameters { + return &TimestampParameters{} +} + +func (TimestampType) IsEmpty(v interface{}) bool { + return v == 0 || v == nil +} + +func (TimestampType) Decode(_ context.Context, _ *Field, v interface{}) (interface{}, error) { + if v == nil { + return nil, nil + } + + switch i := v.(type) { + case string: + t := strings.Split(i, ":") + if len(t) == 3 { + hourToSeconds, _ := strconv.Atoi(t[0]) + minutesToSeconds, _ := strconv.Atoi(t[1]) + seconds, _ := strconv.Atoi(t[2]) + return int64(hourToSeconds*3600 + minutesToSeconds*60 + seconds), nil + } + return nil, errors.New("wrong time format: input in 'HH:MM:SS'") + + case int64: + return i, nil + case uint64: + return int64(i), nil + } + + return nil, fmt.Errorf("TimestampField decode error: unsupported value type : \"%s\"", reflect.ValueOf(v).Kind()) +} + +func (TimestampType) Encode(_ context.Context, _ *Field, v interface{}) (interface{}, error) { + if v == nil { + return nil, nil + } + if _, ok := v.(int64); ok { + return v, nil + } + return nil, fmt.Errorf("TimestampField encode error: unsupported value type : \"%s\"", reflect.ValueOf(v).Kind()) +} + +func Timestamp(o ...interface{}) *Field { + return NewField(&TimestampParameters{}, o...) +} diff --git a/pkg/schema/field/timestamp_test.go b/pkg/schema/field/timestamp_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1665c571e6a051fda2c870462efd0d2b9b129591 --- /dev/null +++ b/pkg/schema/field/timestamp_test.go @@ -0,0 +1,69 @@ +package field + +import ( + "context" + "reflect" + "testing" +) + +func TestTimestamp_Decode(t *testing.T) { + tests := []struct { + name string + field *Field + data interface{} + want interface{} + wantErr bool + }{ + {"Correct", Timestamp(), int64(2), int64(2), false}, // #0 + {"Correct", Timestamp(), uint64(2), int64(2), false}, // #1 + {"Correct", Timestamp(), "13:10:44", int64(47444), false}, // #2 + + {"Wrong data", Timestamp(), "", nil, true}, // #0 + {"Wrong data", Timestamp(), []byte(""), nil, true}, // #1 + {"Wrong data", Timestamp(), 2.2, nil, true}, // #2 + {"Wrong data", Timestamp(), "13:10", nil, true}, // #3 + + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Decode(context.Background(), tt.field, tt.data) + if (err != nil) != tt.wantErr { + t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Decode() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTimestamp_Encode(t *testing.T) { + tests := []struct { + name string + field *Field + data interface{} + want interface{} + wantErr bool + }{ + {"Correct", Timestamp(), int64(2), int64(2), false}, // #0 + + {"Wrong data", Timestamp(), "", nil, true}, // #0 + {"Wrong data", Timestamp(), []byte(""), nil, true}, // #1 + {"Wrong data", Timestamp(), 2.2, nil, true}, // #2 + {"Wrong data", Timestamp(), uint64(2), nil, true}, // #2 + + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Encode(context.Background(), tt.field, tt.data) + if (err != nil) != tt.wantErr { + t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Decode() got = %v, want %v", got, tt.want) + } + }) + } +}