/
datetime2.go
143 lines (117 loc) · 2.39 KB
/
datetime2.go
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
package bactract
import (
"fmt"
"strings"
"time"
)
// readDatetime2 reads the value for a datetime column.
func readDatetime2(r *tReader, tc TableColumn) (ec ExtractedColumn, err error) {
fn := "readDatetime2"
defSz := 8
if debugFlag {
debOut(fmt.Sprintf("Func %s", fn))
}
// Determine how many bytes to read
var ss storedSize
ss, err = r.readStoredSize(tc, 1, defSz)
if err != nil {
return
}
// Check for nulls
if ss.isNull {
ec.IsNull = ss.isNull
return
}
// Read the datetime
if ss.byteCount > 0 {
dateSize := 3
timeSize := ss.byteCount - dateSize
var s, y []byte
s, err = r.readBytes(fmt.Sprintf("%s: timeBytes", fn), timeSize)
if err != nil {
return
}
y, err = r.readBytes(fmt.Sprintf("%s: dateBytes", fn), dateSize)
if err != nil {
return
}
var ticks uint64
for i, sb := range stripTrailingNulls(s) {
ticks |= uint64(sb) << uint(8*i)
}
var days int
for i, sb := range stripTrailingNulls(y) {
days |= int(sb) << uint(8*i)
}
start := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
d := start.AddDate(0, 0, days)
// Add the time portion
var duration string
duration, err = calcDuration(tc.Scale, ticks)
if err != nil {
return
}
m, _ := time.ParseDuration(duration)
dt := d.Add(m)
ec.Str = dt.Format(calcFormat(tc.Scale, ticks))
}
return
}
func calcDuration(scale int, ticks uint64) (pds string, err error) {
var u = map[int]string{
0: "s",
1: "ms",
2: "ms",
3: "ms",
4: "us",
5: "us",
6: "us",
7: "ns",
}
units, ok := u[scale]
if !ok {
err = fmt.Errorf("Could not determine units for datetime2 time duration. Unknown scale (%d)", scale)
return pds, err
}
var pd uint64
switch scale {
case 0:
pd = ticks / 1000000
case 1:
pd = ticks / 100000
case 2:
pd = ticks / 10000
case 3:
pd = ticks / 1000
case 4:
pd = ticks / 100
case 5:
pd = ticks / 10
case 6:
pd = ticks
case 7:
pd = ticks * 100
}
// 0 -> ticks * 1 s
// 1 -> ticks * 100 ms
// 2 -> ticks * 10 ms
// 3 -> ticks * 1 ms
// 4 -> ticks * 100 us
// 5 -> ticks * 10 us
// 6 -> ticks * 1 us
// 7 -> ticks * 100 ns
pds = fmt.Sprintf("%d%s", pd, units)
return pds, err
}
func calcFormat(scale int, ticks uint64) (dtf string) {
var ns []string
ns = append(ns, "2006-01-02 15:04:05")
if scale > 0 {
ns = append(ns, ".")
for i := 0; i < scale; i++ {
ns = append(ns, "0")
}
}
dtf = strings.Join(ns, "")
return dtf
}