File indexing completed on 2025-01-30 09:35:22
0001 #ifndef DATE_TIME_DATE_GENERATORS_HPP__
0002 #define DATE_TIME_DATE_GENERATORS_HPP__
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <sstream>
0017 #include <stdexcept>
0018 #include <boost/throw_exception.hpp>
0019 #include <boost/date_time/date.hpp>
0020 #include <boost/date_time/compiler_config.hpp>
0021
0022 namespace boost {
0023 namespace date_time {
0024
0025
0026
0027
0028
0029
0030
0031 template<class date_type>
0032 class year_based_generator
0033 {
0034 public:
0035 typedef typename date_type::calendar_type calendar_type;
0036 typedef typename calendar_type::year_type year_type;
0037 year_based_generator() {}
0038 virtual ~year_based_generator() {}
0039 virtual date_type get_date(year_type y) const = 0;
0040
0041 virtual std::string to_string() const = 0;
0042 };
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 template<class date_type>
0056 class partial_date : public year_based_generator<date_type>
0057 {
0058 public:
0059 typedef typename date_type::calendar_type calendar_type;
0060 typedef typename calendar_type::day_type day_type;
0061 typedef typename calendar_type::month_type month_type;
0062 typedef typename calendar_type::year_type year_type;
0063 typedef typename date_type::duration_type duration_type;
0064 typedef typename duration_type::duration_rep duration_rep;
0065 partial_date(day_type d, month_type m) :
0066 day_(d),
0067 month_(m)
0068 {}
0069
0070
0071
0072
0073
0074 partial_date(duration_rep days) :
0075 day_(1),
0076 month_(1)
0077 {
0078 date_type d1(2000,1,1);
0079 if(days > 1) {
0080 if(days > 366)
0081 {
0082 days = 366;
0083 }
0084 days = days - 1;
0085 duration_type dd(days);
0086 d1 = d1 + dd;
0087 }
0088 day_ = d1.day();
0089 month_ = d1.month();
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 date_type get_date(year_type y) const BOOST_OVERRIDE
0102 {
0103 if((day_ == 29) && (month_ == 2) && !(calendar_type::is_leap_year(y))) {
0104 std::ostringstream ss;
0105 ss << "No Feb 29th in given year of " << y << ".";
0106 boost::throw_exception(std::invalid_argument(ss.str()));
0107 }
0108 return date_type(y, month_, day_);
0109 }
0110 date_type operator()(year_type y) const
0111 {
0112 return get_date(y);
0113
0114 }
0115 bool operator==(const partial_date& rhs) const
0116 {
0117 return (month_ == rhs.month_) && (day_ == rhs.day_);
0118 }
0119 bool operator<(const partial_date& rhs) const
0120 {
0121 if (month_ < rhs.month_) return true;
0122 if (month_ > rhs.month_) return false;
0123
0124 return (day_ < rhs.day_);
0125 }
0126
0127
0128 month_type month() const
0129 {
0130 return month_;
0131 }
0132 day_type day() const
0133 {
0134 return day_;
0135 }
0136
0137
0138
0139
0140
0141
0142 std::string to_string() const BOOST_OVERRIDE
0143 {
0144 std::ostringstream ss;
0145 date_type d(2004, month_, day_);
0146 unsigned short c = d.day_of_year();
0147 c--;
0148 ss << c;
0149 return ss.str();
0150 }
0151 private:
0152 day_type day_;
0153 month_type month_;
0154 };
0155
0156
0157 inline const char* nth_as_str(int ele)
0158 {
0159 static const char* const _nth_as_str[] = {"out of range", "first", "second",
0160 "third", "fourth", "fifth"};
0161 if(ele >= 1 && ele <= 5) {
0162 return _nth_as_str[ele];
0163 }
0164 else {
0165 return _nth_as_str[0];
0166 }
0167 }
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 template<class date_type>
0187 class nth_kday_of_month : public year_based_generator<date_type>
0188 {
0189 public:
0190 typedef typename date_type::calendar_type calendar_type;
0191 typedef typename calendar_type::day_of_week_type day_of_week_type;
0192 typedef typename calendar_type::month_type month_type;
0193 typedef typename calendar_type::year_type year_type;
0194 typedef typename date_type::duration_type duration_type;
0195 enum week_num {first=1, second, third, fourth, fifth};
0196 nth_kday_of_month(week_num week_no,
0197 day_of_week_type dow,
0198 month_type m) :
0199 month_(m),
0200 wn_(week_no),
0201 dow_(dow)
0202 {}
0203
0204 date_type get_date(year_type y) const BOOST_OVERRIDE
0205 {
0206 date_type d(y, month_, 1);
0207 duration_type one_day(1);
0208 duration_type one_week(7);
0209 while (dow_ != d.day_of_week()) {
0210 d = d + one_day;
0211 }
0212 int week = 1;
0213 while (week < wn_) {
0214 d = d + one_week;
0215 week++;
0216 }
0217
0218 if(d.month() != month_) {
0219 d = d - one_week;
0220 }
0221 return d;
0222 }
0223
0224 month_type month() const
0225 {
0226 return month_;
0227 }
0228 week_num nth_week() const
0229 {
0230 return wn_;
0231 }
0232 day_of_week_type day_of_week() const
0233 {
0234 return dow_;
0235 }
0236 const char* nth_week_as_str() const
0237 {
0238 return nth_as_str(wn_);
0239 }
0240
0241
0242 std::string to_string() const BOOST_OVERRIDE
0243 {
0244 std::ostringstream ss;
0245 ss << 'M'
0246 << static_cast<int>(month_) << '.'
0247 << static_cast<int>(wn_) << '.'
0248 << static_cast<int>(dow_);
0249 return ss.str();
0250 }
0251 private:
0252 month_type month_;
0253 week_num wn_;
0254 day_of_week_type dow_;
0255 };
0256
0257
0258
0259
0260
0261 template<class date_type>
0262 class first_kday_of_month : public year_based_generator<date_type>
0263 {
0264 public:
0265 typedef typename date_type::calendar_type calendar_type;
0266 typedef typename calendar_type::day_of_week_type day_of_week_type;
0267 typedef typename calendar_type::month_type month_type;
0268 typedef typename calendar_type::year_type year_type;
0269 typedef typename date_type::duration_type duration_type;
0270
0271
0272
0273
0274 first_kday_of_month(day_of_week_type dow, month_type m) :
0275 month_(m),
0276 dow_(dow)
0277 {}
0278
0279 date_type get_date(year_type year) const BOOST_OVERRIDE
0280 {
0281 date_type d(year, month_,1);
0282 duration_type one_day(1);
0283 while (dow_ != d.day_of_week()) {
0284 d = d + one_day;
0285 }
0286 return d;
0287 }
0288
0289 month_type month() const
0290 {
0291 return month_;
0292 }
0293 day_of_week_type day_of_week() const
0294 {
0295 return dow_;
0296 }
0297
0298
0299 std::string to_string() const BOOST_OVERRIDE
0300 {
0301 std::ostringstream ss;
0302 ss << 'M'
0303 << static_cast<int>(month_) << '.'
0304 << 1 << '.'
0305 << static_cast<int>(dow_);
0306 return ss.str();
0307 }
0308 private:
0309 month_type month_;
0310 day_of_week_type dow_;
0311 };
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322 template<class date_type>
0323 class last_kday_of_month : public year_based_generator<date_type>
0324 {
0325 public:
0326 typedef typename date_type::calendar_type calendar_type;
0327 typedef typename calendar_type::day_of_week_type day_of_week_type;
0328 typedef typename calendar_type::month_type month_type;
0329 typedef typename calendar_type::year_type year_type;
0330 typedef typename date_type::duration_type duration_type;
0331
0332
0333
0334
0335 last_kday_of_month(day_of_week_type dow, month_type m) :
0336 month_(m),
0337 dow_(dow)
0338 {}
0339
0340 date_type get_date(year_type year) const BOOST_OVERRIDE
0341 {
0342 date_type d(year, month_, calendar_type::end_of_month_day(year,month_));
0343 duration_type one_day(1);
0344 while (dow_ != d.day_of_week()) {
0345 d = d - one_day;
0346 }
0347 return d;
0348 }
0349
0350 month_type month() const
0351 {
0352 return month_;
0353 }
0354 day_of_week_type day_of_week() const
0355 {
0356 return dow_;
0357 }
0358
0359
0360 std::string to_string() const BOOST_OVERRIDE
0361 {
0362 std::ostringstream ss;
0363 ss << 'M'
0364 << static_cast<int>(month_) << '.'
0365 << 5 << '.'
0366 << static_cast<int>(dow_);
0367 return ss.str();
0368 }
0369 private:
0370 month_type month_;
0371 day_of_week_type dow_;
0372 };
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 template<class date_type>
0385 class first_kday_after
0386 {
0387 public:
0388 typedef typename date_type::calendar_type calendar_type;
0389 typedef typename calendar_type::day_of_week_type day_of_week_type;
0390 typedef typename date_type::duration_type duration_type;
0391 first_kday_after(day_of_week_type dow) :
0392 dow_(dow)
0393 {}
0394
0395 date_type get_date(date_type start_day) const
0396 {
0397 duration_type one_day(1);
0398 date_type d = start_day + one_day;
0399 while (dow_ != d.day_of_week()) {
0400 d = d + one_day;
0401 }
0402 return d;
0403 }
0404
0405 day_of_week_type day_of_week() const
0406 {
0407 return dow_;
0408 }
0409 private:
0410 day_of_week_type dow_;
0411 };
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 template<class date_type>
0423 class first_kday_before
0424 {
0425 public:
0426 typedef typename date_type::calendar_type calendar_type;
0427 typedef typename calendar_type::day_of_week_type day_of_week_type;
0428 typedef typename date_type::duration_type duration_type;
0429 first_kday_before(day_of_week_type dow) :
0430 dow_(dow)
0431 {}
0432
0433 date_type get_date(date_type start_day) const
0434 {
0435 duration_type one_day(1);
0436 date_type d = start_day - one_day;
0437 while (dow_ != d.day_of_week()) {
0438 d = d - one_day;
0439 }
0440 return d;
0441 }
0442
0443 day_of_week_type day_of_week() const
0444 {
0445 return dow_;
0446 }
0447 private:
0448 day_of_week_type dow_;
0449 };
0450
0451
0452
0453
0454
0455 template<typename date_type, class weekday_type>
0456 inline
0457 typename date_type::duration_type days_until_weekday(const date_type& d, const weekday_type& wd)
0458 {
0459 typedef typename date_type::duration_type duration_type;
0460 duration_type wks(0);
0461 duration_type dd(wd.as_number() - d.day_of_week().as_number());
0462 if(dd.is_negative()){
0463 wks = duration_type(7);
0464 }
0465 return dd + wks;
0466 }
0467
0468
0469
0470
0471
0472
0473 template<typename date_type, class weekday_type>
0474 inline
0475 typename date_type::duration_type days_before_weekday(const date_type& d, const weekday_type& wd)
0476 {
0477 typedef typename date_type::duration_type duration_type;
0478 duration_type wks(0);
0479 duration_type dd(wd.as_number() - d.day_of_week().as_number());
0480 if(dd.days() > 0){
0481 wks = duration_type(7);
0482 }
0483
0484
0485 return (-dd + wks);
0486 }
0487
0488
0489
0490
0491
0492
0493 template<class date_type, class weekday_type>
0494 inline
0495 date_type next_weekday(const date_type& d, const weekday_type& wd)
0496 {
0497 return d + days_until_weekday(d, wd);
0498 }
0499
0500
0501
0502
0503
0504
0505 template<class date_type, class weekday_type>
0506 inline
0507 date_type previous_weekday(const date_type& d, const weekday_type& wd)
0508 {
0509 return d - days_before_weekday(d, wd);
0510 }
0511
0512 } }
0513
0514 #endif