sparrow ..
Loading...
Searching...
No Matches
timestamp_array.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or mplied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
27#include "sparrow/u8_buffer.hpp"
33
34// tts : timestamp<std::chrono::seconds>
35// tsm : timestamp<std::chrono::milliseconds>
36// tsu : timestamp<std::chrono::microseconds>
37// tsn : timestamp<std::chrono::nanoseconds>
38
39namespace sparrow
40{
41 template <timestamp_type T>
42 class timestamp_array;
43
44 template <timestamp_type T>
60
66 template <typename T>
67 struct is_timestamp_array : std::false_type
68 {
69 };
70
76 template <typename T>
77 struct is_timestamp_array<timestamp_array<T>> : std::true_type
78 {
79 };
80
86 template <typename T>
88
96
104
105 namespace detail
106 {
107 template <>
109 {
110 [[nodiscard]] static constexpr sparrow::data_type get()
111 {
113 }
114 };
115
116 template <>
118 {
119 [[nodiscard]] static constexpr sparrow::data_type get()
120 {
122 }
123 };
124
125 template <>
127 {
128 [[nodiscard]] static constexpr sparrow::data_type get()
129 {
131 }
132 };
133
134 template <>
136 {
137 [[nodiscard]] static constexpr sparrow::data_type get()
138 {
140 }
141 };
142 }
143
196 template <timestamp_type T>
197 class timestamp_array final : public mutable_array_bitmap_base<timestamp_array<T>>
198 {
199 public:
200
203
205 using inner_value_type = typename inner_types::inner_value_type;
206 using inner_reference = typename inner_types::inner_reference;
207 using inner_const_reference = typename inner_types::inner_const_reference;
208
210 using bitmap_reference = typename base_type::bitmap_reference;
214 using bitmap_range = typename base_type::bitmap_range;
216
220
224
225 using value_iterator = typename base_type::value_iterator;
226 using const_value_iterator = typename base_type::const_value_iterator;
227
228 using iterator = typename base_type::iterator;
229 using const_iterator = typename base_type::const_iterator;
230
231 using functor_type = typename inner_types::functor_type;
232 using const_functor_type = typename inner_types::const_functor_type;
233
234 using inner_value_type_duration = inner_value_type::duration;
235 using buffer_inner_value_type = inner_value_type_duration::rep;
238
252
292 template <class... Args>
294 constexpr explicit timestamp_array(Args&&... args)
295 : base_type(create_proxy(std::forward<Args>(args)...))
296 , m_timezone(get_timezone(this->get_arrow_proxy()))
297 , m_data_access(this->get_arrow_proxy(), DATA_BUFFER_INDEX)
298 {
299 }
300
315 template <input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
317 const date::time_zone* timezone,
318 std::initializer_list<inner_value_type> init,
319 std::optional<std::string_view> name = std::nullopt,
320 std::optional<METADATA_RANGE> metadata = std::nullopt
321 )
322 : base_type(create_proxy(timezone, init, std::move(name), std::move(metadata)))
323 , m_timezone(timezone)
324 , m_data_access(this->get_arrow_proxy(), DATA_BUFFER_INDEX)
325 {
326 }
327
338 constexpr timestamp_array(const timestamp_array& rhs);
339
352
363
375
376 private:
377
389 [[nodiscard]] constexpr inner_reference value(size_type i);
390
403 [[nodiscard]] constexpr inner_const_reference value(size_type i) const;
404
412 [[nodiscard]] constexpr value_iterator value_begin();
413
421 [[nodiscard]] constexpr value_iterator value_end();
422
430 [[nodiscard]] constexpr const_value_iterator value_cbegin() const;
431
439 [[nodiscard]] constexpr const_value_iterator value_cend() const;
440
442
479 template <input_metadata_container METADATA_RANGE>
480 [[nodiscard]] static arrow_proxy create_proxy(
481 const date::time_zone* timezone,
482 size_type n,
483 std::optional<std::string_view> name = std::nullopt,
484 std::optional<METADATA_RANGE> metadata = std::nullopt
485 );
486
487 //
515 template <
517 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
518 [[nodiscard]] static auto create_proxy(
519 const date::time_zone* timezone,
521 R&& bitmaps = validity_bitmap{},
522 std::optional<std::string_view> name = std::nullopt,
523 std::optional<METADATA_RANGE> metadata = std::nullopt
524 ) -> arrow_proxy;
525
554 template <std::ranges::input_range R, input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
555 requires std::convertible_to<std::ranges::range_value_t<R>, T>
556 [[nodiscard]] static auto create_proxy(
557 const date::time_zone* timezone,
558 R&& range,
559 bool nullable = true,
560 std::optional<std::string_view> name = std::nullopt,
561 std::optional<METADATA_RANGE> metadata = std::nullopt
562 ) -> arrow_proxy;
563
564
592 template <typename U, input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
593 requires std::convertible_to<U, T>
594 [[nodiscard]] static arrow_proxy create_proxy(
595 const date::time_zone* timezone,
596 size_type n,
597 const U& value = U{},
598 std::optional<std::string_view> name = std::nullopt,
599 std::optional<METADATA_RANGE> metadata = std::nullopt
600 );
601
632 template <
633 std::ranges::input_range VALUE_RANGE,
634 validity_bitmap_input VALIDITY_RANGE,
635 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
636 requires(std::convertible_to<std::ranges::range_value_t<VALUE_RANGE>, T>)
637 [[nodiscard]] static arrow_proxy create_proxy(
638 const date::time_zone* timezone,
639 VALUE_RANGE&&,
640 VALIDITY_RANGE&&,
641 std::optional<std::string_view> name = std::nullopt,
642 std::optional<METADATA_RANGE> metadata = std::nullopt
643 );
644
673 template <std::ranges::input_range R, input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
674 requires std::is_same_v<std::ranges::range_value_t<R>, nullable<T>>
675 [[nodiscard]] static arrow_proxy create_proxy(
676 const date::time_zone* timezone,
677 R&&,
678 std::optional<std::string_view> name = std::nullopt,
679 std::optional<METADATA_RANGE> metadata = std::nullopt
680 );
681
723 template <input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
724 [[nodiscard]] static arrow_proxy create_proxy_impl(
725 const date::time_zone* timezone,
726 u8_buffer<buffer_inner_value_type>&& data_buffer,
727 std::optional<validity_bitmap>&& bitmap,
728 std::optional<std::string_view> name = std::nullopt,
729 std::optional<METADATA_RANGE> metadata = std::nullopt
730 );
731
733
734 // Modifiers
735
747 constexpr void resize_values(size_type new_length, inner_value_type value);
748
763 constexpr value_iterator
764 insert_value(const_value_iterator pos, inner_value_type value, size_type count);
765
783 template <mpl::iterator_of_type<typename timestamp_array<T>::inner_value_type> InputIt>
784 constexpr auto insert_values(const_value_iterator pos, InputIt first, InputIt last) -> value_iterator
785 {
786 const auto input_range = std::ranges::subrange(first, last);
787 const auto values = input_range
788 | std::views::transform(
789 [](const auto& v)
790 {
791 return v.get_sys_time().time_since_epoch();
792 }
793 );
794 const size_t idx = static_cast<size_t>(std::distance(value_cbegin(), pos));
795 m_data_access.insert_values(idx, values.begin(), values.end());
796 return sparrow::next(value_begin(), idx);
797 }
798
814 constexpr value_iterator erase_values(const_value_iterator pos, size_type count);
815
829 constexpr void assign(const T& rhs, size_type index);
830
844 constexpr void assign(T&& rhs, size_type index);
845
846
847 const date::time_zone* m_timezone;
848 details::primitive_data_access<inner_value_type_duration> m_data_access;
849
850 static constexpr size_type DATA_BUFFER_INDEX = 1;
851 friend class timestamp_reference<self_type>;
852 friend base_type;
855 friend functor_type;
856 friend const_functor_type;
857 };
858
859 template <timestamp_type T>
861 : base_type(rhs)
862 , m_timezone(rhs.m_timezone)
863 , m_data_access(this->get_arrow_proxy(), DATA_BUFFER_INDEX)
864 {
865 }
866
867 template <timestamp_type T>
869 {
871 m_timezone = rhs.m_timezone;
872 m_data_access.reset_proxy(this->get_arrow_proxy());
873 return *this;
874 }
875
876 template <timestamp_type T>
878 : base_type(std::move(rhs))
879 , m_timezone(rhs.m_timezone)
880 , m_data_access(this->get_arrow_proxy(), DATA_BUFFER_INDEX)
881 {
882 }
883
884 template <timestamp_type T>
886 {
887 base_type::operator=(std::move(rhs));
888 m_timezone = rhs.m_timezone;
889 m_data_access.reset_proxy(this->get_arrow_proxy());
890 return *this;
891 }
892
893 template <timestamp_type T>
895 : base_type(std::move(proxy))
896 , m_timezone(get_timezone(this->get_arrow_proxy()))
897 , m_data_access(this->get_arrow_proxy(), DATA_BUFFER_INDEX)
898 {
899 }
900
901 template <timestamp_type T>
902 template <validity_bitmap_input R, input_metadata_container METADATA_RANGE>
903 auto timestamp_array<T>::create_proxy(
904 const date::time_zone* timezone,
906 R&& bitmap_input,
907 std::optional<std::string_view> name,
908 std::optional<METADATA_RANGE> metadata
909 ) -> arrow_proxy
910 {
911 const auto size = data_buffer.size();
912 validity_bitmap bitmap = ensure_validity_bitmap(size, std::forward<R>(bitmap_input));
913 return create_proxy_impl(
914 timezone,
915 std::forward<u8_buffer<buffer_inner_value_type>>(data_buffer),
916 std::move(bitmap),
917 std::move(name),
918 std::move(metadata)
919 );
920 }
921
922 template <timestamp_type T>
923 template <std::ranges::input_range VALUE_RANGE, validity_bitmap_input VALIDITY_RANGE, input_metadata_container METADATA_RANGE>
924 requires(std::convertible_to<std::ranges::range_value_t<VALUE_RANGE>, T>)
925 arrow_proxy timestamp_array<T>::create_proxy(
926 const date::time_zone* timezone,
927 VALUE_RANGE&& values,
928 VALIDITY_RANGE&& validity_input,
929 std::optional<std::string_view> name,
930 std::optional<METADATA_RANGE> metadata
931 )
932 {
933 const auto range = values
934 | std::views::transform(
935 [](const auto& v)
936 {
937 return v.get_sys_time().time_since_epoch().count();
938 }
939 );
940
941
942 u8_buffer<buffer_inner_value_type> data_buffer(range);
943 return create_proxy(
944 timezone,
945 std::move(data_buffer),
946 std::forward<VALIDITY_RANGE>(validity_input),
947 std::move(name),
948 std::move(metadata)
949 );
950 }
951
952 template <timestamp_type T>
953 template <typename U, input_metadata_container METADATA_RANGE>
954 requires std::convertible_to<U, T>
955 arrow_proxy timestamp_array<T>::create_proxy(
956 const date::time_zone* timezone,
957 size_type n,
958 const U& value,
959 std::optional<std::string_view> name,
960 std::optional<METADATA_RANGE> metadata
961 )
962 {
963 // create data_buffer
964 u8_buffer<buffer_inner_value_type> data_buffer(n, to_days_since_the_UNIX_epoch(value));
965 return create_proxy(timezone, std::move(data_buffer), std::move(name), std::move(metadata));
966 }
967
968 template <timestamp_type T>
969 template <std::ranges::input_range R, input_metadata_container METADATA_RANGE>
970 requires std::convertible_to<std::ranges::range_value_t<R>, T>
971 arrow_proxy timestamp_array<T>::create_proxy(
972 const date::time_zone* timezone,
973 R&& range,
974 bool nullable,
975 std::optional<std::string_view> name,
976 std::optional<METADATA_RANGE> metadata
977 )
978 {
979 std::optional<validity_bitmap> bitmap = nullable ? std::make_optional<validity_bitmap>(nullptr, 0)
980 : std::nullopt;
981 const auto values = range
982 | std::views::transform(
983 [](const auto& v)
984 {
985 return v.get_sys_time().time_since_epoch().count();
986 }
987 );
988 u8_buffer<buffer_inner_value_type> data_buffer(values);
989 return self_type::create_proxy_impl(
990 timezone,
991 std::move(data_buffer),
992 std::move(bitmap),
993 std::move(name),
994 std::move(metadata)
995 );
996 }
997
998 // range of nullable values
999 template <timestamp_type T>
1000 template <std::ranges::input_range R, input_metadata_container METADATA_RANGE>
1001 requires std::is_same_v<std::ranges::range_value_t<R>, nullable<T>>
1002 arrow_proxy timestamp_array<T>::create_proxy(
1003 const date::time_zone* timezone,
1004 R&& range,
1005 std::optional<std::string_view> name,
1006 std::optional<METADATA_RANGE> metadata
1007 )
1008 { // split into values and is_non_null ranges
1009 auto values = range
1010 | std::views::transform(
1011 [](const auto& v)
1012 {
1013 return v.get();
1014 }
1015 );
1016 auto is_non_null = range
1017 | std::views::transform(
1018 [](const auto& v)
1019 {
1020 return v.has_value();
1021 }
1022 );
1023 return self_type::create_proxy(timezone, values, is_non_null, std::move(name), std::move(metadata));
1024 }
1025
1026 template <timestamp_type T>
1027 template <input_metadata_container METADATA_RANGE>
1028 arrow_proxy timestamp_array<T>::create_proxy_impl(
1029 const date::time_zone* timezone,
1031 std::optional<validity_bitmap>&& bitmap,
1032 std::optional<std::string_view> name,
1033 std::optional<METADATA_RANGE> metadata
1034 )
1035 {
1036 const auto size = data_buffer.size();
1037 const auto null_count = bitmap.has_value() ? bitmap->null_count() : 0;
1038
1040 format += timezone->name();
1041
1043
1044 const std::optional<std::unordered_set<sparrow::ArrowFlag>>
1045 flags = bitmap.has_value()
1046 ? std::make_optional<std::unordered_set<sparrow::ArrowFlag>>({ArrowFlag::NULLABLE})
1047 : std::nullopt;
1048
1049 // create arrow schema and array
1050 ArrowSchema schema = make_arrow_schema(
1051 std::move(format), // format
1052 std::move(name), // name
1053 std::move(metadata), // metadata
1054 flags, // flags
1055 nullptr, // children
1056 children_ownership, // children ownership
1057 nullptr, // dictionary,
1058 true // dictionary ownership
1059 );
1060
1061 std::vector<buffer<uint8_t>> buffers{
1062 bitmap.has_value() ? std::move(bitmap.value()).extract_storage() : buffer<uint8_t>{nullptr, 0},
1063 std::move(data_buffer).extract_storage()
1064 };
1065
1066 // create arrow array
1067 ArrowArray arr = make_arrow_array(
1068 static_cast<std::int64_t>(size), // length
1069 static_cast<int64_t>(null_count),
1070 0, // offset
1071 std::move(buffers),
1072 nullptr, // children
1073 children_ownership, // children ownership
1074 nullptr, // dictionary
1075 true // dicitonary ownership
1076 );
1077 return arrow_proxy(std::move(arr), std::move(schema));
1078 }
1079
1080 template <timestamp_type T>
1081 constexpr void timestamp_array<T>::assign(const T& rhs, size_type index)
1082 {
1083 SPARROW_ASSERT_TRUE(index < this->size());
1084 m_data_access.value(index) = rhs.get_sys_time().time_since_epoch();
1085 }
1086
1087 template <timestamp_type T>
1088 constexpr void timestamp_array<T>::assign(T&& rhs, size_type index)
1089 {
1090 SPARROW_ASSERT_TRUE(index < this->size());
1091 m_data_access.value(index) = rhs.get_sys_time().time_since_epoch();
1092 }
1093
1094 template <timestamp_type T>
1095 constexpr auto timestamp_array<T>::value(size_type i) -> inner_reference
1096 {
1097 SPARROW_ASSERT_TRUE(i < this->size());
1098 return inner_reference(this, i);
1099 }
1100
1101 template <timestamp_type T>
1102 constexpr auto timestamp_array<T>::value(size_type i) const -> inner_const_reference
1103 {
1104 SPARROW_ASSERT_TRUE(i < this->size());
1105 const auto& val = m_data_access.value(i);
1106 using time_duration = typename T::duration;
1107 const auto sys_time = std::chrono::sys_time<time_duration>{val};
1108 return T{m_timezone, sys_time};
1109 }
1110
1111 template <timestamp_type T>
1112 constexpr auto timestamp_array<T>::value_begin() -> value_iterator
1113 {
1114 return value_iterator(functor_type(this), 0);
1115 }
1116
1117 template <timestamp_type T>
1118 constexpr auto timestamp_array<T>::value_end() -> value_iterator
1119 {
1120 return value_iterator(functor_type(this), this->size());
1121 }
1122
1123 template <timestamp_type T>
1124 constexpr auto timestamp_array<T>::value_cbegin() const -> const_value_iterator
1125 {
1126 return const_value_iterator(const_functor_type(this), 0);
1127 }
1128
1129 template <timestamp_type T>
1130 constexpr auto timestamp_array<T>::value_cend() const -> const_value_iterator
1131 {
1132 return const_value_iterator(const_functor_type(this), this->size());
1133 }
1134
1135 template <timestamp_type T>
1136 constexpr void timestamp_array<T>::resize_values(size_type new_length, inner_value_type value)
1137 {
1138 m_data_access.resize_values(new_length, value.get_sys_time().time_since_epoch());
1139 }
1140
1141 template <timestamp_type T>
1142 constexpr auto
1143 timestamp_array<T>::insert_value(const_value_iterator pos, inner_value_type value, size_type count)
1144 -> value_iterator
1145 {
1146 SPARROW_ASSERT_TRUE(pos <= value_cend());
1147 const size_t idx = static_cast<size_t>(std::distance(value_cbegin(), pos));
1148 m_data_access.insert_value(idx, value.get_sys_time().time_since_epoch(), count);
1149 return value_iterator(functor_type(this), idx);
1150 }
1151
1152 template <timestamp_type T>
1153 constexpr auto timestamp_array<T>::erase_values(const_value_iterator pos, size_type count) -> value_iterator
1154 {
1155 SPARROW_ASSERT_TRUE(pos < value_cend());
1156 const size_t idx = static_cast<size_t>(std::distance(value_cbegin(), pos));
1157 m_data_access.erase_values(idx, count);
1158 return value_iterator(functor_type(this), idx);
1159 }
1160}
typename base_type::const_bitmap_range const_bitmap_range
typename base_type::bitmap_iterator bitmap_iterator
typename base_type::iterator_tag iterator_tag
typename base_type::const_bitmap_iterator const_bitmap_iterator
constexpr array_bitmap_base_impl & operator=(const array_bitmap_base_impl &)
std::conditional_t< is_mutable, mutable_array_base< D >, array_crtp_base< D > > base_type
typename base_type::bitmap_const_reference bitmap_const_reference
typename base_type::bitmap_type bitmap_type
typename base_type::difference_type difference_type
Object that owns a piece of contiguous memory.
Definition buffer.hpp:113
storage_type extract_storage() noexcept
Extracts the underlying storage (move operation).
constexpr size_type null_count() const noexcept
Returns the number of bits set to false (null/invalid).
A view that repeats a value a given number of times.
Array implementation for storing timestamp values with timezone information.
mutable_array_bitmap_base< self_type > base_type
typename inner_types::inner_reference inner_reference
constexpr timestamp_array(timestamp_array &&rhs)
Move constructor.
constexpr timestamp_array(const timestamp_array &rhs)
Copy constructor.
timestamp_array(arrow_proxy)
Constructs timestamp array from Arrow proxy.
typename base_type::const_bitmap_iterator const_bitmap_iterator
typename base_type::const_value_iterator const_value_iterator
pointer_iterator< const buffer_inner_value_type * > buffer_inner_const_value_iterator
typename base_type::bitmap_const_reference bitmap_const_reference
constexpr timestamp_array & operator=(const timestamp_array &rhs)
Copy assignment operator.
pointer_iterator< buffer_inner_value_type * > buffer_inner_value_iterator
typename base_type::const_bitmap_range const_bitmap_range
constexpr timestamp_array(Args &&... args)
Generic constructor for creating timestamp arrays from various inputs.
nullable< inner_const_reference, bitmap_const_reference > const_reference
typename inner_types::inner_const_reference inner_const_reference
nullable< inner_reference, bitmap_reference > reference
typename base_type::bitmap_reference bitmap_reference
constexpr timestamp_array(const date::time_zone *timezone, std::initializer_list< inner_value_type > init, std::optional< std::string_view > name=std::nullopt, std::optional< METADATA_RANGE > metadata=std::nullopt)
Constructs timestamp array from initializer list.
constexpr timestamp_array & operator=(timestamp_array &&rhs)
Move assignment operator.
typename inner_types::const_functor_type const_functor_type
typename inner_types::inner_value_type inner_value_type
Implementation of reference to inner type used for layout L.
This buffer class is used as storage buffer for all sparrow arrays.
Concept for input containers that can provide metadata pairs.
Definition metadata.hpp:304
Concept defining valid input types for validity bitmap creation.
#define SPARROW_ASSERT_TRUE(expr__)
constexpr std::size_t size(typelist< T... >={})
Gets the count of types contained in a typelist.
Definition mp_utils.hpp:216
constexpr bool excludes_copy_and_move_ctor_v
Convenience variable template for excludes_copy_and_move_ctor.
array_bitmap_base_impl< D, true > mutable_array_bitmap_base
Convenient alias for arrays with mutable validity bitmaps.
ArrowSchema make_arrow_schema(F format, N name, std::optional< M > metadata, std::optional< std::unordered_set< ArrowFlag > > flags, ArrowSchema **children, const CHILDREN_OWNERSHIP &children_ownership, ArrowSchema *dictionary, bool dictionary_ownership)
Creates an ArrowSchema owned by a unique_ptr and holding the provided data.
timestamp< std::chrono::microseconds > timestamp_microsecond
constexpr std::string_view data_type_to_format(data_type type)
timestamp< std::chrono::nanoseconds > timestamp_nanosecond
constexpr InputIt next(InputIt it, Distance n)
Definition iterator.hpp:503
SPARROW_API const date::time_zone * get_timezone(const arrow_proxy &proxy)
timestamp_array< timestamp_second > timestamp_seconds_array
Type aliases for timestamp arrays with common durations.
date::zoned_time< Duration, TimeZonePtr > timestamp
constexpr bool is_timestamp_array_v
Variable template for convenient access to is_timestamp_array.
ArrowArray make_arrow_array(int64_t length, int64_t null_count, int64_t offset, B buffers, ArrowArray **children, const CHILDREN_OWNERSHIP &children_ownership, ArrowArray *dictionary, bool dictionary_ownership)
Creates an ArrowArray.
dynamic_bitset< std::uint8_t > validity_bitmap
Type alias for a validity bitmap using 8-bit storage blocks.
timestamp_array< timestamp_nanosecond > timestamp_nanoseconds_array
timestamp< std::chrono::seconds > timestamp_second
Type aliases for common timestamp durations.
validity_bitmap ensure_validity_bitmap(std::size_t size, R &&validity_input)
Ensures a validity bitmap of the specified size from various input types.
timestamp< std::chrono::milliseconds > timestamp_millisecond
data_type
Runtime identifier of arrow data types, usually associated with raw bytes with the associated value.
timestamp_array< timestamp_microsecond > timestamp_microseconds_array
timestamp_array< timestamp_millisecond > timestamp_milliseconds_array
functor_index_iterator< functor_type > value_iterator
functor_index_iterator< const_functor_type > const_value_iterator
detail::layout_value_functor< self_type, inner_reference > functor_type
detail::layout_value_functor< const self_type, inner_const_reference > const_functor_type
Base class for array_inner_types specializations.
Traits class that must be specialized by array implementations.
Metafunction for retrieving the data_type of a typed array.
Type trait to check if a type is a timestamp_array.