1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
package proto
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/go-faster/errors"
)
var (
_ ColumnOf[time.Time] = (*ColDateTime64)(nil)
_ Inferable = (*ColDateTime64)(nil)
_ Column = (*ColDateTime64)(nil)
)
// ColDateTime64 implements ColumnOf[time.Time].
//
// If Precision is not set, Append and Row() panics.
// Use ColDateTime64Raw to work with raw DateTime64 values.
type ColDateTime64 struct {
Data []DateTime64
Location *time.Location
Precision Precision
PrecisionSet bool
}
func (c *ColDateTime64) WithPrecision(p Precision) *ColDateTime64 {
c.Precision = p
c.PrecisionSet = true
return c
}
func (c *ColDateTime64) WithLocation(loc *time.Location) *ColDateTime64 {
c.Location = loc
return c
}
func (c ColDateTime64) Rows() int {
return len(c.Data)
}
func (c *ColDateTime64) Reset() {
c.Data = c.Data[:0]
}
func (c ColDateTime64) Type() ColumnType {
var elems []string
if p := c.Precision; c.PrecisionSet {
elems = append(elems, strconv.Itoa(int(p)))
}
if loc := c.Location; loc != nil {
elems = append(elems, fmt.Sprintf(`'%s'`, loc))
}
return ColumnTypeDateTime64.With(elems...)
}
func (c *ColDateTime64) Infer(t ColumnType) error {
elem := string(t.Elem())
if elem == "" {
return errors.Errorf("invalid DateTime64: no elements in %q", t)
}
elems := strings.SplitN(elem, ",", 2)
for i := range elems {
elems[i] = strings.Trim(elems[i], `' `)
}
n, err := strconv.ParseUint(elems[0], 10, 8)
if err != nil {
return errors.Wrap(err, "parse precision")
}
p := Precision(n)
if !p.Valid() {
return errors.Errorf("precision %d is invalid", n)
}
c.Precision = p
c.PrecisionSet = true
if len(elems) > 1 {
loc, err := time.LoadLocation(elems[1])
if err != nil {
return errors.Wrap(err, "invalid location")
}
c.Location = loc
}
return nil
}
func (c ColDateTime64) Row(i int) time.Time {
if !c.PrecisionSet {
panic("DateTime64: no precision set")
}
return c.Data[i].Time(c.Precision).In(c.loc())
}
func (c ColDateTime64) loc() *time.Location {
if c.Location == nil {
// Defaulting to local timezone (not UTC).
return time.Local
}
return c.Location
}
func (c *ColDateTime64) AppendRaw(v DateTime64) {
c.Data = append(c.Data, v)
}
func (c *ColDateTime64) Append(v time.Time) {
if !c.PrecisionSet {
panic("DateTime64: no precision set")
}
c.AppendRaw(ToDateTime64(v, c.Precision))
}
func (c *ColDateTime64) AppendArr(v []time.Time) {
if !c.PrecisionSet {
panic("DateTime64: no precision set")
}
for _, item := range v {
c.AppendRaw(ToDateTime64(item, c.Precision))
}
}
// Raw version of ColDateTime64 for ColumnOf[DateTime64].
func (c ColDateTime64) Raw() *ColDateTime64Raw {
return &ColDateTime64Raw{ColDateTime64: c}
}
func (c *ColDateTime64) Array() *ColArr[time.Time] {
return &ColArr[time.Time]{Data: c}
}
var (
_ ColumnOf[DateTime64] = (*ColDateTime64Raw)(nil)
_ Inferable = (*ColDateTime64Raw)(nil)
_ Column = (*ColDateTime64Raw)(nil)
)
// ColDateTime64Raw is DateTime64 wrapper to implement ColumnOf[DateTime64].
type ColDateTime64Raw struct {
ColDateTime64
}
func (c *ColDateTime64Raw) Append(v DateTime64) { c.AppendRaw(v) }
func (c *ColDateTime64Raw) AppendArr(vs []DateTime64) {
for _, v := range vs {
c.AppendRaw(v)
}
}
func (c ColDateTime64Raw) Row(i int) DateTime64 { return c.Data[i] }
|