ClockWork DB CoreAPI 1.0.48
Abstract Time Series and Storage/Management Library
Loading...
Searching...
No Matches
time_series.hpp
1#ifndef HAVE_TOM_TSDB_TIME_SERIES_HPP
2#define HAVE_TOM_TSDB_TIME_SERIES_HPP
3
4#include <tom-util/time_series.hpp>
5#include <tom-tsdb/types.hpp>
6#include <map>
7#include <set>
8
9namespace tom {
10
11 namespace tsdb {
12
13 class datastore;
14 class native_calendar_type;
15
22 {
23 public:
24 static
26 factory( unsigned short int v )
27 {
28 if ( ( v >= 1 && v <= 4 ) ||
29 ( v>=7 && v <= 8 ) )
30 return aggregation_type(v);
31 else
32 //throw std::runtime_error( "Invalid aggregation_type." );
33 return aggregation_type(1);
34 }
39 static
41 begin() { return aggregation_type(1); }
42
47 static
49 end() { return aggregation_type(2); }
50
55 static
57 averaged() { return aggregation_type(3); }
58
63 static
65 summed() { return aggregation_type(4); }
66
71 static
73 high() { return aggregation_type(7); }
74
79 static
81 low() { return aggregation_type(8); }
82
83 unsigned short int
84 value() const { return m_value; }
85
89 const char *
90 name() const
91 {
92 switch( value() )
93 {
94 case 1:
95 return "Begin";
96 case 2:
97 return "End";
98 case 3:
99 return "Averaged";
100 case 4:
101 return "Summed";
102 case 7:
103 return "High";
104 case 8:
105 return "Low";
106 default:
107 return "Unknown";
108 }
109 }
113 bool
115 {
116 if ( rhs.value() == m_value )
117 return true;
118
119 return false;
120 }
124 bool
126 {
127 return ! ( *this == rhs );
128 }
129 private:
131 aggregation_type( unsigned short int v ) :
132 m_value( v ) { }
133 unsigned short int m_value;
134 };
140 class alias_set :
141 public std::set<tom::string, std::less<tom::string> >
142 {
143 public:
144 typedef std::set<
146 std::less<tom::string>
147 >
148 parent_type;
149 typedef parent_type::iterator iterator;
150 typedef parent_type::const_iterator const_iterator;
151
155 alias_set() : m_changed(false) { }
156
161 template <typename IteratorT>
162 alias_set( IteratorT begin, IteratorT end ) :
163 parent_type( begin, end ), m_changed(false) { }
164
168 alias_set( const alias_set &rhs ) :
169 parent_type(rhs), m_changed( rhs.m_changed ) { }
170
174 alias_set &
175 operator=( const alias_set &rhs )
176 {
177 clear();
178 insert( rhs.begin(), rhs.end() );
179 m_changed = rhs.m_changed;
180 return *this;
181 }
185 bool
186 operator==( const alias_set &rhs )
187 {
188 // same size & size > 0
189 if ( size() > 0 && size() == rhs.size() )
190 return std::equal( begin(), end(), rhs.begin() );
191
192 // different sizes must be different
193 else if ( size() != rhs.size() )
194 return false;
195
196 // both must be empty sets to reach here
197 return true;
198 }
202 bool
203 operator!=( const alias_set &rhs )
204 {
205 return ! ( *this == rhs );
206 }
207 virtual ~alias_set() { }
208
209 // allow no non-const iterators, or someone could
210 // change an alias value, and the persistence side
211 // of things wouldn't know. This would be confusing
212 // to users...
219 const_iterator
220 begin() const { return this->parent_type::begin(); }
221
226 const_iterator
227 end() const { return this->parent_type::end(); }
228
234 bool
235 add( const char * );
236
242 bool
243 add( const tom::observation & );
244
250 bool
251 add( const tom::string & );
252
257 bool
258 remove( const char * );
259
264 bool
265 remove( const tom::observation & );
266
271 bool
272 remove( const tom::string & );
273
280 bool
281 changed( ) const;
282
286 void
287 clear( ) { m_changed = true; this->parent_type::clear(); }
288
289 protected:
290 bool m_changed;
291
292 };
293
312 class TOM_UTIL_API time_series : public tom::collections::time_series
313 {
314 public:
315
316 // struct to keep track of attributes for time-series that
317 // don't yet exist
318 typedef std::map< tom::string, tom::string > attribute_map_t;
319 typedef std::set< tom::string > attribute_set_t;
320
321 // callback function to populate time-series w/ data
322 // This may be used by implementations of time-series
323 // (such as time_series_impl<> below )
324 // to allow back-ends to register callbacks for
325 // lazy eval when getting time-series
326 typedef bool (tom::tsdb::datastore::*populate_data_func)(
328 const tom::string & name,
331 tom::calendars::date_int_type from,
332 tom::calendars::date_int_type to
333 );
334
335 // this is useful mainly for datastore implementations that
336 // need to update create/modify time-stamps when saving time_series
337 friend class ::tom::tsdb::datastore;
338
339 time_series() : m_alias_set_touched(false) { }
340 virtual ~time_series() { }
344 virtual const tom::string &get_name() const = 0;
345
349 virtual tom::tsdb::datastore & get_datastore() const = 0;
353 virtual const values::data_type & get_data_type() const = 0;
372 virtual void save( bool overwrite = false );
378 virtual alias_set &get_alias_set();
384 virtual const alias_set &get_alias_set() const;
385
386 // this is for internal use...
387 // The purpose is to return a pointer to the beginning
388 // of the data-space for time-series to avoid serialization
389 // or other reasons (optimized algos?)...
390 // This may(should) go away in the future so
391 // consider it deprecated since the beginning of time!
392 // you've been warned.
393 virtual
394 const void *
395 get_raw_data() const = 0;
396
401 virtual
402 const tom::calendars::date_time &
404
409 virtual
410 const tom::calendars::date_time &
412
417 bool
418 operator==( const time_series &rhs ) const;
419
424 bool
425 operator!=( const time_series &rhs ) const;
426
432 bool
433 alias_set_touched() const;
434
439 size_t
440 get_dropped_aliases( alias_set &dropped ) const;
441
446 size_t
447 get_added_aliases( alias_set &added ) const;
448
456 const tom::String &
457 get_attribute( const char *att_name, bool check_datastore = true ) const
458 { return get_attribute( tom::String( att_name ), check_datastore ); }
459
467 const tom::String &
468 get_attribute( const tom::observation &att_name, bool check_datastore = true ) const
469 { return get_attribute( tom::String( att_name ) ); }
470
478 const tom::String &
479 get_attribute( const tom::String &att_name, bool check_datastore = true ) const;
480
489 void
490 set_attribute( const char *att_name,
491 const char *att_value )
492 { return set_attribute( tom::String( att_name ), tom::String( att_value ) ); }
493
502 void
504 const tom::observation &att_value )
505 { return set_attribute( tom::String( att_name ), tom::String( att_value ) ); }
506
515 void
516 set_attribute( const tom::String &att_name,
517 const tom::String &att_value );
518
523 virtual
524 bool
525 is_sparse_series() const = 0;
526
532 virtual
533 tom::calendars::date_int_type
535
541 virtual
542 tom::calendars::date_int_type
544
548 virtual
549 bool
550 exists() const;
551
552 virtual
553 const attribute_set_t &
554 get_changed_attribute_names() const { return m_changed_attributes; }
555
556 protected:
557 bool
558 populate_alias_set() const;
559
560 virtual
561 void
562 set_create_date_time(const tom::calendars::date_time &) = 0;
563
564 virtual
565 void
566 set_modify_date_time(const tom::calendars::date_time &) = 0;
567
568 // mutable because we lazy init alias_sets
569 // and a const method may need to populate these
570 mutable bool m_alias_set_touched;
571 mutable alias_set m_alias_set;
572 mutable alias_set m_original_alias_set;
573 mutable attribute_map_t m_attributes;
574 attribute_set_t m_changed_attributes;
575 };
576 namespace collections {
577
578 template <typename T, typename NATIVE_TYPE>
579 class TOM_UTIL_API time_series : public tom::tsdb::time_series
580 {
581 public:
582 typedef typename T::value_type value_type;
583
586
588 aggregation_type, const tom::calendars::date_time &created,
589 const tom::calendars::date_time &modified );
590
591 template <typename IteratorT>
593 aggregation_type agg_t, const tom::calendars::date_time &created,
594 const tom::calendars::date_time &modified,
595 tom::calendars::date_int_type start,
596 IteratorT begin, IteratorT end );
597
598
599 // create it and register a populate data call back
600 // that is, we can create the ts w/ out reading the real data
601 // but as soon as someone calls the get_observation() family of
602 // calls, the populate_data_func is called to populate the timeseries
604 aggregation_type agg_t, const tom::calendars::date_time &created,
605 const tom::calendars::date_time &modified,
606 tom::calendars::date_int_type start,
607 tom::calendars::date_int_type end,
608 populate_data_func );
609
610 virtual datastore & get_datastore() const { return m_ds; }
611 virtual const values::data_type & get_data_type() const { return NATIVE_TYPE::Instance(); }
612 virtual aggregation_type get_aggregation_type() const;
613 virtual void set_aggregation_type( aggregation_type );
614
615 virtual const tom::string &get_name() const{ return m_name; }
616
617 virtual
619 begin() const;
620
621 virtual
623 end() const;
624
625 virtual const tom::observation &get_observation( const tom::calendars::date_int_type d ) const;
626 virtual const tom::observation &get_observation( const tom::calendars::date d ) const;
627 virtual void set_observation( const tom::calendars::date_int_type d, const tom::observation & val );
628 virtual void set_observation( const tom::calendars::date d, const tom::observation & val );
629 virtual void set_observation( tom::calendars::date_int_type d, const tom::Date & );
630 virtual void set_observation( tom::calendars::date d, const tom::Date & );
631 virtual const tom::observation & operator[ ]( const tom::calendars::date_int_type d ) const;
632 virtual tom::observation & operator[ ]( const tom::calendars::date_int_type d );
633 virtual const tom::observation & operator[ ] ( const tom::calendars::date d ) const;
634 virtual tom::observation & operator[ ] ( const tom::calendars::date d );
635 virtual tom::calendars::date_int_type get_first_date_int() const;
636 virtual tom::calendars::date_int_type get_last_date_int() const;
637
638 virtual
639 tom::calendars::date_int_type
640 get_first_dirty_date_int() const;
641
642 virtual
643 tom::calendars::date_int_type
644 get_last_dirty_date_int() const;
645
646
647 virtual std::ostream &print( std::ostream & ) const;
648 virtual tom::calendars::calendar & get_calendar( ) const;
649
650 virtual
651 const tom::calendars::date_time &
652 get_create_date_time() const { return m_create_date_time; }
653
654 virtual
655 const tom::calendars::date_time &
656 get_modify_date_time() const { return m_modify_date_time; }
657
658 virtual
659 bool
660 is_sparse_series() const{ return false; }
661
662 virtual
663 const void *
664 get_raw_data() const
665 {
666 // force lazy init if needed
667 if ( m_populate_data_func != NULL )
668 get_observation( get_last_date_int() );
669 return m_data.data();
670 }
671
672 protected:
673 virtual
674 void
675 set_create_date_time(const tom::calendars::date_time &d)
676 {
677 m_create_date_time = d;
678 }
679 virtual
680 void
681 set_modify_date_time(const tom::calendars::date_time &d)
682 {
683 m_modify_date_time = d;
684 }
685
686 aggregation_type m_agg_type;
687 datastore & m_ds;
688 tom::string m_name;
689 tom::calendars::date_time m_create_date_time;
690 tom::calendars::date_time m_modify_date_time;
691
692 // must be mutable if get_observation() const
693 // might trigger callback and modification of m_data
695
696 tom::calendars::date_int_type m_l_first_date_int;
697 tom::calendars::date_int_type m_l_last_date_int;
698 tom::calendars::date_int_type m_first_dirty_date_int;
699 tom::calendars::date_int_type m_last_dirty_date_int;
700
701 mutable populate_data_func m_populate_data_func;
702
703 };
704
705 template <typename T, typename NATIVE_TYPE>
706 time_series<T,NATIVE_TYPE>::time_series( tom::calendars::calendar &cal, datastore &ds,
707 const observation &name, aggregation_type agg_t ) :
708 m_agg_type(agg_t), m_ds(ds), m_name( String( name ).value() ), m_data(cal),
709 m_l_first_date_int( 0 ), m_l_last_date_int(0),
710 m_first_dirty_date_int( 0 ), m_last_dirty_date_int( 0 ),
711 m_populate_data_func(0)
712 {
713 //m_name.to_upper();
714 }
715 template <typename T, typename NATIVE_TYPE>
716 time_series<T,NATIVE_TYPE>::time_series( tom::calendars::calendar &cal, datastore &ds,
717 const observation &name, aggregation_type agg_t,
718 const tom::calendars::date_time &created,
719 const tom::calendars::date_time &modified ) :
720 m_agg_type(agg_t), m_ds(ds), m_name( String( name ).value() ),
721 m_create_date_time( created ), m_modify_date_time( modified ), m_data(cal),
722 m_l_first_date_int( 0 ), m_l_last_date_int(0),
723 m_first_dirty_date_int( 0 ), m_last_dirty_date_int( 0 ),
724 m_populate_data_func(0)
725 {
726 //m_name.to_upper();
727 }
728 template <typename T, typename NATIVE_TYPE>
729 template <typename IteratorT>
730 time_series<T,NATIVE_TYPE>::time_series( tom::calendars::calendar &cal, datastore &ds, const observation &name,
731 aggregation_type agg_t,
732 const tom::calendars::date_time &created,
733 const tom::calendars::date_time &modified,
734 tom::calendars::date_int_type start,
735 IteratorT begin, IteratorT end ) :
736 m_agg_type(agg_t), m_ds(ds), m_name( String(name).value() ), m_create_date_time( created ),
737 m_modify_date_time( modified ), m_data(cal,cal(start), begin,end),
738 m_l_first_date_int( 0 ), m_l_last_date_int(0),
739 m_first_dirty_date_int( 0 ), m_last_dirty_date_int( 0 ),
740 m_populate_data_func(0)
741 {
742 //m_name.to_upper();
743 }
744 template <typename T, typename NATIVE_TYPE>
745 time_series<T,NATIVE_TYPE>::time_series( tom::calendars::calendar &cal, datastore &ds, const observation &name,
746 aggregation_type agg_t, const tom::calendars::date_time &created,
747 const tom::calendars::date_time &modified,
748 tom::calendars::date_int_type start,
749 tom::calendars::date_int_type end,
750 populate_data_func callback ) :
751 m_agg_type(agg_t), m_ds(ds), m_name( String(name).value() ), m_create_date_time( created ),
752 m_modify_date_time( modified ), m_data(cal),
753 m_l_first_date_int( start ), m_l_last_date_int(end),
754 m_first_dirty_date_int( 0 ), m_last_dirty_date_int( 0 ),
755 m_populate_data_func( callback )
756 {
757 //m_name.to_upper();
758 }
759
760
761 template <typename T, typename NATIVE_TYPE>
762 aggregation_type
764 {
765 return m_agg_type;
766 }
767 template <typename T, typename NATIVE_TYPE>
768 void
770 {
771 m_agg_type = agg_t;
772 }
773
774 template <typename T, typename NATIVE_TYPE>
775 const tom::observation &
776 time_series<T,NATIVE_TYPE>::get_observation( const tom::calendars::date_int_type d ) const
777 {
778 if ( m_populate_data_func != NULL )
779 {
780 // call callback function
781 if ( (m_ds.*m_populate_data_func)( m_data, m_name,
782 tom::tsdb::native_data_type::factory( NATIVE_TYPE::Instance().id() ),
783 get_calendar(),
784 static_cast<tom::calendars::date_int_type> (m_l_first_date_int),
785 static_cast<tom::calendars::date_int_type>(m_l_last_date_int )) )
786 m_populate_data_func = NULL;
787 }
788 return m_data.get_observation( d );
789 }
790
791 template <typename T, typename NATIVE_TYPE>
792 const tom::observation &
793 time_series<T,NATIVE_TYPE>::get_observation( const tom::calendars::date d ) const
794 {
795 return this->get_observation( get_calendar()( d ) ); //m_data.get_observation( d );
796 }
797
798 template <typename T, typename NATIVE_TYPE>
799 void
800 time_series<T,NATIVE_TYPE>::set_observation( const tom::calendars::date_int_type d, const tom::observation & val )
801 {
802 if ( m_first_dirty_date_int != 0 && d < m_first_dirty_date_int )
803 m_first_dirty_date_int = d;
804
805 if ( d > m_last_dirty_date_int )
806 m_last_dirty_date_int = d;
807
808 m_data.set_observation( d, val );
809 }
810 template <typename T, typename NATIVE_TYPE>
811 void
812 time_series<T,NATIVE_TYPE>::set_observation( tom::calendars::date_int_type d, const tom::Date &v )
813 {
814 if ( m_first_dirty_date_int != 0 && d < m_first_dirty_date_int )
815 m_first_dirty_date_int = d;
816
817 if ( d > m_last_dirty_date_int )
818 m_last_dirty_date_int = d;
819
820 m_data.set_observation( d, v );
821 }
822 template <typename T, typename NATIVE_TYPE>
823 void
824 time_series<T,NATIVE_TYPE>::set_observation( tom::calendars::date d, const tom::Date &v )
825 {
826 set_observation( get_calendar()(d), v );
827 }
828
829 template <typename T, typename NATIVE_TYPE>
830 void
831 time_series<T,NATIVE_TYPE>::set_observation( const tom::calendars::date d, const tom::observation & val )
832 {
833 this->set_observation( get_calendar()( d ), val ); //m_data.set_observation( d, val );
834 }
835
836 template <typename T, typename NATIVE_TYPE>
837 const tom::observation &
838 time_series<T,NATIVE_TYPE>::operator[ ]( const tom::calendars::date_int_type d ) const
839 {
840 return this->get_observation(d); //m_data[ d ];
841 }
842 //TODO: this is a memory leak...change it!
843 template <typename T, typename NATIVE_TYPE>
845 time_series<T,NATIVE_TYPE>::operator[ ]( const tom::calendars::date_int_type d )
846 {
847 return this->get_observation(d).clone(); //m_data[ d ];
848 }
849
850 template <typename T, typename NATIVE_TYPE>
851 const tom::observation &
852 time_series<T,NATIVE_TYPE>::operator[ ] ( const tom::calendars::date d ) const
853 {
854 return this->get_observation(d); //m_data[ d ];
855 }
856
857 template <typename T, typename NATIVE_TYPE>
859 time_series<T,NATIVE_TYPE>::operator[ ] ( const tom::calendars::date d )
860 {
861 return this->get_observation(d).clone(); //m_data[ d ];
862 }
863
864
865 template <typename T, typename NATIVE_TYPE>
866 std::ostream &
867 time_series<T,NATIVE_TYPE>::print( std::ostream &os ) const
868 {
869 // force lazy init if needed
870 if ( m_populate_data_func != NULL )
871 get_observation( get_last_date_int() );
872
873 return m_data.print( os );
874 }
875
876 template <typename T, typename NATIVE_TYPE>
878 time_series<T,NATIVE_TYPE>::get_calendar( ) const
879 { return m_data.get_calendar(); }
880
881 //virtual
882 template <typename T, typename NATIVE_TYPE>
883 tom::calendars::date_int_type
884 time_series<T,NATIVE_TYPE>::get_first_date_int() const
885 {
886 tom::calendars::date_int_type fd = m_data.get_first_date_int();
887
888 if ( m_populate_data_func == NULL ) // m_data holds all data
889 return fd;
890
891 else // m_data only holds new data
892 {
893 if ( m_l_first_date_int != 0 && fd != 0 )
894 return m_l_first_date_int < fd ? m_l_first_date_int : fd;
895 else if ( m_l_first_date_int != 0 )
896 return m_l_first_date_int;
897 else
898 return fd;
899 }
900 }
901
902 //virtual
903 template <typename T, typename NATIVE_TYPE>
904 tom::calendars::date_int_type
905 time_series<T,NATIVE_TYPE>::get_last_date_int() const
906 {
907 tom::calendars::date_int_type ld = m_data.get_last_date_int();
908 if ( m_populate_data_func == NULL ) // m_data holds all data
909 return ld;
910
911 else // m_data only holds new data
912 {
913 if ( m_l_last_date_int != 0 && m_l_last_date_int > ld )
914 return m_l_last_date_int; // no data added after original last date
915
916 else
917 return ld;
918 }
919 }
920 //virtual
921 template <typename T, typename NATIVE_TYPE>
922 tom::calendars::date_int_type
924 {
925 return m_first_dirty_date_int;
926 }
927
928 //virtual
929 template <typename T, typename NATIVE_TYPE>
930 tom::calendars::date_int_type
932 {
933 return m_last_dirty_date_int;
934 }
935
936 //virtual
937 template <typename T, typename NATIVE_TYPE>
940 {
941 return m_data.begin();
942 }
943
944 //virtual
945 template <typename T, typename NATIVE_TYPE>
948 {
949 return m_data.end();
950 }
951
952 } // end collections namespace
953
954 } // end tsdb namespace
955
956} // end tom namespace
957
958 TOM_UTIL_API
959 inline
960 std::ostream &
961 operator<<( std::ostream &os, const tom::tsdb::time_series &ts )
962 {
963 return ts.print( os );
964 }
965
966#endif
Definition dates.hpp:22
Definition string.hpp:15
Definition calendar.hpp:120
Definition calendar.hpp:47
Definition time_series.hpp:309
Definition time_series.hpp:157
Definition time_series.hpp:25
Definition observation.hpp:13
Definition time_series.hpp:22
static aggregation_type begin()
Definition time_series.hpp:41
bool operator==(const aggregation_type &rhs)
Definition time_series.hpp:114
static aggregation_type low()
Definition time_series.hpp:81
static aggregation_type end()
Definition time_series.hpp:49
static aggregation_type averaged()
Definition time_series.hpp:57
static aggregation_type summed()
Definition time_series.hpp:65
const char * name() const
Definition time_series.hpp:90
static aggregation_type high()
Definition time_series.hpp:73
bool operator!=(const aggregation_type &rhs)
Definition time_series.hpp:125
Definition time_series.hpp:142
void clear()
Definition time_series.hpp:287
bool add(const char *)
Definition time_series.cpp:11
alias_set()
Definition time_series.hpp:155
alias_set & operator=(const alias_set &rhs)
Definition time_series.hpp:175
alias_set(const alias_set &rhs)
Definition time_series.hpp:168
const_iterator end() const
Definition time_series.hpp:227
bool operator==(const alias_set &rhs)
Definition time_series.hpp:186
bool remove(const char *)
Definition time_series.cpp:32
bool changed() const
Definition time_series.cpp:52
const_iterator begin() const
Definition time_series.hpp:220
bool operator!=(const alias_set &rhs)
Definition time_series.hpp:203
alias_set(IteratorT begin, IteratorT end)
Definition time_series.hpp:162
Definition time_series.hpp:580
virtual datastore & get_datastore() const
Definition time_series.hpp:610
virtual const tom::string & get_name() const
Definition time_series.hpp:615
virtual aggregation_type get_aggregation_type() const
Definition time_series.hpp:763
virtual const tom::calendars::date_time & get_create_date_time() const
Definition time_series.hpp:652
virtual bool is_sparse_series() const
Definition time_series.hpp:660
virtual void set_aggregation_type(aggregation_type)
Definition time_series.hpp:769
virtual const tom::calendars::date_time & get_modify_date_time() const
Definition time_series.hpp:656
virtual tom::calendars::date_int_type get_last_dirty_date_int() const
Definition time_series.hpp:931
virtual tom::calendars::date_int_type get_first_dirty_date_int() const
Definition time_series.hpp:923
virtual const values::data_type & get_data_type() const
Definition time_series.hpp:611
Definition datastore.hpp:445
Definition types.hpp:31
static native_data_type factory(unsigned short int t)
Definition types.hpp:57
Definition time_series.hpp:313
virtual void set_aggregation_type(aggregation_type)=0
virtual const tom::calendars::date_time & get_modify_date_time() const =0
virtual tom::tsdb::datastore & get_datastore() const =0
const tom::String & get_attribute(const tom::observation &att_name, bool check_datastore=true) const
Definition time_series.hpp:468
virtual const tom::string & get_name() const =0
virtual aggregation_type get_aggregation_type() const =0
virtual const values::data_type & get_data_type() const =0
virtual tom::calendars::date_int_type get_last_dirty_date_int() const =0
void set_attribute(const char *att_name, const char *att_value)
Definition time_series.hpp:490
virtual bool is_sparse_series() const =0
void set_attribute(const tom::observation &att_name, const tom::observation &att_value)
Definition time_series.hpp:503
const tom::String & get_attribute(const char *att_name, bool check_datastore=true) const
Definition time_series.hpp:457
virtual tom::calendars::date_int_type get_first_dirty_date_int() const =0
virtual const tom::calendars::date_time & get_create_date_time() const =0
Definition value_types.hpp:96