From e20e022612ba108606e2e8293bc79aeca245f741 Mon Sep 17 00:00:00 2001
From: ko_oler <kooler89@gmail.com>
Date: Sun, 20 Aug 2023 12:35:14 +0300
Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?=
 =?UTF-8?q?=D0=B2=D0=B0=D0=BD=20=D1=82=D0=B8=D0=BF=20=D0=BF=D0=BE=D0=BB?=
 =?UTF-8?q?=D1=8F=20Timestamp=20=D0=B2=20perxis=20schema?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pkg/schema/field/timestamp.go      | 70 ++++++++++++++++++++++++++++++
 pkg/schema/field/timestamp_test.go | 69 +++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+)
 create mode 100644 pkg/schema/field/timestamp.go
 create mode 100644 pkg/schema/field/timestamp_test.go

diff --git a/pkg/schema/field/timestamp.go b/pkg/schema/field/timestamp.go
new file mode 100644
index 00000000..66f6d4fb
--- /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 00000000..1665c571
--- /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)
+			}
+		})
+	}
+}
-- 
GitLab