This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 3fad2ad4 fix(array): format date arrays in String (#1068)
3fad2ad4 is described below

commit 3fad2ad4ced30a7e293e4703c56b74c882eb811a
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 5 20:33:25 2026 +0200

    fix(array): format date arrays in String (#1068)
    
    Fixes #63
    
    ## Problem
    
    Date32 and Date64 arrays inherited the numeric array `String`
    implementation, so their values were rendered as raw integers instead of
    dates. This was inconsistent with their existing `ValueStr` and JSON
    formatting.
    
    ## Change
    
    Give date arrays a `String` implementation that formats each non-null
    value through `ValueStr`. Null markers, slice behavior, and the
    established array layout are preserved.
    
    ## Coverage
    
    The tests cover Date32, Date64, null values, negative dates, and sliced
    arrays. Generated builder expectations are updated to match the
    user-visible date representation.
    
    ## Validation
    
    `go test ./arrow/array`
---
 arrow/array/date_string_test.go             | 56 +++++++++++++++++++++++++++++
 arrow/array/numeric_generic.go              | 13 +++++++
 arrow/array/numericbuilder.gen_test.go      |  8 ++---
 arrow/array/numericbuilder.gen_test.go.tmpl |  6 ++--
 arrow/csv/reader_test.go                    |  8 ++---
 arrow/ipc/cmd/arrow-cat/main_test.go        | 36 +++++++++----------
 6 files changed, 97 insertions(+), 30 deletions(-)

diff --git a/arrow/array/date_string_test.go b/arrow/array/date_string_test.go
new file mode 100644
index 00000000..e0a28845
--- /dev/null
+++ b/arrow/array/date_string_test.go
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package array_test
+
+import (
+       "testing"
+
+       "github.com/apache/arrow-go/v18/arrow"
+       "github.com/apache/arrow-go/v18/arrow/array"
+       "github.com/apache/arrow-go/v18/arrow/memory"
+)
+
+func TestDateArrayString(t *testing.T) {
+       tests := []struct {
+               name  string
+               build func() arrow.Array
+               want  string
+       }{
+               {"date32", func() arrow.Array {
+                       b := array.NewDate32Builder(memory.DefaultAllocator)
+                       defer b.Release()
+                       b.AppendValues([]arrow.Date32{1, 2, 3}, []bool{true, 
false, true})
+                       return b.NewArray()
+               }, "[1970-01-02 (null) 1970-01-04]"},
+               {"date64", func() arrow.Array {
+                       b := array.NewDate64Builder(memory.DefaultAllocator)
+                       defer b.Release()
+                       b.AppendValues([]arrow.Date64{-86400000, 0, 86400000}, 
nil)
+                       return b.NewArray()
+               }, "[1969-12-31 1970-01-01 1970-01-02]"},
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       arr := tt.build()
+                       defer arr.Release()
+                       if got := arr.String(); got != tt.want {
+                               t.Fatalf("unexpected string: got %q, want %q", 
got, tt.want)
+                       }
+               })
+       }
+}
diff --git a/arrow/array/numeric_generic.go b/arrow/array/numeric_generic.go
index 1b671fc7..24edd549 100644
--- a/arrow/array/numeric_generic.go
+++ b/arrow/array/numeric_generic.go
@@ -173,6 +173,19 @@ type dateArray[T interface {
        numericArray[T]
 }
 
+func (d *dateArray[T]) String() string {
+       var b strings.Builder
+       b.WriteByte('[')
+       for i := range d.values {
+               if i > 0 {
+                       b.WriteByte(' ')
+               }
+               b.WriteString(d.ValueStr(i))
+       }
+       b.WriteByte(']')
+       return b.String()
+}
+
 func (d *dateArray[T]) MarshalJSON() ([]byte, error) {
        vals := make([]any, d.Len())
        for i := range d.values {
diff --git a/arrow/array/numericbuilder.gen_test.go 
b/arrow/array/numericbuilder.gen_test.go
index c54d8cf2..dccadcfe 100644
--- a/arrow/array/numericbuilder.gen_test.go
+++ b/arrow/array/numericbuilder.gen_test.go
@@ -3012,7 +3012,7 @@ func TestNewDate32Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.Date32")
        }
 
-       if got, want := a.String(), `[1 2 (null) 4]`; got != want {
+       if got, want := a.String(), `[1970-01-02 1970-01-03 (null) 
1970-01-05]`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
@@ -3027,7 +3027,7 @@ func TestNewDate32Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.Date32")
        }
 
-       if got, want := v.String(), `[(null) 4]`; got != want {
+       if got, want := v.String(), `[(null) 1970-01-05]`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
@@ -3258,7 +3258,7 @@ func TestNewDate64Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.Date64")
        }
 
-       if got, want := a.String(), `[1 2 (null) 4]`; got != want {
+       if got, want := a.String(), `[1970-01-01 1970-01-01 (null) 
1970-01-01]`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
@@ -3273,7 +3273,7 @@ func TestNewDate64Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.Date64")
        }
 
-       if got, want := v.String(), `[(null) 4]`; got != want {
+       if got, want := v.String(), `[(null) 1970-01-01]`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
diff --git a/arrow/array/numericbuilder.gen_test.go.tmpl 
b/arrow/array/numericbuilder.gen_test.go.tmpl
index e3422496..c655b764 100644
--- a/arrow/array/numericbuilder.gen_test.go.tmpl
+++ b/arrow/array/numericbuilder.gen_test.go.tmpl
@@ -161,7 +161,7 @@ func TestNew{{.Name}}Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.{{.Name}}")
        }
 
-       if got, want := a.String(), `[1 2 (null) 4]`; got != want {
+       if got, want := a.String(), `{{if eq .Name "Date32"}}[1970-01-02 
1970-01-03 (null) 1970-01-05]{{else if eq .Name "Date64"}}[1970-01-01 
1970-01-01 (null) 1970-01-01]{{else}}[1 2 (null) 4]{{end}}`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
@@ -176,7 +176,7 @@ func TestNew{{.Name}}Builder(t *testing.T) {
                t.Fatalf("could not type-assert to array.{{.Name}}")
        }
 
-       if got, want := v.String(), `[(null) 4]`; got != want {
+       if got, want := v.String(), `{{if eq .Name "Date32"}}[(null) 
1970-01-05]{{else if eq .Name "Date64"}}[(null) 1970-01-01]{{else}}[(null) 
4]{{end}}`; got != want {
                t.Fatalf("got=%q, want=%q", got, want)
        }
 
@@ -339,5 +339,3 @@ func Test{{.Name}}BuilderUnmarshalJSON(t *testing.T) {
 }
 
 {{end}}
-
-
diff --git a/arrow/csv/reader_test.go b/arrow/csv/reader_test.go
index acc516aa..80c78482 100644
--- a/arrow/csv/reader_test.go
+++ b/arrow/csv/reader_test.go
@@ -422,8 +422,8 @@ rec[0]["binary"]: ["\x00\x01\x02"]
 rec[0]["large_binary"]: ["\x00\x01\x02"]
 rec[0]["fixed_size_binary"]: ["\x00\x01\x02"]
 rec[0]["uuid"]: ["00000000-0000-0000-0000-000000000001"]
-rec[0]["date32"]: [19121]
-rec[0]["date64"]: [1652054400000]
+rec[0]["date32"]: [2022-05-09]
+rec[0]["date64"]: [2022-05-09]
 rec[1]["bool"]: [false]
 rec[1]["i8"]: [-2]
 rec[1]["i16"]: [-2]
@@ -446,8 +446,8 @@ rec[1]["binary"]: [(null)]
 rec[1]["large_binary"]: [(null)]
 rec[1]["fixed_size_binary"]: [(null)]
 rec[1]["uuid"]: ["00000000-0000-0000-0000-000000000002"]
-rec[1]["date32"]: [19121]
-rec[1]["date64"]: [1652054400000]
+rec[1]["date32"]: [2022-05-09]
+rec[1]["date64"]: [2022-05-09]
 rec[2]["bool"]: [(null)]
 rec[2]["i8"]: [(null)]
 rec[2]["i16"]: [(null)]
diff --git a/arrow/ipc/cmd/arrow-cat/main_test.go 
b/arrow/ipc/cmd/arrow-cat/main_test.go
index 78b3853c..7c8bcea0 100644
--- a/arrow/ipc/cmd/arrow-cat/main_test.go
+++ b/arrow/ipc/cmd/arrow-cat/main_test.go
@@ -131,8 +131,8 @@ record 3...
   col[6] "timestamp_ms": [0 (null) (null) 3 4]
   col[7] "timestamp_us": [0 (null) (null) 3 4]
   col[8] "timestamp_ns": [0 (null) (null) 3 4]
-  col[9] "date32s": [-2 (null) (null) 1 2]
-  col[10] "date64s": [-2 (null) (null) 1 2]
+  col[9] "date32s": [1969-12-30 (null) (null) 1970-01-02 1970-01-03]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 2...
   col[0] "float16s": [11 (null) (null) 14 15]
   col[1] "time32ms": [-12 (null) (null) 11 12]
@@ -143,8 +143,8 @@ record 2...
   col[6] "timestamp_ms": [10 (null) (null) 13 14]
   col[7] "timestamp_us": [10 (null) (null) 13 14]
   col[8] "timestamp_ns": [10 (null) (null) 13 14]
-  col[9] "date32s": [-12 (null) (null) 11 12]
-  col[10] "date64s": [-12 (null) (null) 11 12]
+  col[9] "date32s": [1969-12-20 (null) (null) 1970-01-12 1970-01-13]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 3...
   col[0] "float16s": [21 (null) (null) 24 25]
   col[1] "time32ms": [-22 (null) (null) 21 22]
@@ -155,8 +155,8 @@ record 3...
   col[6] "timestamp_ms": [20 (null) (null) 23 24]
   col[7] "timestamp_us": [20 (null) (null) 23 24]
   col[8] "timestamp_ns": [20 (null) (null) 23 24]
-  col[9] "date32s": [-22 (null) (null) 21 22]
-  col[10] "date64s": [-22 (null) (null) 21 22]
+  col[9] "date32s": [1969-12-10 (null) (null) 1970-01-22 1970-01-23]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 `,
                },
                {
@@ -448,8 +448,8 @@ record 3/3...
   col[6] "timestamp_ms": [0 (null) (null) 3 4]
   col[7] "timestamp_us": [0 (null) (null) 3 4]
   col[8] "timestamp_ns": [0 (null) (null) 3 4]
-  col[9] "date32s": [-2 (null) (null) 1 2]
-  col[10] "date64s": [-2 (null) (null) 1 2]
+  col[9] "date32s": [1969-12-30 (null) (null) 1970-01-02 1970-01-03]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 2...
   col[0] "float16s": [11 (null) (null) 14 15]
   col[1] "time32ms": [-12 (null) (null) 11 12]
@@ -460,8 +460,8 @@ record 2...
   col[6] "timestamp_ms": [10 (null) (null) 13 14]
   col[7] "timestamp_us": [10 (null) (null) 13 14]
   col[8] "timestamp_ns": [10 (null) (null) 13 14]
-  col[9] "date32s": [-12 (null) (null) 11 12]
-  col[10] "date64s": [-12 (null) (null) 11 12]
+  col[9] "date32s": [1969-12-20 (null) (null) 1970-01-12 1970-01-13]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 3...
   col[0] "float16s": [21 (null) (null) 24 25]
   col[1] "time32ms": [-22 (null) (null) 21 22]
@@ -472,8 +472,8 @@ record 3...
   col[6] "timestamp_ms": [20 (null) (null) 23 24]
   col[7] "timestamp_us": [20 (null) (null) 23 24]
   col[8] "timestamp_ns": [20 (null) (null) 23 24]
-  col[9] "date32s": [-22 (null) (null) 21 22]
-  col[10] "date64s": [-22 (null) (null) 21 22]
+  col[9] "date32s": [1969-12-10 (null) (null) 1970-01-22 1970-01-23]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 `,
                },
                {
@@ -489,8 +489,8 @@ record 1/3...
   col[6] "timestamp_ms": [0 (null) (null) 3 4]
   col[7] "timestamp_us": [0 (null) (null) 3 4]
   col[8] "timestamp_ns": [0 (null) (null) 3 4]
-  col[9] "date32s": [-2 (null) (null) 1 2]
-  col[10] "date64s": [-2 (null) (null) 1 2]
+  col[9] "date32s": [1969-12-30 (null) (null) 1970-01-02 1970-01-03]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 2/3...
   col[0] "float16s": [11 (null) (null) 14 15]
   col[1] "time32ms": [-12 (null) (null) 11 12]
@@ -501,8 +501,8 @@ record 2/3...
   col[6] "timestamp_ms": [10 (null) (null) 13 14]
   col[7] "timestamp_us": [10 (null) (null) 13 14]
   col[8] "timestamp_ns": [10 (null) (null) 13 14]
-  col[9] "date32s": [-12 (null) (null) 11 12]
-  col[10] "date64s": [-12 (null) (null) 11 12]
+  col[9] "date32s": [1969-12-20 (null) (null) 1970-01-12 1970-01-13]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 record 3/3...
   col[0] "float16s": [21 (null) (null) 24 25]
   col[1] "time32ms": [-22 (null) (null) 21 22]
@@ -513,8 +513,8 @@ record 3/3...
   col[6] "timestamp_ms": [20 (null) (null) 23 24]
   col[7] "timestamp_us": [20 (null) (null) 23 24]
   col[8] "timestamp_ns": [20 (null) (null) 23 24]
-  col[9] "date32s": [-22 (null) (null) 21 22]
-  col[10] "date64s": [-22 (null) (null) 21 22]
+  col[9] "date32s": [1969-12-10 (null) (null) 1970-01-22 1970-01-23]
+  col[10] "date64s": [1970-01-01 (null) (null) 1970-01-01 1970-01-01]
 `,
                },
                {

Reply via email to