1#ifndef HAVE_TOM_CALENDAR_HPP
2#define HAVE_TOM_CALENDAR_HPP
4#include <tom-util/defines.hpp>
11#include <boost/date_time/gregorian/gregorian.hpp>
12#include <boost/date_time/posix_time/posix_time.hpp>
17typedef boost::gregorian::date::date_int_type date_int_type;
18typedef long wdate_int_type;
19typedef boost::gregorian::date_duration date_duration;
20typedef boost::gregorian::greg_month greg_month;
21typedef boost::gregorian::greg_year greg_year;
22typedef boost::gregorian::greg_day greg_day;
23typedef boost::gregorian::greg_year_month_day greg_year_month_day;
24typedef boost::gregorian::gregorian_calendar gregorian_calendar;
26using boost::gregorian::to_simple_string;
27using boost::gregorian::to_iso_extended_string;
28using boost::gregorian::from_string;
29using boost::gregorian::from_undelimited_string;
30using boost::gregorian::day_clock;
31using boost::posix_time::ptime;
32using boost::posix_time::time_duration;
33using boost::posix_time::hours;
34using boost::posix_time::minutes;
35using boost::posix_time::seconds;
36using boost::posix_time::millisec;
39using boost::posix_time::to_simple_string;
40using boost::posix_time::to_iso_string;
42typedef ptime date_time;
46class TOM_UTIL_API
date :
public boost::gregorian::date
49 date( greg_year y, greg_month m, greg_day d);
51 date(
const date &d ) : boost::gregorian::date(d) { }
53 date(
const boost::gregorian::date &d ) : boost::gregorian::date(d) { }
55 date( boost::gregorian::greg_year_month_day d ) : boost::gregorian::date(d) { }
57 date( date_int_type d ) : boost::gregorian::date( 1900,1,1) { days_ = d; }
59 date_int_type days()
const {
return days_; }
69 if ( tspec ) {
m_tspec.tv_sec = tspec->tv_sec;
m_tspec.tv_nsec = tspec->tv_nsec; }
75 if ( tspec ) {
m_tspec.tv_sec = tspec->tv_sec;
m_tspec.tv_nsec = tspec->tv_nsec; }
80 if ( tspec ) {
m_tspec.tv_sec = tspec->tv_sec;
m_tspec.tv_nsec = tspec->tv_nsec; }
85 if ( tspec ) {
m_tspec.tv_sec = tspec->tv_sec;
m_tspec.tv_nsec = tspec->tv_nsec; }
90 if ( tspec ) {
m_tspec.tv_sec = tspec->tv_sec;
m_tspec.tv_nsec = tspec->tv_nsec; }
104class TOM_UTIL_API
date_period :
public boost::gregorian::date_period
108 date_period( boost::gregorian::date begin, boost::gregorian::date end ) :
109 boost::gregorian::date_period(begin, end) { }
110 date_period(
date begin, boost::gregorian::date_duration d ) : boost::gregorian::date_period( begin, d) { }
112 date_period(
const boost::gregorian::date_period & rhs) : boost::gregorian::date_period( rhs ) { }
123 virtual date_int_type operator()(
const date & )
const = 0;
124 virtual date operator()( date_int_type )
const = 0;
126 virtual date_period get_date_period( date_int_type )
const = 0;
127 virtual bool operator==(
const calendar &rhs )
const = 0;
128 virtual bool operator!=(
const calendar &rhs )
const = 0;
129 virtual const date &get_first_date( )
const = 0;
130 virtual const char *name()
const = 0;
150 date_period( cal.get_date_period( start ).begin(), cal.get_date_period( end ).end() ),
153 date_period( cal.get_date_period( i ).begin(), cal.get_date_period( i ).end() + date_duration(1) ) ,
157 m_calendar( rhs.m_calendar ) { }
160 this->date_period::operator=( rhs );
161 this->m_calendar = rhs.m_calendar;
165 const calendar &get_calendar()
const {
return m_calendar; }
166 date get_first_date( )
const {
return begin( ); }
167 date get_last_date( )
const {
return last( ); }
168 date get_end_date( )
const {
return end( ); }
169 date_int_type get_first_date_int( )
const {
return m_calendar( begin() ); }
170 date_int_type get_last_date_int( )
const {
return m_calendar( last() ); }
181template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
184 static const date first_date;
186 static int get_first_year() {
return FIRST_YEAR; }
188 static int get_first_month() {
return FIRST_MONTH; }
190 static int get_first_day() {
return FIRST_DAY; }
192 static date get_first_date() {
return date( FIRST_YEAR, FIRST_MONTH, FIRST_DAY ); }
195template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
210template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
213 date operator()( date_int_type )
const;
214 date_int_type operator()(
const date & )
const;
218template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
223 return d.days() - this->first_date.days() + 1;
226template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
229daily_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
231 return date( boost::gregorian::gregorian_calendar::from_day_number( di + this->first_date.days() -1 ));
234template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
237 date operator()( date_int_type )
const;
238 date_int_type operator()(
const date & )
const;
241template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
247 switch (d.day_of_week() )
249 case boost::gregorian::Saturday:
250 d += date_duration( 2 );
252 case boost::gregorian::Sunday:
253 d += date_duration( 1 );
255 date_int_type corrected = d.days() - this->first_date.days() + 1;
256 int m = corrected % 7;
257 if ( m == 5 || m == 6 )
260 return corrected - (( corrected / 7 ) * 2);
263template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
266business_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
268 date_int_type corrected = di * 7;
269 date_int_type offset = 1;
270 if ( (corrected % 5) % 2 == 1 )
273 return date( this->first_date + date_duration( corrected - offset ) );
277template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
280 static const boost::gregorian::date_duration duration;
281 date operator()( date_int_type )
const;
282 date_int_type operator()(
const date & )
const;
286template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
289template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
295 while ( tmp.day_of_week() != this->first_date.day_of_week() ) { tmp += date_duration(1); }
296 date_duration dd = tmp - this->first_date;
297 date_int_type di = dd.days() / duration.days();
300template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
303weekly_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
305 date_duration reversed = date_duration(date_duration( (di - 1) ).days() * duration.days());
306 date tmp = this->first_date;
311template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
314 date operator()( date_int_type )
const;
315 date_int_type operator()(
const date & )
const;
319template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
324 return ( d.year() - this->first_date.year() ) * 12 + d.month();
327template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
330month_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
332 unsigned short mod = di % 12;
333 greg_month month( mod == 0 ? 12 : mod );
335 greg_year year = di / 12 + this->first_date.year() - ( mod == 0 ? 1 : 0 );
336 short int day = gregorian_calendar::end_of_month_day( year, month );
337 return date ( year, month, day );
340template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
343 date operator()( date_int_type )
const;
344 date_int_type operator()(
const date & )
const;
345 static greg_month first_month;
348template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
353template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
358 date_int_type qtrs = ( d.year() - this->first_date.year() ) * 4 + 1;
359 signed short d_mon = d.month();
360 signed short first_qtr = ( first_month / 3 + ( first_month % 3 != 0 ? 1 : 0 ) );
361 signed short d_qtr = ( d_mon / 3 + ( d_mon % 3 != 0 ? 1 : 0 ) );
362 return qtrs + ( d_qtr - first_qtr );
365template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
368quarterly_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
370 signed short yr_mod = di % 4;
371 signed short mon_mod = yr_mod != 0 ? yr_mod - 1 : 3;
372 unsigned int year = (di / 4) + this->first_date.year();
373 unsigned short month = first_month + (mon_mod * 3);
374 if ( month > 12 ){ month = month - 12; }
375 if ( first_month == 3 && yr_mod == 0 ) year--;
376 short int day = gregorian_calendar::end_of_month_day( year, month );
377 return date ( year, month, day );
380template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
383 date operator()( date_int_type )
const;
384 date_int_type operator()(
const date & )
const;
385 static greg_month first_month;
388template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
393template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
398 date_int_type qtrs = ( d.year() - this->first_date.year() ) * 2 + 1;
399 signed short d_mon = d.month();
400 signed short first_qtr = ( first_month / 6 + ( first_month % 6 != 0 ? 1 : 0 ) );
401 signed short d_qtr = ( d_mon / 6 + ( d_mon % 6 != 0 ? 1 : 0 ) );
402 return qtrs + ( d_qtr - first_qtr);
405template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
408semiannual_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
410 signed short yr_mod = di % 2;
411 signed short mon_mod = yr_mod != 0 ? yr_mod -1 : 1;
412 unsigned int year = (di / 2) + this->first_date.year();
413 unsigned short month = first_month + ( mon_mod * 6 );
414 if ( month > 12 ){ month = month - 12; }
415 if ( first_month == 6 && yr_mod == 0 ) year--;
416 short int day = gregorian_calendar::end_of_month_day( year, month );
417 return date ( year, month, day );
420template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
423 date operator()( date_int_type )
const;
424 date_int_type operator()(
const date & )
const;
427template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
432 return d.year() - this->first_date.year() + 1;
435template <
int FIRST_YEAR,
int FIRST_MONTH,
int FIRST_DAY>
438annual_converter<FIRST_YEAR,FIRST_MONTH,FIRST_DAY>::operator()( date_int_type di )
const
440 greg_year year = di + this->first_date.year() - 1;
441 greg_month month = FIRST_MONTH;
442 short int day = gregorian_calendar::end_of_month_day( year, month );
443 return date ( year, month, day );
450template <
typename CONVERTER>
454 typedef date::date_int_type date_int_type;
455 typedef CONVERTER converter_type;
459 virtual date_int_type operator()(
const date & )
const;
460 virtual date operator()( date_int_type )
const;
462 virtual date_period get_date_period( date_int_type )
const;
463 virtual bool operator==(
const calendar &rhs )
const;
464 virtual bool operator!=(
const calendar &rhs )
const;
465 virtual const date &get_first_date( )
const;
466 virtual const char *name()
const;
474template <
typename CONVERTER>
487template <
typename CONVERTER>
490calendar_impl<CONVERTER>::operator==(
const calendar &rhs )
const
500template <
typename CONVERTER>
503calendar_impl<CONVERTER>::operator!=(
const calendar &rhs )
const
510template <
typename CONVERTER>
513calendar_impl<CONVERTER>::get_first_date( )
const
515 return CONVERTER::first_date;
518template <
typename CONVERTER>
520calendar_impl<CONVERTER> &
521calendar_impl<CONVERTER>::Instance()
523 static calendar_impl calendar;
526template <
typename CONVERTER>
529calendar_impl<CONVERTER>::operator()(
const date &d )
const
531 return converter (d);
533template <
typename CONVERTER>
536calendar_impl<CONVERTER>::operator()( date_int_type d )
const
538 return converter (d);
540template <
typename CONVERTER>
543calendar_impl<CONVERTER>::get_date_period( date_int_type d )
const
545 date end = converter (d);
546 date prev = converter( d -1 );
549 return date_period( prev + date_duration(1), end + date_duration(1) );
551template <
typename CONVERTER>
554calendar_impl<CONVERTER>::get_date_period(
const date &d )
const
556 date_int_type end_date_int = converter (d);
557 date end = converter ( end_date_int );
558 date prev = converter ( end_date_int -1 );
559 return date_period( prev + date_duration(1), end + date_duration(1) );
573typedef calendar_impl< daily_converter<1850,1,1> > timestamp_calendar;
574typedef calendar_impl< daily_converter<1401,1,1> > ordinal_calendar;
575typedef calendar_impl< daily_converter<1850,1,1> > daily_calendar;
576typedef calendar_impl< business_converter<1850,1,1> > business_calendar;
577typedef calendar_impl< weekly_converter<1850,1,7> > weekly_monday_calendar;
578typedef calendar_impl< weekly_converter<1850,1,8> > weekly_tuesday_calendar;
579typedef calendar_impl< weekly_converter<1850,1,9> > weekly_wednesday_calendar;
580typedef calendar_impl< weekly_converter<1850,1,10> > weekly_thursday_calendar;
581typedef calendar_impl< weekly_converter<1850,1,11> > weekly_friday_calendar;
582typedef calendar_impl< weekly_converter<1850,1,12> > weekly_saturday_calendar;
583typedef calendar_impl< weekly_converter<1850,1,13> > weekly_sunday_calendar;
584typedef calendar_impl< month_converter<1850,1,31> > monthly_calendar;
585typedef calendar_impl< quarterly_converter<1850,4,30> > quarterly_october_calendar;
586typedef calendar_impl< quarterly_converter<1850,5,31> > quarterly_november_calendar;
587typedef calendar_impl< quarterly_converter<1850,3,31> > quarterly_december_calendar;
588typedef calendar_impl< semiannual_converter<1850,7,31> > semiannual_july_calendar;
589typedef calendar_impl< semiannual_converter<1850,8,31> > semiannual_august_calendar;
590typedef calendar_impl< semiannual_converter<1850,9,30> > semiannual_september_calendar;
591typedef calendar_impl< semiannual_converter<1850,10,31> > semiannual_october_calendar;
592typedef calendar_impl< semiannual_converter<1850,11,30> > semiannual_november_calendar;
593typedef calendar_impl< semiannual_converter<1850,6,30> > semiannual_december_calendar;
594typedef calendar_impl< annual_converter<1851,1,31> > annual_january_calendar;
595typedef calendar_impl< annual_converter<1851,2,28> > annual_february_calendar;
596typedef calendar_impl< annual_converter<1851,3,31> > annual_march_calendar;
597typedef calendar_impl< annual_converter<1851,4,30> > annual_april_calendar;
598typedef calendar_impl< annual_converter<1851,5,31> > annual_may_calendar;
599typedef calendar_impl< annual_converter<1851,6,30> > annual_june_calendar;
600typedef calendar_impl< annual_converter<1851,7,31> > annual_july_calendar;
601typedef calendar_impl< annual_converter<1851,8,31> > annual_august_calendar;
602typedef calendar_impl< annual_converter<1851,9,30> > annual_september_calendar;
603typedef calendar_impl< annual_converter<1851,10,31> > annual_october_calendar;
604typedef calendar_impl< annual_converter<1851,11,30> > annual_november_calendar;
605typedef calendar_impl< annual_converter<1850,12,31> > annual_december_calendar;
608typedef weekly_friday_calendar weekly_calendar;
609typedef quarterly_december_calendar quarterly_calendar;
610typedef semiannual_december_calendar semiannual_calendar;
611typedef annual_december_calendar annual_calendar;
617 template <
typename COLLECTION_T>
619 populate_calendar_map( );
625 typedef std::map< const tom::calendars::calendar *, const char *> map_t;
626 static std::unique_ptr<map_t> map( populate_calendar_map<map_t>() );
627 map_t::const_iterator it = map->find( cal );
628 if ( it != map->end() )
633 template <
typename COLLECTION_T>
636 populate_calendar_map( )
638 typedef typename COLLECTION_T::value_type value_type;
639 static value_type items[] = {
640 value_type( &ordinal_calendar::Instance(),
"Ordinal" ),
641 value_type( &daily_calendar::Instance(),
"Daily" ),
642 value_type( &business_calendar::Instance(),
"Business" ),
643 value_type( &weekly_monday_calendar::Instance(),
"Weekly(Mon)" ),
644 value_type( &weekly_tuesday_calendar::Instance(),
"Weekly(Tue)" ),
645 value_type( &weekly_wednesday_calendar::Instance(),
"Weekly(Wed)" ),
646 value_type( &weekly_thursday_calendar::Instance(),
"Weekly(Thu)" ),
647 value_type( &weekly_friday_calendar::Instance(),
"Weekly(Fri)" ),
648 value_type( &weekly_saturday_calendar::Instance(),
"Weekly(Sat)" ),
649 value_type( &weekly_sunday_calendar::Instance(),
"Weekly(Sun)" ),
650 value_type( &monthly_calendar::Instance(),
"Monthly" ),
651 value_type( &quarterly_october_calendar::Instance(),
"Quarterly(Oct)" ),
652 value_type( &quarterly_november_calendar::Instance(),
"Quarterly(Nov)" ),
653 value_type( &quarterly_december_calendar::Instance(),
"Quarterly(Dec)" ),
654 value_type( &semiannual_july_calendar::Instance(),
"Semiannual(Jul)" ),
655 value_type( &semiannual_august_calendar::Instance(),
"Semiannual(Aug)" ),
656 value_type( &semiannual_september_calendar::Instance(),
"Semiannual(Sep)" ),
657 value_type( &semiannual_october_calendar::Instance(),
"Semiannual(Oct)" ),
658 value_type( &semiannual_november_calendar::Instance(),
"Semiannual(Nov)" ),
659 value_type( &semiannual_december_calendar::Instance(),
"Semiannual(Dec)" ),
660 value_type( &annual_january_calendar::Instance(),
"Annual(Jan)" ),
661 value_type( &annual_february_calendar::Instance(),
"Annual(Feb)" ),
662 value_type( &annual_march_calendar::Instance(),
"Annual(Mar)" ),
663 value_type( &annual_april_calendar::Instance(),
"Annual(Apr)" ),
664 value_type( &annual_may_calendar::Instance(),
"Annual(May)" ),
665 value_type( &annual_june_calendar::Instance(),
"Annual(Jun)" ),
666 value_type( &annual_july_calendar::Instance(),
"Annual(Jul)" ),
667 value_type( &annual_august_calendar::Instance(),
"Annual(Aug)" ),
668 value_type( &annual_september_calendar::Instance(),
"Annual(Sep)" ),
669 value_type( &annual_october_calendar::Instance(),
"Annual(Oct)" ),
670 value_type( &annual_november_calendar::Instance(),
"Annual(Nov)" ),
671 value_type( &annual_december_calendar::Instance(),
"Annual(Dec)" )
673 COLLECTION_T *result =
new COLLECTION_T( items, items +
674 (
sizeof(items) /
sizeof( value_type ) ) );
679 template <
typename CONVERTER>
682 calendar_impl<CONVERTER>::name()
const
686 return lookup_name(
this );
Definition calendar.hpp:452
Definition calendar.hpp:120
Definition calendar.hpp:105
Definition calendar.hpp:47
Definition calendar.hpp:147
Definition calendar.hpp:64
Definition calendar.hpp:422
Definition calendar.hpp:236
Definition calendar.hpp:183
Definition calendar.hpp:212
Definition calendar.hpp:313
Definition calendar.hpp:342
Definition calendar.hpp:382
Definition calendar.hpp:98
Definition calendar.hpp:279