| 848 | |
| 849 | template <typename T, bool AddEpoch> |
| 850 | Formatter MakeTimeFormatter(const std::string& fmt_str) { |
| 851 | return [fmt_str](const Array& array, int64_t index, std::ostream* os) { |
| 852 | auto fmt = fmt_str.c_str(); |
| 853 | auto unit = checked_cast<const T&>(*array.type()).unit(); |
| 854 | auto value = checked_cast<const NumericArray<T>&>(array).Value(index); |
| 855 | // Using unqualified `format` directly would produce ambiguous |
| 856 | // lookup because of `std::format` (ARROW-15520). |
| 857 | namespace avd = arrow_vendored::date; |
| 858 | using std::chrono::nanoseconds; |
| 859 | using std::chrono::microseconds; |
| 860 | using std::chrono::milliseconds; |
| 861 | using std::chrono::seconds; |
| 862 | if (AddEpoch) { |
| 863 | static avd::sys_days epoch{avd::jan / 1 / 1970}; |
| 864 | |
| 865 | switch (unit) { |
| 866 | case TimeUnit::NANO: |
| 867 | *os << avd::format(fmt, static_cast<nanoseconds>(value) + epoch); |
| 868 | break; |
| 869 | case TimeUnit::MICRO: |
| 870 | *os << avd::format(fmt, static_cast<microseconds>(value) + epoch); |
| 871 | break; |
| 872 | case TimeUnit::MILLI: |
| 873 | *os << avd::format(fmt, static_cast<milliseconds>(value) + epoch); |
| 874 | break; |
| 875 | case TimeUnit::SECOND: |
| 876 | *os << avd::format(fmt, static_cast<seconds>(value) + epoch); |
| 877 | break; |
| 878 | } |
| 879 | return; |
| 880 | } |
| 881 | switch (unit) { |
| 882 | case TimeUnit::NANO: |
| 883 | *os << avd::format(fmt, static_cast<nanoseconds>(value)); |
| 884 | break; |
| 885 | case TimeUnit::MICRO: |
| 886 | *os << avd::format(fmt, static_cast<microseconds>(value)); |
| 887 | break; |
| 888 | case TimeUnit::MILLI: |
| 889 | *os << avd::format(fmt, static_cast<milliseconds>(value)); |
| 890 | break; |
| 891 | case TimeUnit::SECOND: |
| 892 | *os << avd::format(fmt, static_cast<seconds>(value)); |
| 893 | break; |
| 894 | } |
| 895 | }; |
| 896 | } |
| 897 | |
| 898 | Formatter impl_; |
| 899 | }; |