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

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


The following commit(s) were added to refs/heads/main by this push:
     new c711561fe9 fix(c/driver/sqlite): format extreme time/date values 
properly (#4841)
c711561fe9 is described below

commit c711561fe929d9426249176761805306183af3a5
Author: David Li <[email protected]>
AuthorDate: Wed Sep 30 16:14:23 2026 -0700

    fix(c/driver/sqlite): format extreme time/date values properly (#4841)
    
    This is already tested by/discovered via the validation suite.
    
    Generated-by: GPT-6 Astra
---
 c/driver/sqlite/statement_reader.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/c/driver/sqlite/statement_reader.c 
b/c/driver/sqlite/statement_reader.c
index 7c2cae682c..96bcbae96b 100644
--- a/c/driver/sqlite/statement_reader.c
+++ b/c/driver/sqlite/statement_reader.c
@@ -143,7 +143,7 @@ static AdbcStatusCode ArrowDate32ToIsoString(int32_t value, 
char** buf,
   }
   time_t time = (time_t)(value * SECONDS_PER_DAY);
 #else
-  time_t time = value * SECONDS_PER_DAY;
+  time_t time = (int64_t)value * SECONDS_PER_DAY;
 #endif
 
   struct tm broken_down_time;
@@ -169,9 +169,14 @@ static AdbcStatusCode ArrowDate32ToIsoString(int32_t 
value, char** buf,
     return ADBC_STATUS_IO;
   }
 
-  if (strftime(tsstr, strlen + 1, "%Y-%m-%d", &broken_down_time) == 0) {
-    InternalAdbcSetError(error, "Call to strftime for date %" PRId32 " with 
failed",
-                         value);
+  // Whether %Y pads years < 1000 is platform dependent
+  // https://github.com/python/cpython/issues/120713
+  // Specifiers like %04Y are not portable; format manually instead
+  int written = snprintf(tsstr, strlen + 1, "%04" PRId64 "-%02d-%02d",
+                         (int64_t)broken_down_time.tm_year + 1900,
+                         broken_down_time.tm_mon + 1, 
broken_down_time.tm_mday);
+  if (written != strlen) {
+    InternalAdbcSetError(error, "Could not format date %" PRId32, value);
     free(tsstr);
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
@@ -207,14 +212,14 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t 
value, enum ArrowTimeUni
       break;
   }
 
+  int64_t seconds = value / scale;
   rem = value % scale;
   if (rem < 0) {
-    value -= scale;
+    // Floor the quotient without subtracting from a possibly INT64_MIN value.
+    seconds--;
     rem = scale + rem;
   }
 
-  const int64_t seconds = value / scale;
-
 #if SIZEOF_TIME_T < 8
   if ((seconds > INT32_MAX) || (seconds < INT32_MIN)) {
     InternalAdbcSetError(
@@ -253,9 +258,14 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t 
value, enum ArrowTimeUni
     return ADBC_STATUS_IO;
   }
 
-  if (strftime(tsstr, strlen, "%Y-%m-%dT%H:%M:%S", &broken_down_time) == 0) {
-    InternalAdbcSetError(error,
-                         "Call to strftime for timestamp %" PRId64 " with unit 
%d failed",
+  // %Y does not consistently pad early years across platforms (see above)
+  int written =
+      snprintf(tsstr, strlen + 1, "%04" PRId64 "-%02d-%02dT%02d:%02d:%02d",
+               (int64_t)broken_down_time.tm_year + 1900, 
broken_down_time.tm_mon + 1,
+               broken_down_time.tm_mday, broken_down_time.tm_hour,
+               broken_down_time.tm_min, broken_down_time.tm_sec);
+  if (written != 19) {
+    InternalAdbcSetError(error, "Could not format timestamp %" PRId64 " with 
unit %d",
                          value, unit);
     free(tsstr);
     return ADBC_STATUS_INVALID_ARGUMENT;

Reply via email to