andygrove opened a new pull request, #6351:
URL: https://github.com/apache/datafusion-comet/pull/6351

   ## Which issue does this PR close?
   
   Closes #6329.
   
   ## Rationale for this change
   
   Comet passed the session timezone to native code as the raw string stamped 
on each expression. Native code parses that string with arrow's `Tz::from_str`, 
which only accepts:
   
   - IANA zone names
   - offsets written as `+HH`, `+HHMM` or `+HH:MM`
   
   Spark resolves the ID with `ZoneId.of(id, ZoneId.SHORT_IDS)`, which also 
accepts:
   
   - `Z`
   - offsets such as `+8` and `+08:00:00`
   - prefixed offsets such as `GMT+8` and `UTC+08:00`
   - short IDs such as `PST` and `IST`
   
   The `spark.sql.session.timeZone` documentation lists `Z` and `(+|-)HH:mm:ss` 
explicitly. With any of these IDs, most timestamp expressions failed at 
execution time with `Parser error: Invalid timezone "GMT+8"`. That covered 
`CAST(ts AS STRING/DATE)`, `hour`, `year`, string- and date-to-timestamp casts, 
`unix_timestamp` of a date, casts between `TIMESTAMP` and `TIMESTAMP_NTZ`, and 
`df.show()`. `GMT+8` in particular is a common production setting.
   
   ## What changes are included in this PR?
   
   - A new `CometTimeZone.nativeId` normalizes the stamped timezone into an ID 
native code parses. It uses Spark's own `DateTimeUtils.getZoneId`, then 
`ZoneId.normalized()`:
     - fixed offsets become `+HH:MM`
     - zero offsets become `UTC`
     - short IDs become their region
     - an expression with no timezone gets `UTC`, since Spark only leaves it 
unset on casts that don't use one (the measurement is in #6335)
   - An offset with seconds, such as `+05:45:30`, can't be written for native 
code. `nativeId` returns `None` for it, and the serde reports the expression as 
unsupported. The cast then goes through the codegen dispatcher, and expressions 
without a dispatcher path fall back.
   - Every serde that sends a timezone to native code now goes through the 
helper. That covers `Cast`, `hour`, `minute`, `second`, `unix_timestamp`, 
`date_trunc`, `from_unixtime`, `to_json`, `from_json`, `to_csv`, 
`ToPrettyString` (both shims) and the native Parquet scan's session timezone. 
These were the `getOrElse("UTC")` sites that #2730 asked about.
   - `date_trunc` and `date_format` decide "is this session UTC" through the 
same helper. `GMT`, `Z` and `+00:00` sessions now take their native UTC paths 
as well.
   - `CometDays` is left alone, because #6348 moves it to UTC.
   
   ## How are these changes tested?
   
   - **New tests:**
     - A unit test in `CometTemporalExpressionSuite` for the normalization.
     - `session_timezone_ids.sql`, which runs casts, field extraction, 
`unix_timestamp`, `TIMESTAMP_NTZ` casts, `date_trunc` and `date_format` under 
`GMT+8`, `UTC+08:00`, `+8`, `-08`, `+08:00:00`, `Z`, `PST` and `IST`.
     - `session_timezone_ids_unsupported.sql`, which covers `+05:45:30`.
   - **Before the change:** with `main`'s serdes, `session_timezone_ids.sql` 
fails for every timezone except `-08`, which arrow already parses. The 
unsupported file fails too.
   - **With the change on Spark 4.1:** all 200 tests in these suites pass, with 
the `spotless` and `scalastyle` checks included:
     - `CometTemporalExpressionSuite`
     - every `expressions/datetime/` SQL file test
     - `CometJsonExpressionSuite`
     - `CometCsvExpressionSuite`
   - **Casts:** all 185 `CometNativeCastSuite` tests pass on Spark 4.1.
   - **Spark 3.5:** the new tests pass on Spark 3.5 as well, which also 
compiles the 3.5 `ToPrettyString` shim.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to