]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/cpp/src/arrow/compute/kernels/scalar_cast_temporal.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / compute / kernels / scalar_cast_temporal.cc
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,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 // Implementation of casting to (or between) temporal types
19
20 #include <limits>
21
22 #include "arrow/array/builder_time.h"
23 #include "arrow/compute/kernels/common.h"
24 #include "arrow/compute/kernels/scalar_cast_internal.h"
25 #include "arrow/compute/kernels/temporal_internal.h"
26 #include "arrow/util/bitmap_reader.h"
27 #include "arrow/util/time.h"
28 #include "arrow/util/value_parsing.h"
29
30 namespace arrow {
31
32 using internal::ParseValue;
33
34 namespace compute {
35 namespace internal {
36
37 constexpr int64_t kMillisecondsInDay = 86400000;
38
39 // ----------------------------------------------------------------------
40 // From one timestamp to another
41
42 template <typename in_type, typename out_type>
43 Status ShiftTime(KernelContext* ctx, const util::DivideOrMultiply factor_op,
44 const int64_t factor, const ArrayData& input, ArrayData* output) {
45 const CastOptions& options = checked_cast<const CastState&>(*ctx->state()).options;
46 auto in_data = input.GetValues<in_type>(1);
47 auto out_data = output->GetMutableValues<out_type>(1);
48
49 if (factor == 1) {
50 for (int64_t i = 0; i < input.length; i++) {
51 out_data[i] = static_cast<out_type>(in_data[i]);
52 }
53 } else if (factor_op == util::MULTIPLY) {
54 if (options.allow_time_overflow) {
55 for (int64_t i = 0; i < input.length; i++) {
56 out_data[i] = static_cast<out_type>(in_data[i] * factor);
57 }
58 } else {
59 #define RAISE_OVERFLOW_CAST(VAL) \
60 return Status::Invalid("Casting from ", input.type->ToString(), " to ", \
61 output->type->ToString(), " would result in ", \
62 "out of bounds timestamp: ", VAL);
63
64 int64_t max_val = std::numeric_limits<int64_t>::max() / factor;
65 int64_t min_val = std::numeric_limits<int64_t>::min() / factor;
66 if (input.null_count != 0) {
67 BitmapReader bit_reader(input.buffers[0]->data(), input.offset, input.length);
68 for (int64_t i = 0; i < input.length; i++) {
69 if (bit_reader.IsSet() && (in_data[i] < min_val || in_data[i] > max_val)) {
70 RAISE_OVERFLOW_CAST(in_data[i]);
71 }
72 out_data[i] = static_cast<out_type>(in_data[i] * factor);
73 bit_reader.Next();
74 }
75 } else {
76 for (int64_t i = 0; i < input.length; i++) {
77 if (in_data[i] < min_val || in_data[i] > max_val) {
78 RAISE_OVERFLOW_CAST(in_data[i]);
79 }
80 out_data[i] = static_cast<out_type>(in_data[i] * factor);
81 }
82 }
83
84 #undef RAISE_OVERFLOW_CAST
85 }
86 } else {
87 if (options.allow_time_truncate) {
88 for (int64_t i = 0; i < input.length; i++) {
89 out_data[i] = static_cast<out_type>(in_data[i] / factor);
90 }
91 } else {
92 #define RAISE_INVALID_CAST(VAL) \
93 return Status::Invalid("Casting from ", input.type->ToString(), " to ", \
94 output->type->ToString(), " would lose data: ", VAL);
95
96 if (input.null_count != 0) {
97 BitmapReader bit_reader(input.buffers[0]->data(), input.offset, input.length);
98 for (int64_t i = 0; i < input.length; i++) {
99 out_data[i] = static_cast<out_type>(in_data[i] / factor);
100 if (bit_reader.IsSet() && (out_data[i] * factor != in_data[i])) {
101 RAISE_INVALID_CAST(in_data[i]);
102 }
103 bit_reader.Next();
104 }
105 } else {
106 for (int64_t i = 0; i < input.length; i++) {
107 out_data[i] = static_cast<out_type>(in_data[i] / factor);
108 if (out_data[i] * factor != in_data[i]) {
109 RAISE_INVALID_CAST(in_data[i]);
110 }
111 }
112 }
113
114 #undef RAISE_INVALID_CAST
115 }
116 }
117
118 return Status::OK();
119 }
120
121 template <template <typename...> class Op, typename OutType, typename... Args>
122 Status ExtractTemporal(KernelContext* ctx, const ExecBatch& batch, Datum* out,
123 Args... args) {
124 const auto& ty = checked_cast<const TimestampType&>(*batch[0].type());
125
126 switch (ty.unit()) {
127 case TimeUnit::SECOND:
128 return TemporalComponentExtract<Op, std::chrono::seconds, TimestampType, OutType,
129 Args...>::Exec(ctx, batch, out, args...);
130 case TimeUnit::MILLI:
131 return TemporalComponentExtract<Op, std::chrono::milliseconds, TimestampType,
132 OutType, Args...>::Exec(ctx, batch, out, args...);
133 case TimeUnit::MICRO:
134 return TemporalComponentExtract<Op, std::chrono::microseconds, TimestampType,
135 OutType, Args...>::Exec(ctx, batch, out, args...);
136 case TimeUnit::NANO:
137 return TemporalComponentExtract<Op, std::chrono::nanoseconds, TimestampType,
138 OutType, Args...>::Exec(ctx, batch, out, args...);
139 }
140 return Status::Invalid("Unknown timestamp unit: ", ty);
141 }
142
143 // <TimestampType, TimestampType> and <DurationType, DurationType>
144 template <typename O, typename I>
145 struct CastFunctor<
146 O, I,
147 enable_if_t<(is_timestamp_type<O>::value && is_timestamp_type<I>::value) ||
148 (is_duration_type<O>::value && is_duration_type<I>::value)>> {
149 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
150 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
151
152 const ArrayData& input = *batch[0].array();
153 ArrayData* output = out->mutable_array();
154
155 // If units are the same, zero copy, otherwise convert
156 const auto& in_type = checked_cast<const I&>(*batch[0].type());
157 const auto& out_type = checked_cast<const O&>(*output->type);
158
159 // The units may be equal if the time zones are different. We might go to
160 // lengths to make this zero copy in the future but we leave it for now
161
162 auto conversion = util::GetTimestampConversion(in_type.unit(), out_type.unit());
163 return ShiftTime<int64_t, int64_t>(ctx, conversion.first, conversion.second, input,
164 output);
165 }
166 };
167
168 // ----------------------------------------------------------------------
169 // From timestamp to date32 or date64
170
171 template <>
172 struct CastFunctor<Date32Type, TimestampType> {
173 template <typename Duration, typename Localizer>
174 struct Date32 {
175 Date32(const FunctionOptions* options, Localizer&& localizer)
176 : localizer_(std::move(localizer)) {}
177
178 template <typename T, typename Arg0>
179 T Call(KernelContext*, Arg0 arg, Status*) const {
180 return static_cast<T>(static_cast<const int32_t>(
181 floor<days>(localizer_.template ConvertTimePoint<Duration>(arg))
182 .time_since_epoch()
183 .count()));
184 }
185
186 Localizer localizer_;
187 };
188
189 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
190 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
191 return ExtractTemporal<Date32, Date32Type>(ctx, batch, out);
192 }
193 };
194
195 template <>
196 struct CastFunctor<Date64Type, TimestampType> {
197 template <typename Duration, typename Localizer>
198 struct Date64 {
199 constexpr static int64_t kMillisPerDay = 86400000;
200 Date64(const FunctionOptions* options, Localizer&& localizer)
201 : localizer_(std::move(localizer)) {}
202
203 template <typename T, typename Arg0>
204 T Call(KernelContext*, Arg0 arg, Status*) const {
205 return static_cast<T>(
206 kMillisPerDay *
207 static_cast<const int32_t>(
208 floor<days>(localizer_.template ConvertTimePoint<Duration>(arg))
209 .time_since_epoch()
210 .count()));
211 }
212
213 Localizer localizer_;
214 };
215
216 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
217 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
218 return ExtractTemporal<Date64, Date64Type>(ctx, batch, out);
219 }
220 };
221
222 // ----------------------------------------------------------------------
223 // From timestamp to time32 or time64
224
225 template <typename Duration, typename Localizer>
226 struct ExtractTimeDownscaled {
227 ExtractTimeDownscaled(const FunctionOptions* options, Localizer&& localizer,
228 const int64_t factor)
229 : localizer_(std::move(localizer)), factor_(factor) {}
230
231 template <typename T, typename Arg0>
232 T Call(KernelContext*, Arg0 arg, Status* st) const {
233 const auto t = localizer_.template ConvertTimePoint<Duration>(arg);
234 const int64_t orig_value = (t - floor<days>(t)).count();
235 const T scaled = static_cast<T>(orig_value / factor_);
236 const int64_t unscaled = static_cast<int64_t>(scaled) * factor_;
237 if (unscaled != orig_value) {
238 *st = Status::Invalid("Cast would lose data: ", orig_value);
239 return 0;
240 }
241 return scaled;
242 }
243
244 Localizer localizer_;
245 const int64_t factor_;
246 };
247
248 template <typename Duration, typename Localizer>
249 struct ExtractTimeUpscaledUnchecked {
250 ExtractTimeUpscaledUnchecked(const FunctionOptions* options, Localizer&& localizer,
251 const int64_t factor)
252 : localizer_(std::move(localizer)), factor_(factor) {}
253
254 template <typename T, typename Arg0>
255 T Call(KernelContext*, Arg0 arg, Status*) const {
256 const auto t = localizer_.template ConvertTimePoint<Duration>(arg);
257 const int64_t orig_value = (t - floor<days>(t)).count();
258 return static_cast<T>(orig_value * factor_);
259 }
260
261 Localizer localizer_;
262 const int64_t factor_;
263 };
264
265 template <typename Duration, typename Localizer>
266 struct ExtractTimeDownscaledUnchecked {
267 ExtractTimeDownscaledUnchecked(const FunctionOptions* options, Localizer&& localizer,
268 const int64_t factor)
269 : localizer_(std::move(localizer)), factor_(factor) {}
270
271 template <typename T, typename Arg0>
272 T Call(KernelContext*, Arg0 arg, Status*) const {
273 const auto t = localizer_.template ConvertTimePoint<Duration>(arg);
274 const int64_t orig_value = (t - floor<days>(t)).count();
275 return static_cast<T>(orig_value / factor_);
276 }
277
278 Localizer localizer_;
279 const int64_t factor_;
280 };
281
282 template <>
283 struct CastFunctor<Time32Type, TimestampType> {
284 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
285 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
286 const auto& in_type = checked_cast<const TimestampType&>(*batch[0].type());
287 const auto& out_type = checked_cast<const Time32Type&>(*out->type());
288 const CastOptions& options = checked_cast<const CastState&>(*ctx->state()).options;
289
290 // Shifting before extraction won't work since the timestamp may not fit
291 // even if the time itself fits
292 if (in_type.unit() != out_type.unit()) {
293 auto conversion = util::GetTimestampConversion(in_type.unit(), out_type.unit());
294 if (conversion.first == util::MULTIPLY) {
295 return ExtractTemporal<ExtractTimeUpscaledUnchecked, Time32Type>(
296 ctx, batch, out, conversion.second);
297 } else {
298 if (options.allow_time_truncate) {
299 return ExtractTemporal<ExtractTimeDownscaledUnchecked, Time32Type>(
300 ctx, batch, out, conversion.second);
301 } else {
302 return ExtractTemporal<ExtractTimeDownscaled, Time32Type>(ctx, batch, out,
303 conversion.second);
304 }
305 }
306 }
307 return ExtractTemporal<ExtractTimeUpscaledUnchecked, Time32Type>(ctx, batch, out, 1);
308 }
309 };
310
311 template <>
312 struct CastFunctor<Time64Type, TimestampType> {
313 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
314 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
315 const auto& in_type = checked_cast<const TimestampType&>(*batch[0].type());
316 const auto& out_type = checked_cast<const Time64Type&>(*out->type());
317 const CastOptions& options = checked_cast<const CastState&>(*ctx->state()).options;
318
319 // Shifting before extraction won't work since the timestamp may not fit
320 // even if the time itself fits
321 if (in_type.unit() != out_type.unit()) {
322 auto conversion = util::GetTimestampConversion(in_type.unit(), out_type.unit());
323 if (conversion.first == util::MULTIPLY) {
324 return ExtractTemporal<ExtractTimeUpscaledUnchecked, Time64Type>(
325 ctx, batch, out, conversion.second);
326 } else {
327 if (options.allow_time_truncate) {
328 return ExtractTemporal<ExtractTimeDownscaledUnchecked, Time64Type>(
329 ctx, batch, out, conversion.second);
330 } else {
331 return ExtractTemporal<ExtractTimeDownscaled, Time64Type>(ctx, batch, out,
332 conversion.second);
333 }
334 }
335 }
336 return ExtractTemporal<ExtractTimeUpscaledUnchecked, Time64Type>(ctx, batch, out, 1);
337 }
338 };
339
340 // ----------------------------------------------------------------------
341 // From one time32 or time64 to another
342
343 template <typename O, typename I>
344 struct CastFunctor<O, I, enable_if_t<is_time_type<I>::value && is_time_type<O>::value>> {
345 using in_t = typename I::c_type;
346 using out_t = typename O::c_type;
347
348 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
349 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
350
351 const ArrayData& input = *batch[0].array();
352 ArrayData* output = out->mutable_array();
353
354 // If units are the same, zero copy, otherwise convert
355 const auto& in_type = checked_cast<const I&>(*input.type);
356 const auto& out_type = checked_cast<const O&>(*output->type);
357 DCHECK_NE(in_type.unit(), out_type.unit()) << "Do not cast equal types";
358 auto conversion = util::GetTimestampConversion(in_type.unit(), out_type.unit());
359 return ShiftTime<in_t, out_t>(ctx, conversion.first, conversion.second, input,
360 output);
361 }
362 };
363
364 // ----------------------------------------------------------------------
365 // Between date32 and date64
366
367 template <>
368 struct CastFunctor<Date64Type, Date32Type> {
369 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
370 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
371
372 return ShiftTime<int32_t, int64_t>(ctx, util::MULTIPLY, kMillisecondsInDay,
373 *batch[0].array(), out->mutable_array());
374 }
375 };
376
377 template <>
378 struct CastFunctor<Date32Type, Date64Type> {
379 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
380 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
381
382 return ShiftTime<int64_t, int32_t>(ctx, util::DIVIDE, kMillisecondsInDay,
383 *batch[0].array(), out->mutable_array());
384 }
385 };
386
387 // ----------------------------------------------------------------------
388 // date32, date64 to timestamp
389
390 template <>
391 struct CastFunctor<TimestampType, Date32Type> {
392 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
393 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
394
395 const auto& out_type = checked_cast<const TimestampType&>(*out->type());
396 // get conversion SECOND -> unit
397 auto conversion = util::GetTimestampConversion(TimeUnit::SECOND, out_type.unit());
398 DCHECK_EQ(conversion.first, util::MULTIPLY);
399
400 // multiply to achieve days -> unit
401 conversion.second *= kMillisecondsInDay / 1000;
402 return ShiftTime<int32_t, int64_t>(ctx, util::MULTIPLY, conversion.second,
403 *batch[0].array(), out->mutable_array());
404 }
405 };
406
407 template <>
408 struct CastFunctor<TimestampType, Date64Type> {
409 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
410 DCHECK_EQ(batch[0].kind(), Datum::ARRAY);
411
412 const auto& out_type = checked_cast<const TimestampType&>(*out->type());
413
414 // date64 is ms since epoch
415 auto conversion = util::GetTimestampConversion(TimeUnit::MILLI, out_type.unit());
416 return ShiftTime<int64_t, int64_t>(ctx, conversion.first, conversion.second,
417 *batch[0].array(), out->mutable_array());
418 }
419 };
420
421 // ----------------------------------------------------------------------
422 // String to Timestamp
423
424 struct ParseTimestamp {
425 template <typename OutValue, typename Arg0Value>
426 OutValue Call(KernelContext*, Arg0Value val, Status* st) const {
427 OutValue result = 0;
428 if (ARROW_PREDICT_FALSE(!ParseValue(type, val.data(), val.size(), &result))) {
429 *st = Status::Invalid("Failed to parse string: '", val, "' as a scalar of type ",
430 type.ToString());
431 }
432 return result;
433 }
434
435 const TimestampType& type;
436 };
437
438 template <typename I>
439 struct CastFunctor<TimestampType, I, enable_if_t<is_base_binary_type<I>::value>> {
440 static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
441 const auto& out_type = checked_cast<const TimestampType&>(*out->type());
442 applicator::ScalarUnaryNotNullStateful<TimestampType, I, ParseTimestamp> kernel(
443 ParseTimestamp{out_type});
444 return kernel.Exec(ctx, batch, out);
445 }
446 };
447
448 template <typename Type>
449 void AddCrossUnitCast(CastFunction* func) {
450 ScalarKernel kernel;
451 kernel.exec = TrivialScalarUnaryAsArraysExec(CastFunctor<Type, Type>::Exec);
452 kernel.signature = KernelSignature::Make({InputType(Type::type_id)}, kOutputTargetType);
453 DCHECK_OK(func->AddKernel(Type::type_id, std::move(kernel)));
454 }
455
456 std::shared_ptr<CastFunction> GetDate32Cast() {
457 auto func = std::make_shared<CastFunction>("cast_date32", Type::DATE32);
458 auto out_ty = date32();
459 AddCommonCasts(Type::DATE32, out_ty, func.get());
460
461 // int32 -> date32
462 AddZeroCopyCast(Type::INT32, int32(), date32(), func.get());
463
464 // date64 -> date32
465 AddSimpleCast<Date64Type, Date32Type>(date64(), date32(), func.get());
466
467 // timestamp -> date32
468 AddSimpleCast<TimestampType, Date32Type>(InputType(Type::TIMESTAMP), date32(),
469 func.get());
470 return func;
471 }
472
473 std::shared_ptr<CastFunction> GetDate64Cast() {
474 auto func = std::make_shared<CastFunction>("cast_date64", Type::DATE64);
475 auto out_ty = date64();
476 AddCommonCasts(Type::DATE64, out_ty, func.get());
477
478 // int64 -> date64
479 AddZeroCopyCast(Type::INT64, int64(), date64(), func.get());
480
481 // date32 -> date64
482 AddSimpleCast<Date32Type, Date64Type>(date32(), date64(), func.get());
483
484 // timestamp -> date64
485 AddSimpleCast<TimestampType, Date64Type>(InputType(Type::TIMESTAMP), date64(),
486 func.get());
487 return func;
488 }
489
490 std::shared_ptr<CastFunction> GetDurationCast() {
491 auto func = std::make_shared<CastFunction>("cast_duration", Type::DURATION);
492 AddCommonCasts(Type::DURATION, kOutputTargetType, func.get());
493
494 auto seconds = duration(TimeUnit::SECOND);
495 auto millis = duration(TimeUnit::MILLI);
496 auto micros = duration(TimeUnit::MICRO);
497 auto nanos = duration(TimeUnit::NANO);
498
499 // Same integer representation
500 AddZeroCopyCast(Type::INT64, /*in_type=*/int64(), kOutputTargetType, func.get());
501
502 // Between durations
503 AddCrossUnitCast<DurationType>(func.get());
504
505 return func;
506 }
507
508 std::shared_ptr<CastFunction> GetIntervalCast() {
509 auto func = std::make_shared<CastFunction>("cast_month_day_nano_interval",
510 Type::INTERVAL_MONTH_DAY_NANO);
511 AddCommonCasts(Type::INTERVAL_MONTH_DAY_NANO, kOutputTargetType, func.get());
512 return func;
513 }
514
515 std::shared_ptr<CastFunction> GetTime32Cast() {
516 auto func = std::make_shared<CastFunction>("cast_time32", Type::TIME32);
517 AddCommonCasts(Type::TIME32, kOutputTargetType, func.get());
518
519 // Zero copy when the unit is the same or same integer representation
520 AddZeroCopyCast(Type::INT32, /*in_type=*/int32(), kOutputTargetType, func.get());
521
522 // time64 -> time32
523 AddSimpleCast<Time64Type, Time32Type>(InputType(Type::TIME64), kOutputTargetType,
524 func.get());
525
526 // time32 -> time32
527 AddCrossUnitCast<Time32Type>(func.get());
528
529 // timestamp -> time32
530 AddSimpleCast<TimestampType, Time32Type>(InputType(Type::TIMESTAMP), kOutputTargetType,
531 func.get());
532
533 return func;
534 }
535
536 std::shared_ptr<CastFunction> GetTime64Cast() {
537 auto func = std::make_shared<CastFunction>("cast_time64", Type::TIME64);
538 AddCommonCasts(Type::TIME64, kOutputTargetType, func.get());
539
540 // Zero copy when the unit is the same or same integer representation
541 AddZeroCopyCast(Type::INT64, /*in_type=*/int64(), kOutputTargetType, func.get());
542
543 // time32 -> time64
544 AddSimpleCast<Time32Type, Time64Type>(InputType(Type::TIME32), kOutputTargetType,
545 func.get());
546
547 // Between durations
548 AddCrossUnitCast<Time64Type>(func.get());
549
550 // timestamp -> time64
551 AddSimpleCast<TimestampType, Time64Type>(InputType(Type::TIMESTAMP), kOutputTargetType,
552 func.get());
553
554 return func;
555 }
556
557 std::shared_ptr<CastFunction> GetTimestampCast() {
558 auto func = std::make_shared<CastFunction>("cast_timestamp", Type::TIMESTAMP);
559 AddCommonCasts(Type::TIMESTAMP, kOutputTargetType, func.get());
560
561 // Same integer representation
562 AddZeroCopyCast(Type::INT64, /*in_type=*/int64(), kOutputTargetType, func.get());
563
564 // From date types
565 // TODO: ARROW-8876, these casts are not directly tested
566 AddSimpleCast<Date32Type, TimestampType>(InputType(Type::DATE32), kOutputTargetType,
567 func.get());
568 AddSimpleCast<Date64Type, TimestampType>(InputType(Type::DATE64), kOutputTargetType,
569 func.get());
570
571 // string -> timestamp
572 AddSimpleCast<StringType, TimestampType>(utf8(), kOutputTargetType, func.get());
573 // large_string -> timestamp
574 AddSimpleCast<LargeStringType, TimestampType>(large_utf8(), kOutputTargetType,
575 func.get());
576
577 // From one timestamp to another
578 AddCrossUnitCast<TimestampType>(func.get());
579
580 return func;
581 }
582
583 std::vector<std::shared_ptr<CastFunction>> GetTemporalCasts() {
584 std::vector<std::shared_ptr<CastFunction>> functions;
585
586 functions.push_back(GetDate32Cast());
587 functions.push_back(GetDate64Cast());
588 functions.push_back(GetDurationCast());
589 functions.push_back(GetIntervalCast());
590 functions.push_back(GetTime32Cast());
591 functions.push_back(GetTime64Cast());
592 functions.push_back(GetTimestampCast());
593 return functions;
594 }
595
596 } // namespace internal
597 } // namespace compute
598 } // namespace arrow