github.com/apache/arrow/go/v16@v16.1.0/arrow/array/timestamp.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package array 18 19 import ( 20 "bytes" 21 "fmt" 22 "reflect" 23 "strings" 24 "sync/atomic" 25 "time" 26 27 "github.com/apache/arrow/go/v16/arrow" 28 "github.com/apache/arrow/go/v16/arrow/bitutil" 29 "github.com/apache/arrow/go/v16/arrow/internal/debug" 30 "github.com/apache/arrow/go/v16/arrow/memory" 31 "github.com/apache/arrow/go/v16/internal/json" 32 ) 33 34 // Timestamp represents an immutable sequence of arrow.Timestamp values. 35 type Timestamp struct { 36 array 37 values []arrow.Timestamp 38 } 39 40 // NewTimestampData creates a new Timestamp from Data. 41 func NewTimestampData(data arrow.ArrayData) *Timestamp { 42 a := &Timestamp{} 43 a.refCount = 1 44 a.setData(data.(*Data)) 45 return a 46 } 47 48 // Reset resets the array for re-use. 49 func (a *Timestamp) Reset(data *Data) { 50 a.setData(data) 51 } 52 53 // Value returns the value at the specified index. 54 func (a *Timestamp) Value(i int) arrow.Timestamp { return a.values[i] } 55 56 // TimestampValues returns the values. 57 func (a *Timestamp) TimestampValues() []arrow.Timestamp { return a.values } 58 59 // String returns a string representation of the array. 60 func (a *Timestamp) String() string { 61 o := new(strings.Builder) 62 o.WriteString("[") 63 for i, v := range a.values { 64 if i > 0 { 65 fmt.Fprintf(o, " ") 66 } 67 switch { 68 case a.IsNull(i): 69 o.WriteString(NullValueStr) 70 default: 71 fmt.Fprintf(o, "%v", v) 72 } 73 } 74 o.WriteString("]") 75 return o.String() 76 } 77 78 func (a *Timestamp) setData(data *Data) { 79 a.array.setData(data) 80 vals := data.buffers[1] 81 if vals != nil { 82 a.values = arrow.TimestampTraits.CastFromBytes(vals.Bytes()) 83 beg := a.array.data.offset 84 end := beg + a.array.data.length 85 a.values = a.values[beg:end] 86 } 87 } 88 89 func (a *Timestamp) ValueStr(i int) string { 90 if a.IsNull(i) { 91 return NullValueStr 92 } 93 94 toTime, _ := a.DataType().(*arrow.TimestampType).GetToTimeFunc() 95 return toTime(a.values[i]).Format("2006-01-02 15:04:05.999999999Z0700") 96 } 97 98 func (a *Timestamp) GetOneForMarshal(i int) interface{} { 99 if val := a.ValueStr(i); val != NullValueStr { 100 return val 101 } 102 return nil 103 } 104 105 func (a *Timestamp) MarshalJSON() ([]byte, error) { 106 vals := make([]interface{}, a.Len()) 107 for i := range a.values { 108 vals[i] = a.GetOneForMarshal(i) 109 } 110 111 return json.Marshal(vals) 112 } 113 114 func arrayEqualTimestamp(left, right *Timestamp) bool { 115 for i := 0; i < left.Len(); i++ { 116 if left.IsNull(i) { 117 continue 118 } 119 if left.Value(i) != right.Value(i) { 120 return false 121 } 122 } 123 return true 124 } 125 126 type TimestampBuilder struct { 127 builder 128 129 dtype *arrow.TimestampType 130 data *memory.Buffer 131 rawData []arrow.Timestamp 132 } 133 134 func NewTimestampBuilder(mem memory.Allocator, dtype *arrow.TimestampType) *TimestampBuilder { 135 return &TimestampBuilder{builder: builder{refCount: 1, mem: mem}, dtype: dtype} 136 } 137 138 func (b *TimestampBuilder) Type() arrow.DataType { return b.dtype } 139 140 // Release decreases the reference count by 1. 141 // When the reference count goes to zero, the memory is freed. 142 func (b *TimestampBuilder) Release() { 143 debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") 144 145 if atomic.AddInt64(&b.refCount, -1) == 0 { 146 if b.nullBitmap != nil { 147 b.nullBitmap.Release() 148 b.nullBitmap = nil 149 } 150 if b.data != nil { 151 b.data.Release() 152 b.data = nil 153 b.rawData = nil 154 } 155 } 156 } 157 158 func (b *TimestampBuilder) AppendTime(t time.Time) { 159 ts, err := arrow.TimestampFromTime(t, b.dtype.Unit) 160 if err != nil { 161 panic(err) 162 } 163 b.Append(ts) 164 } 165 166 func (b *TimestampBuilder) Append(v arrow.Timestamp) { 167 b.Reserve(1) 168 b.UnsafeAppend(v) 169 } 170 171 func (b *TimestampBuilder) AppendNull() { 172 b.Reserve(1) 173 b.UnsafeAppendBoolToBitmap(false) 174 } 175 176 func (b *TimestampBuilder) AppendNulls(n int) { 177 for i := 0; i < n; i++ { 178 b.AppendNull() 179 } 180 } 181 182 func (b *TimestampBuilder) AppendEmptyValue() { 183 b.Append(0) 184 } 185 186 func (b *TimestampBuilder) AppendEmptyValues(n int) { 187 for i := 0; i < n; i++ { 188 b.AppendEmptyValue() 189 } 190 } 191 192 func (b *TimestampBuilder) UnsafeAppend(v arrow.Timestamp) { 193 bitutil.SetBit(b.nullBitmap.Bytes(), b.length) 194 b.rawData[b.length] = v 195 b.length++ 196 } 197 198 func (b *TimestampBuilder) UnsafeAppendBoolToBitmap(isValid bool) { 199 if isValid { 200 bitutil.SetBit(b.nullBitmap.Bytes(), b.length) 201 } else { 202 b.nulls++ 203 } 204 b.length++ 205 } 206 207 // AppendValues will append the values in the v slice. The valid slice determines which values 208 // in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, 209 // all values in v are appended and considered valid. 210 func (b *TimestampBuilder) AppendValues(v []arrow.Timestamp, valid []bool) { 211 if len(v) != len(valid) && len(valid) != 0 { 212 panic("len(v) != len(valid) && len(valid) != 0") 213 } 214 215 if len(v) == 0 { 216 return 217 } 218 219 b.Reserve(len(v)) 220 arrow.TimestampTraits.Copy(b.rawData[b.length:], v) 221 b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) 222 } 223 224 func (b *TimestampBuilder) init(capacity int) { 225 b.builder.init(capacity) 226 227 b.data = memory.NewResizableBuffer(b.mem) 228 bytesN := arrow.TimestampTraits.BytesRequired(capacity) 229 b.data.Resize(bytesN) 230 b.rawData = arrow.TimestampTraits.CastFromBytes(b.data.Bytes()) 231 } 232 233 // Reserve ensures there is enough space for appending n elements 234 // by checking the capacity and calling Resize if necessary. 235 func (b *TimestampBuilder) Reserve(n int) { 236 b.builder.reserve(n, b.Resize) 237 } 238 239 // Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), 240 // additional memory will be allocated. If n is smaller, the allocated memory may reduced. 241 func (b *TimestampBuilder) Resize(n int) { 242 nBuilder := n 243 if n < minBuilderCapacity { 244 n = minBuilderCapacity 245 } 246 247 if b.capacity == 0 { 248 b.init(n) 249 } else { 250 b.builder.resize(nBuilder, b.init) 251 b.data.Resize(arrow.TimestampTraits.BytesRequired(n)) 252 b.rawData = arrow.TimestampTraits.CastFromBytes(b.data.Bytes()) 253 } 254 } 255 256 // NewArray creates a Timestamp array from the memory buffers used by the builder and resets the TimestampBuilder 257 // so it can be used to build a new array. 258 func (b *TimestampBuilder) NewArray() arrow.Array { 259 return b.NewTimestampArray() 260 } 261 262 // NewTimestampArray creates a Timestamp array from the memory buffers used by the builder and resets the TimestampBuilder 263 // so it can be used to build a new array. 264 func (b *TimestampBuilder) NewTimestampArray() (a *Timestamp) { 265 data := b.newData() 266 a = NewTimestampData(data) 267 data.Release() 268 return 269 } 270 271 func (b *TimestampBuilder) newData() (data *Data) { 272 bytesRequired := arrow.TimestampTraits.BytesRequired(b.length) 273 if bytesRequired > 0 && bytesRequired < b.data.Len() { 274 // trim buffers 275 b.data.Resize(bytesRequired) 276 } 277 data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) 278 b.reset() 279 280 if b.data != nil { 281 b.data.Release() 282 b.data = nil 283 b.rawData = nil 284 } 285 286 return 287 } 288 289 func (b *TimestampBuilder) AppendValueFromString(s string) error { 290 if s == NullValueStr { 291 b.AppendNull() 292 return nil 293 } 294 295 loc, err := b.dtype.GetZone() 296 if err != nil { 297 return err 298 } 299 300 v, _, err := arrow.TimestampFromStringInLocation(s, b.dtype.Unit, loc) 301 if err != nil { 302 b.AppendNull() 303 return err 304 } 305 b.Append(v) 306 return nil 307 } 308 309 func (b *TimestampBuilder) UnmarshalOne(dec *json.Decoder) error { 310 t, err := dec.Token() 311 if err != nil { 312 return err 313 } 314 315 switch v := t.(type) { 316 case nil: 317 b.AppendNull() 318 case string: 319 loc, _ := b.dtype.GetZone() 320 tm, _, err := arrow.TimestampFromStringInLocation(v, b.dtype.Unit, loc) 321 if err != nil { 322 return &json.UnmarshalTypeError{ 323 Value: v, 324 Type: reflect.TypeOf(arrow.Timestamp(0)), 325 Offset: dec.InputOffset(), 326 } 327 } 328 329 b.Append(tm) 330 case json.Number: 331 n, err := v.Int64() 332 if err != nil { 333 return &json.UnmarshalTypeError{ 334 Value: v.String(), 335 Type: reflect.TypeOf(arrow.Timestamp(0)), 336 Offset: dec.InputOffset(), 337 } 338 } 339 b.Append(arrow.Timestamp(n)) 340 case float64: 341 b.Append(arrow.Timestamp(v)) 342 343 default: 344 return &json.UnmarshalTypeError{ 345 Value: fmt.Sprint(t), 346 Type: reflect.TypeOf(arrow.Timestamp(0)), 347 Offset: dec.InputOffset(), 348 } 349 } 350 351 return nil 352 } 353 354 func (b *TimestampBuilder) Unmarshal(dec *json.Decoder) error { 355 for dec.More() { 356 if err := b.UnmarshalOne(dec); err != nil { 357 return err 358 } 359 } 360 return nil 361 } 362 363 func (b *TimestampBuilder) UnmarshalJSON(data []byte) error { 364 dec := json.NewDecoder(bytes.NewReader(data)) 365 t, err := dec.Token() 366 if err != nil { 367 return err 368 } 369 370 if delim, ok := t.(json.Delim); !ok || delim != '[' { 371 return fmt.Errorf("binary builder must unpack from json array, found %s", delim) 372 } 373 374 return b.Unmarshal(dec) 375 } 376 377 var ( 378 _ arrow.Array = (*Timestamp)(nil) 379 _ Builder = (*TimestampBuilder)(nil) 380 )