diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal.cc b/cpp/src/arrow/compute/kernels/scalar_temporal.cc index f0257772d4a..b6cabddd118 100644 --- a/cpp/src/arrow/compute/kernels/scalar_temporal.cc +++ b/cpp/src/arrow/compute/kernels/scalar_temporal.cc @@ -35,7 +35,12 @@ namespace { using arrow_vendored::date::days; using arrow_vendored::date::floor; using arrow_vendored::date::hh_mm_ss; +using arrow_vendored::date::local_days; +using arrow_vendored::date::local_time; +using arrow_vendored::date::locate_zone; +using arrow_vendored::date::sys_days; using arrow_vendored::date::sys_time; +using arrow_vendored::date::time_zone; using arrow_vendored::date::trunc; using arrow_vendored::date::weekday; using arrow_vendored::date::weeks; @@ -51,6 +56,12 @@ using internal::applicator::SimpleUnary; using DayOfWeekState = OptionsWrapper; +const std::shared_ptr& IsoCalendarType() { + static auto type = struct_({field("iso_year", int64()), field("iso_week", int64()), + field("iso_day_of_week", int64())}); + return type; +} + const std::string& GetInputTimezone(const Datum& datum) { return checked_cast(*datum.type()).timezone(); } @@ -63,29 +74,79 @@ const std::string& GetInputTimezone(const ArrayData& array) { return checked_cast(*array.type).timezone(); } -template -Status TemporalComponentExtractCheckTimezone(const T& input) { - const auto& timezone = GetInputTimezone(input); - if (!timezone.empty()) { - return Status::NotImplemented( - "Cannot extract components from timestamp with specific timezone: ", timezone); +struct NonZonedLocalizer { + // No-op conversions: UTC -> UTC + template + sys_time ConvertTimePoint(int64_t t) const { + return sys_time(Duration{t}); + } + + sys_days ConvertDays(sys_days d) const { return d; } +}; + +struct ZonedLocalizer { + // Timezone-localizing conversions: UTC -> local time + const time_zone* tz; + + template + local_time ConvertTimePoint(int64_t t) const { + return tz->to_local(sys_time(Duration{t})); } - return Status::OK(); -} -template -struct TemporalComponentExtract { - using OutValue = typename internal::GetOutputType::T; + local_days ConvertDays(sys_days d) const { return local_days(year_month_day(d)); } +}; + +// +// Executor class for temporal component extractors, i.e. scalar kernels +// with the signature Timestamp -> +// +// The `Op` parameter is templated on the Duration (which depends on the timestamp +// unit) and a Localizer class (depending on whether the timestamp has a +// timezone defined). +// +template