1 // 2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 #ifndef BOOST_LOCALE_DATE_TIME_HPP_INCLUDED 9 #define BOOST_LOCALE_DATE_TIME_HPP_INCLUDED 10 11 #include <boost/locale/config.hpp> 12 #ifdef BOOST_MSVC 13 # pragma warning(push) 14 # pragma warning(disable : 4275 4251 4231 4660) 15 #endif 16 17 #include <boost/locale/hold_ptr.hpp> 18 #include <boost/locale/date_time_facet.hpp> 19 #include <boost/locale/formatting.hpp> 20 #include <boost/locale/time_zone.hpp> 21 #include <locale> 22 #include <vector> 23 #include <stdexcept> 24 25 26 namespace boost { 27 namespace locale { 28 /// 29 /// \defgroup date_time Date, Time, Timezone and Calendar manipulations 30 /// 31 /// This module provides various calendar, timezone and date time services 32 /// 33 /// @{ 34 35 36 /// 37 /// \brief This error is thrown in case of invalid state that occurred 38 /// 39 class BOOST_SYMBOL_VISIBLE date_time_error : public std::runtime_error { 40 public: 41 /// 42 /// Constructor of date_time_error class 43 /// date_time_error(std::string const & e)44 date_time_error(std::string const &e) : std::runtime_error(e) {} 45 }; 46 47 48 /// 49 /// \brief This class represents a pair of period_type and the integer 50 /// values that describes its amount. For example 3 days or 4 years. 51 /// 52 /// Usually obtained as product of period_type and integer or 53 /// my calling a representative functions 54 /// For example day()*3 == date_time_period(day(),3) == day(3) 55 /// 56 struct date_time_period 57 { 58 period::period_type type; ///< The type of period, i.e. era, year, day etc. 59 int value; ///< The value the actual number of \a periods 60 /// 61 /// Operator + returns copy of itself 62 /// operator +boost::locale::date_time_period63 date_time_period operator+() const { return *this; } 64 /// 65 /// Operator -, switches the sign of period 66 /// operator -boost::locale::date_time_period67 date_time_period operator-() const { return date_time_period(type,-value); } 68 69 /// 70 /// Constructor that creates date_time_period from period_type \a f and a value \a v -- default 1. 71 /// date_time_periodboost::locale::date_time_period72 date_time_period(period::period_type f=period::period_type(),int v=1) : type(f), value(v) {} 73 }; 74 75 namespace period { 76 /// 77 /// Get period_type for: special invalid value, should not be used directly 78 /// invalid()79 inline period_type invalid(){ return period_type(marks::invalid); } 80 /// 81 /// Get period_type for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] 82 /// era()83 inline period_type era(){ return period_type(marks::era); } 84 /// 85 /// Get period_type for: Year, it is calendar specific, for example 2011 in Gregorian calendar. 86 /// year()87 inline period_type year(){ return period_type(marks::year); } 88 /// 89 /// Get period_type for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. 90 /// extended_year()91 inline period_type extended_year(){ return period_type(marks::extended_year); } 92 /// 93 /// Get period_type for: The month of year, calendar specific, in Gregorian [0..11] 94 /// month()95 inline period_type month(){ return period_type(marks::month); } 96 /// 97 /// Get period_type for: The day of month, calendar specific, in Gregorian [1..31] 98 /// day()99 inline period_type day(){ return period_type(marks::day); } 100 /// 101 /// Get period_type for: The number of day in year, starting from 1, in Gregorian [1..366] 102 /// day_of_year()103 inline period_type day_of_year(){ return period_type(marks::day_of_year); } 104 /// 105 /// Get period_type for: Day of week, Sunday=1, Monday=2,..., Saturday=7. 106 /// 107 /// Note that updating this value respects local day of week, so for example, 108 /// If first day of week is Monday and the current day is Tuesday then setting 109 /// the value to Sunday (1) would forward the date by 5 days forward and not backward 110 /// by two days as it could be expected if the numbers were taken as is. 111 /// day_of_week()112 inline period_type day_of_week(){ return period_type(marks::day_of_week); } 113 /// 114 /// Get period_type for: Original number of the day of the week in month. For example 1st Sunday, 115 /// 2nd Sunday, etc. in Gregorian [1..5] 116 /// day_of_week_in_month()117 inline period_type day_of_week_in_month(){ return period_type(marks::day_of_week_in_month); } 118 /// 119 /// Get period_type for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] 120 /// day_of_week_local()121 inline period_type day_of_week_local(){ return period_type(marks::day_of_week_local); } 122 /// 123 /// Get period_type for: 24 clock hour [0..23] 124 /// hour()125 inline period_type hour(){ return period_type(marks::hour); } 126 /// 127 /// Get period_type for: 12 clock hour [0..11] 128 /// hour_12()129 inline period_type hour_12(){ return period_type(marks::hour_12); } 130 /// 131 /// Get period_type for: am or pm marker [0..1] 132 /// am_pm()133 inline period_type am_pm(){ return period_type(marks::am_pm); } 134 /// 135 /// Get period_type for: minute [0..59] 136 /// minute()137 inline period_type minute(){ return period_type(marks::minute); } 138 /// 139 /// Get period_type for: second [0..59] 140 /// second()141 inline period_type second(){ return period_type(marks::second); } 142 /// 143 /// Get period_type for: The week number in the year 144 /// week_of_year()145 inline period_type week_of_year(){ return period_type(marks::week_of_year); } 146 /// 147 /// Get period_type for: The week number within current month 148 /// week_of_month()149 inline period_type week_of_month(){ return period_type(marks::week_of_month); } 150 /// 151 /// Get period_type for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2 152 /// first_day_of_week()153 inline period_type first_day_of_week(){ return period_type(marks::first_day_of_week); } 154 155 /// 156 /// Get date_time_period for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] 157 /// era(int v)158 inline date_time_period era(int v) { return date_time_period(era(),v); } 159 /// 160 /// Get date_time_period for: Year, it is calendar specific, for example 2011 in Gregorian calendar. 161 /// year(int v)162 inline date_time_period year(int v) { return date_time_period(year(),v); } 163 /// 164 /// Get date_time_period for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. 165 /// extended_year(int v)166 inline date_time_period extended_year(int v) { return date_time_period(extended_year(),v); } 167 /// 168 /// Get date_time_period for: The month of year, calendar specific, in Gregorian [0..11] 169 /// month(int v)170 inline date_time_period month(int v) { return date_time_period(month(),v); } 171 /// 172 /// Get date_time_period for: The day of month, calendar specific, in Gregorian [1..31] 173 /// day(int v)174 inline date_time_period day(int v) { return date_time_period(day(),v); } 175 /// 176 /// Get date_time_period for: The number of day in year, starting from 1, in Gregorian [1..366] 177 /// day_of_year(int v)178 inline date_time_period day_of_year(int v) { return date_time_period(day_of_year(),v); } 179 /// 180 /// Get date_time_period for: Day of week, Sunday=1, Monday=2,..., Saturday=7. 181 /// 182 /// Note that updating this value respects local day of week, so for example, 183 /// If first day of week is Monday and the current day is Tuesday then setting 184 /// the value to Sunday (1) would forward the date by 5 days forward and not backward 185 /// by two days as it could be expected if the numbers were taken as is. 186 /// day_of_week(int v)187 inline date_time_period day_of_week(int v) { return date_time_period(day_of_week(),v); } 188 /// 189 /// Get date_time_period for: Original number of the day of the week in month. For example 1st Sunday, 190 /// 2nd Sunday, etc. in Gregorian [1..5] 191 /// day_of_week_in_month(int v)192 inline date_time_period day_of_week_in_month(int v) { return date_time_period(day_of_week_in_month(),v); } 193 /// 194 /// Get date_time_period for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] 195 /// day_of_week_local(int v)196 inline date_time_period day_of_week_local(int v) { return date_time_period(day_of_week_local(),v); } 197 /// 198 /// Get date_time_period for: 24 clock hour [0..23] 199 /// hour(int v)200 inline date_time_period hour(int v) { return date_time_period(hour(),v); } 201 /// 202 /// Get date_time_period for: 12 clock hour [0..11] 203 /// hour_12(int v)204 inline date_time_period hour_12(int v) { return date_time_period(hour_12(),v); } 205 /// 206 /// Get date_time_period for: am or pm marker [0..1] 207 /// am_pm(int v)208 inline date_time_period am_pm(int v) { return date_time_period(am_pm(),v); } 209 /// 210 /// Get date_time_period for: minute [0..59] 211 /// minute(int v)212 inline date_time_period minute(int v) { return date_time_period(minute(),v); } 213 /// 214 /// Get date_time_period for: second [0..59] 215 /// second(int v)216 inline date_time_period second(int v) { return date_time_period(second(),v); } 217 /// 218 /// Get date_time_period for: The week number in the year 219 /// week_of_year(int v)220 inline date_time_period week_of_year(int v) { return date_time_period(week_of_year(),v); } 221 /// 222 /// Get date_time_period for: The week number within current month 223 /// week_of_month(int v)224 inline date_time_period week_of_month(int v) { return date_time_period(week_of_month(),v); } 225 /// 226 /// Get date_time_period for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2 227 /// first_day_of_week(int v)228 inline date_time_period first_day_of_week(int v) { return date_time_period(first_day_of_week(),v); } 229 230 /// 231 /// Get predefined constant for January 232 /// january()233 inline date_time_period january() { return date_time_period(month(),0); } 234 /// 235 /// Get predefined constant for February 236 /// february()237 inline date_time_period february() { return date_time_period(month(),1); } 238 /// 239 /// Get predefined constant for March 240 /// march()241 inline date_time_period march() { return date_time_period(month(),2); } 242 /// 243 /// Get predefined constant for April 244 /// april()245 inline date_time_period april() { return date_time_period(month(),3); } 246 /// 247 /// Get predefined constant for May 248 /// may()249 inline date_time_period may() { return date_time_period(month(),4); } 250 /// 251 /// Get predefined constant for June 252 /// june()253 inline date_time_period june() { return date_time_period(month(),5); } 254 /// 255 /// Get predefined constant for July 256 /// july()257 inline date_time_period july() { return date_time_period(month(),6); } 258 /// 259 /// Get predefined constant for August 260 /// august()261 inline date_time_period august() { return date_time_period(month(),7); } 262 /// 263 /// Get predefined constant for September 264 /// september()265 inline date_time_period september() { return date_time_period(month(),8); } 266 /// 267 /// Get predefined constant for October 268 /// october()269 inline date_time_period october() { return date_time_period(month(),9); } 270 /// 271 /// Get predefined constant for November 272 /// november()273 inline date_time_period november() { return date_time_period(month(),10); } 274 /// 275 /// Get predefined constant for December 276 /// december()277 inline date_time_period december() { return date_time_period(month(),11); } 278 279 /// 280 /// Get predefined constant for Sunday 281 /// sunday()282 inline date_time_period sunday() { return date_time_period(day_of_week(),1); } 283 /// 284 /// Get predefined constant for Monday 285 /// monday()286 inline date_time_period monday() { return date_time_period(day_of_week(),2); } 287 /// 288 /// Get predefined constant for Tuesday 289 /// tuesday()290 inline date_time_period tuesday() { return date_time_period(day_of_week(),3); } 291 /// 292 /// Get predefined constant for Wednesday 293 /// wednesday()294 inline date_time_period wednesday() { return date_time_period(day_of_week(),4); } 295 /// 296 /// Get predefined constant for Thursday 297 /// thursday()298 inline date_time_period thursday() { return date_time_period(day_of_week(),5); } 299 /// 300 /// Get predefined constant for Friday 301 /// friday()302 inline date_time_period friday() { return date_time_period(day_of_week(),6); } 303 /// 304 /// Get predefined constant for Saturday 305 /// saturday()306 inline date_time_period saturday() { return date_time_period(day_of_week(),7); } 307 /// 308 /// Get predefined constant for AM (Ante Meridiem) 309 /// am()310 inline date_time_period am() { return date_time_period(am_pm(),0); } 311 /// 312 /// Get predefined constant for PM (Post Meridiem) 313 /// pm()314 inline date_time_period pm() { return date_time_period(am_pm(),1); } 315 316 /// 317 /// convert period_type to date_time_period(f,1) 318 /// operator +(period::period_type f)319 inline date_time_period operator+(period::period_type f) 320 { 321 return date_time_period(f); 322 } 323 /// 324 /// convert period_type to date_time_period(f,-1) 325 /// operator -(period::period_type f)326 inline date_time_period operator-(period::period_type f) 327 { 328 return date_time_period(f,-1); 329 } 330 331 /// 332 /// Create date_time_period of type \a f with value \a v. 333 /// 334 template<typename T> operator *(period::period_type f,T v)335 date_time_period operator*(period::period_type f,T v) 336 { 337 return date_time_period(f,v); 338 } 339 340 /// 341 /// Create date_time_period of type \a f with value \a v. 342 /// 343 template<typename T> operator *(T v,period::period_type f)344 date_time_period operator*(T v,period::period_type f) 345 { 346 return date_time_period(f,v); 347 } 348 /// 349 /// Create date_time_period of type \a f with value \a v. 350 /// 351 template<typename T> operator *(T v,date_time_period f)352 date_time_period operator*(T v,date_time_period f) 353 { 354 return date_time_period(f.type,f.value*v); 355 } 356 357 /// 358 /// Create date_time_period of type \a f with value \a v. 359 /// 360 template<typename T> operator *(date_time_period f,T v)361 date_time_period operator*(date_time_period f,T v) 362 { 363 return date_time_period(f.type,f.value*v); 364 } 365 366 367 } // period 368 369 370 /// 371 /// \brief this class that represents a set of periods, 372 /// 373 /// It is generally created by operations on periods: 374 /// 1995*year + 3*month + 1*day. Note: operations are not commutative. 375 /// 376 class date_time_period_set { 377 public: 378 379 /// 380 /// Default constructor - empty set 381 /// date_time_period_set()382 date_time_period_set() 383 { 384 } 385 /// 386 /// Create a set of single period with value 1 387 /// date_time_period_set(period::period_type f)388 date_time_period_set(period::period_type f) 389 { 390 basic_[0]=date_time_period(f); 391 } 392 /// 393 /// Create a set of single period \a fl 394 /// date_time_period_set(date_time_period const & fl)395 date_time_period_set(date_time_period const &fl) 396 { 397 basic_[0]=fl; 398 } 399 /// 400 /// Append date_time_period \a f to the set 401 /// add(date_time_period f)402 void add(date_time_period f) 403 { 404 size_t n=size(); 405 if(n < 4) 406 basic_[n]=f; 407 else 408 periods_.push_back(f); 409 } 410 /// 411 /// Get number if items in list 412 /// size() const413 size_t size() const 414 { 415 if(basic_[0].type == period::period_type()) 416 return 0; 417 if(basic_[1].type == period::period_type()) 418 return 1; 419 if(basic_[2].type == period::period_type()) 420 return 2; 421 if(basic_[3].type == period::period_type()) 422 return 3; 423 return 4+periods_.size(); 424 } 425 /// 426 /// Get item at position \a n the set, n should be in range [0,size) 427 /// operator [](size_t n) const428 date_time_period const &operator[](size_t n) const 429 { 430 if(n >= size()) 431 throw std::out_of_range("Invalid index to date_time_period"); 432 if(n < 4) 433 return basic_[n]; 434 else 435 return periods_[n-4]; 436 } 437 private: 438 date_time_period basic_[4]; 439 std::vector<date_time_period> periods_; 440 }; 441 442 443 /// 444 /// Append two periods sets. Note this operator is not commutative 445 /// operator +(date_time_period_set const & a,date_time_period_set const & b)446 inline date_time_period_set operator+(date_time_period_set const &a,date_time_period_set const &b) 447 { 448 date_time_period_set s(a); 449 for(unsigned i=0;i<b.size();i++) 450 s.add(b[i]); 451 return s; 452 } 453 454 /// 455 /// Append two period sets when all periods of set \b change their sign 456 /// operator -(date_time_period_set const & a,date_time_period_set const & b)457 inline date_time_period_set operator-(date_time_period_set const &a,date_time_period_set const &b) 458 { 459 date_time_period_set s(a); 460 for(unsigned i=0;i<b.size();i++) 461 s.add(-b[i]); 462 return s; 463 } 464 465 466 /// 467 /// \brief this class provides an access to general calendar information. 468 /// 469 /// This information is not connected to specific date but generic to locale, and timezone. 470 /// It is used in obtaining general information about calendar and is essential for creation of 471 /// date_time objects. 472 /// 473 class BOOST_LOCALE_DECL calendar { 474 public: 475 476 /// 477 /// Create calendar taking locale and timezone information from ios_base instance. 478 /// 479 /// \note throws std::bad_cast if ios does not have a locale with installed \ref calendar_facet 480 /// facet installed 481 /// 482 calendar(std::ios_base &ios); 483 /// 484 /// Create calendar with locale \a l and time_zone \a zone 485 /// 486 /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed 487 /// 488 calendar(std::locale const &l,std::string const &zone); 489 /// 490 /// Create calendar with locale \a l and default timezone 491 /// 492 /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed 493 /// 494 calendar(std::locale const &l); 495 /// 496 /// Create calendar with default locale and timezone \a zone 497 /// 498 /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed 499 /// 500 calendar(std::string const &zone); 501 /// 502 /// Create calendar with default locale and timezone 503 /// 504 /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed 505 /// 506 calendar(); 507 ~calendar(); 508 509 /// 510 /// copy calendar 511 /// 512 calendar(calendar const &other); 513 /// 514 /// assign calendar 515 /// 516 calendar const &operator=(calendar const &other); 517 518 /// 519 /// Get minimum value for period f, For example for period::day it is 1. 520 /// 521 int minimum(period::period_type f) const; 522 /// 523 /// Get greatest possible minimum value for period f, For example for period::day it is 1, but may be different for other calendars. 524 /// 525 int greatest_minimum(period::period_type f) const; 526 /// 527 /// Get maximum value for period f, For example for Gregorian calendar's maximum period::day it is 31. 528 /// 529 int maximum(period::period_type f) const; 530 /// 531 /// Get least maximum value for period f, For example for Gregorian calendar's maximum period::day it is 28. 532 /// 533 int least_maximum(period::period_type f) const; 534 535 /// 536 /// Get first day of week for specific calendar, for example for US it is 1 - Sunday for France it is 2 - Monday 537 int first_day_of_week() const; 538 539 /// 540 /// get calendar's locale 541 /// 542 std::locale get_locale() const; 543 /// 544 /// get calendar's time zone 545 /// 546 std::string get_time_zone() const; 547 548 /// 549 /// Check if the calendar is Gregorian 550 /// 551 bool is_gregorian() const; 552 553 /// 554 /// Compare calendars for equivalence: i.e. calendar types, time zones etc. 555 /// 556 bool operator==(calendar const &other) const; 557 /// 558 /// Opposite of == 559 /// 560 bool operator!=(calendar const &other) const; 561 562 private: 563 friend class date_time; 564 std::locale locale_; 565 std::string tz_; 566 hold_ptr<abstract_calendar> impl_; 567 }; 568 569 /// 570 /// \brief this class represents a date time and allows to perform various operation according to the 571 /// locale settings. 572 /// 573 /// This class allows to manipulate various aspects of dates and times easily using arithmetic operations with 574 /// periods. 575 /// 576 /// General arithmetic functions: 577 /// 578 /// - date_time + date_time_period_set = date_time: move time point forward by specific periods like date_time + month; 579 /// - date_time - date_time_period_set = date_time: move time point backward by specific periods like date_time - month; 580 /// - date_time << date_time_period_set = date_time: roll time point forward by specific periods with rolling to begin if overflows: like "2010-01-31" << 2* day == "2010-01-02" instead of "2010-02-02" 581 /// - date_time >> date_time_period_set = date_time: roll time point backward by specific periods with rolling to end if overflows: like "2010-01-02" >> 2* day == "2010-01-31" instead of "2009-12-30" 582 /// - date_time / period_type = int - current period value: like "2010-12-21" / month == 12. "2010-12-21" / year = 2010 583 /// - (date_time - date_time) / period_type = int: distance between dates in period_type. Like ("2010-12-01" - "2008-12-01") / month = 24. 584 /// 585 /// You can also assign specific periods using assignment operator like: 586 /// some_time = year * 1995 that sets the year to 1995. 587 /// 588 /// 589 590 class BOOST_LOCALE_DECL date_time { 591 public: 592 593 /// 594 /// Dafault constructor, uses default calendar initialized date_time object to current time. 595 /// 596 /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed 597 /// 598 date_time(); 599 /// 600 /// copy date_time 601 /// 602 date_time(date_time const &other); 603 /// 604 /// copy date_time and change some fields according to the \a set 605 /// 606 date_time(date_time const &other,date_time_period_set const &set); 607 /// 608 /// assign the date_time 609 /// 610 date_time const &operator=(date_time const &other); 611 ~date_time(); 612 613 /// 614 /// Create a date_time object using POSIX time \a time and default calendar 615 /// 616 /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed 617 /// 618 date_time(double time); 619 /// 620 /// Create a date_time object using POSIX time \a time and calendar \a cal 621 /// 622 date_time(double time,calendar const &cal); 623 /// 624 /// Create a date_time object using calendar \a cal and initializes it to current time. 625 /// 626 date_time(calendar const &cal); 627 628 /// 629 /// Create a date_time object using default calendar and define values given in \a set 630 /// 631 /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed 632 /// 633 date_time(date_time_period_set const &set); 634 /// 635 /// Create a date_time object using calendar \a cal and define values given in \a set 636 /// 637 date_time(date_time_period_set const &set,calendar const &cal); 638 639 640 /// 641 /// assign values to various periods in set \a f 642 /// 643 date_time const &operator=(date_time_period_set const &f); 644 645 /// 646 /// set specific period \a f value to \a v 647 /// 648 void set(period::period_type f,int v); 649 /// 650 /// get specific period \a f value 651 /// 652 int get(period::period_type f) const; 653 654 /// 655 /// syntactic sugar for get(f) 656 /// operator /(period::period_type f) const657 int operator/(period::period_type f) const 658 { 659 return get(f); 660 } 661 662 /// 663 /// add single period f to the current date_time 664 /// operator +(period::period_type f) const665 date_time operator+(period::period_type f) const 666 { 667 return *this+date_time_period(f); 668 } 669 670 /// 671 /// subtract single period f from the current date_time 672 /// operator -(period::period_type f) const673 date_time operator-(period::period_type f) const 674 { 675 return *this-date_time_period(f); 676 } 677 678 /// 679 /// add single period f to the current date_time 680 /// operator +=(period::period_type f)681 date_time const &operator+=(period::period_type f) 682 { 683 return *this+=date_time_period(f); 684 } 685 /// 686 /// subtract single period f from the current date_time 687 /// operator -=(period::period_type f)688 date_time const &operator-=(period::period_type f) 689 { 690 return *this-=date_time_period(f); 691 } 692 693 /// 694 /// roll forward a date by single period f. 695 /// operator <<(period::period_type f) const696 date_time operator<<(period::period_type f) const 697 { 698 return *this<<date_time_period(f); 699 } 700 701 /// 702 /// roll backward a date by single period f. 703 /// operator >>(period::period_type f) const704 date_time operator>>(period::period_type f) const 705 { 706 return *this>>date_time_period(f); 707 } 708 709 /// 710 /// roll forward a date by single period f. 711 /// operator <<=(period::period_type f)712 date_time const &operator<<=(period::period_type f) 713 { 714 return *this<<=date_time_period(f); 715 } 716 /// 717 /// roll backward a date by single period f. 718 /// operator >>=(period::period_type f)719 date_time const &operator>>=(period::period_type f) 720 { 721 return *this>>=date_time_period(f); 722 } 723 724 /// 725 /// add date_time_period to the current date_time 726 /// 727 date_time operator+(date_time_period const &v) const; 728 /// 729 /// subtract date_time_period from the current date_time 730 /// 731 date_time operator-(date_time_period const &v) const; 732 /// 733 /// add date_time_period to the current date_time 734 /// 735 date_time const &operator+=(date_time_period const &v); 736 /// 737 /// subtract date_time_period from the current date_time 738 /// 739 date_time const &operator-=(date_time_period const &v); 740 741 /// 742 /// roll current date_time forward by date_time_period v 743 /// 744 date_time operator<<(date_time_period const &v) const; 745 /// 746 /// roll current date_time backward by date_time_period v 747 /// 748 date_time operator>>(date_time_period const &v) const ; 749 /// 750 /// roll current date_time forward by date_time_period v 751 /// 752 date_time const &operator<<=(date_time_period const &v); 753 /// 754 /// roll current date_time backward by date_time_period v 755 /// 756 date_time const &operator>>=(date_time_period const &v); 757 758 /// 759 /// add date_time_period_set v to the current date_time 760 /// 761 date_time operator+(date_time_period_set const &v) const; 762 /// 763 /// subtract date_time_period_set v from the current date_time 764 /// 765 date_time operator-(date_time_period_set const &v) const; 766 /// 767 /// add date_time_period_set v to the current date_time 768 /// 769 date_time const &operator+=(date_time_period_set const &v); 770 /// 771 /// subtract date_time_period_set v from the current date_time 772 /// 773 date_time const &operator-=(date_time_period_set const &v); 774 775 /// 776 /// roll current date_time forward by date_time_period_set v 777 /// 778 date_time operator<<(date_time_period_set const &v) const; 779 /// 780 /// roll current date_time backward by date_time_period_set v 781 /// 782 date_time operator>>(date_time_period_set const &v) const ; 783 /// 784 /// roll current date_time forward by date_time_period_set v 785 /// 786 date_time const &operator<<=(date_time_period_set const &v); 787 /// 788 /// roll current date_time backward by date_time_period_set v 789 /// 790 date_time const &operator>>=(date_time_period_set const &v); 791 792 /// 793 /// Get POSIX time 794 /// 795 /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds. 796 /// 797 double time() const; 798 /// 799 /// set POSIX time 800 /// 801 /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds. 802 /// This time can be fetched from Operating system clock using C function time, gettimeofday and others. 803 /// 804 void time(double v); 805 806 /// 807 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 808 /// 809 bool operator==(date_time const &other) const; 810 /// 811 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 812 /// 813 bool operator!=(date_time const &other) const; 814 /// 815 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 816 /// 817 bool operator<(date_time const &other) const; 818 /// 819 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 820 /// 821 bool operator>(date_time const &other) const; 822 /// 823 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 824 /// 825 bool operator<=(date_time const &other) const; 826 /// 827 /// compare date_time in the timeline (ignores difference in calendar, timezone etc) 828 /// 829 bool operator>=(date_time const &other) const; 830 831 /// 832 /// swaps two dates - efficient, does not throw 833 /// 834 void swap(date_time &other); 835 836 /// 837 /// calculate the distance from this date_time to \a other in terms of perios \a f 838 /// 839 int difference(date_time const &other,period::period_type f) const; 840 841 /// 842 /// Get minimal possible value for *this time point for a period \a f. 843 /// 844 int minimum(period::period_type f) const; 845 /// 846 /// Get minimal possible value for *this time point for a period \a f. For example 847 /// in February maximum(day) may be 28 or 29, in January maximum(day)==31 848 /// 849 int maximum(period::period_type f) const; 850 851 /// 852 /// Check if *this time point is in daylight saving time 853 /// 854 bool is_in_daylight_saving_time() const; 855 856 private: 857 hold_ptr<abstract_calendar> impl_; 858 }; 859 860 /// 861 /// Writes date_time \a t to output stream \a out. 862 /// 863 /// This function uses locale, calendar and time zone of the target stream \a in. 864 /// 865 /// For example: 866 /// \code 867 /// date_time now(time(0),hebrew_calendar) 868 /// cout << "Year: " << period::year(now) <<" Full Date:"<< now; 869 /// \endcode 870 /// 871 /// The output may be Year:5770 Full Date:Jan 1, 2010 872 /// 873 template<typename CharType> operator <<(std::basic_ostream<CharType> & out,date_time const & t)874 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,date_time const &t) 875 { 876 double time_point = t.time(); 877 uint64_t display_flags = ios_info::get(out).display_flags(); 878 if ( 879 display_flags == flags::date 880 || display_flags == flags::time 881 || display_flags == flags::datetime 882 || display_flags == flags::strftime 883 ) 884 { 885 out << time_point; 886 } 887 else { 888 ios_info::get(out).display_flags(flags::datetime); 889 out << time_point; 890 ios_info::get(out).display_flags(display_flags); 891 } 892 return out; 893 } 894 895 /// 896 /// Reads date_time \a t from output stream \a in 897 /// 898 /// This function uses locale, calendar and time zone of the source stream \a in. 899 /// 900 template<typename CharType> operator >>(std::basic_istream<CharType> & in,date_time & t)901 std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,date_time &t) 902 { 903 double v; 904 uint64_t display_flags = ios_info::get(in).display_flags(); 905 if ( 906 display_flags == flags::date 907 || display_flags == flags::time 908 || display_flags == flags::datetime 909 || display_flags == flags::strftime 910 ) 911 { 912 in >> v; 913 } 914 else { 915 ios_info::get(in).display_flags(flags::datetime); 916 in >> v; 917 ios_info::get(in).display_flags(display_flags); 918 } 919 if(!in.fail()) 920 t.time(v); 921 return in; 922 } 923 924 /// 925 /// \brief This class represents a period: a pair of two date_time objects. 926 /// 927 /// It is generally used as syntactic sugar to calculate difference between two dates. 928 /// 929 /// Note: it stores references to the original objects, so it is not recommended to be used 930 /// outside of the equation you calculate the difference in. 931 /// 932 class date_time_duration { 933 public: 934 935 /// 936 /// Create an object were \a first represents earlier point on time line and \a second is later 937 /// point. 938 /// date_time_duration(date_time const & first,date_time const & second)939 date_time_duration(date_time const &first,date_time const &second) : 940 s_(first), 941 e_(second) 942 { 943 } 944 945 /// 946 /// find a difference in terms of period_type \a f 947 /// get(period::period_type f) const948 int get(period::period_type f) const 949 { 950 return start().difference(end(),f); 951 } 952 953 /// 954 /// Syntactic sugar for get(f) 955 /// operator /(period::period_type f) const956 int operator / (period::period_type f) const 957 { 958 return start().difference(end(),f); 959 } 960 961 /// 962 /// Get starting point 963 /// start() const964 date_time const &start() const { return s_; } 965 /// 966 /// Get ending point 967 /// end() const968 date_time const &end() const { return e_; } 969 private: 970 date_time const &s_; 971 date_time const &e_; 972 }; 973 974 /// 975 /// Calculates the difference between two dates, the left operand is a later point on time line. 976 /// Returns date_time_duration object. 977 /// operator -(date_time const & later,date_time const & earlier)978 inline date_time_duration operator-(date_time const &later,date_time const &earlier) 979 { 980 return date_time_duration(earlier,later); 981 } 982 983 984 namespace period { 985 /// 986 /// Extract from date_time numerical value of Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] 987 /// era(date_time const & dt)988 inline int era(date_time const &dt) { return dt.get(era()); } 989 /// 990 /// Extract from date_time numerical value of Year, it is calendar specific, for example 2011 in Gregorian calendar. 991 /// year(date_time const & dt)992 inline int year(date_time const &dt) { return dt.get(year()); } 993 /// 994 /// Extract from date_time numerical value of Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. 995 /// extended_year(date_time const & dt)996 inline int extended_year(date_time const &dt) { return dt.get(extended_year()); } 997 /// 998 /// Extract from date_time numerical value of The month of year, calendar specific, in Gregorian [0..11] 999 /// month(date_time const & dt)1000 inline int month(date_time const &dt) { return dt.get(month()); } 1001 /// 1002 /// Extract from date_time numerical value of The day of month, calendar specific, in Gregorian [1..31] 1003 /// day(date_time const & dt)1004 inline int day(date_time const &dt) { return dt.get(day()); } 1005 /// 1006 /// Extract from date_time numerical value of The number of day in year, starting from 1, in Gregorian [1..366] 1007 /// day_of_year(date_time const & dt)1008 inline int day_of_year(date_time const &dt) { return dt.get(day_of_year()); } 1009 /// 1010 /// Extract from date_time numerical value of Day of week, Sunday=1, Monday=2,..., Saturday=7. 1011 /// 1012 /// Note that updating this value respects local day of week, so for example, 1013 /// If first day of week is Monday and the current day is Tuesday then setting 1014 /// the value to Sunday (1) would forward the date by 5 days forward and not backward 1015 /// by two days as it could be expected if the numbers were taken as is. 1016 /// day_of_week(date_time const & dt)1017 inline int day_of_week(date_time const &dt) { return dt.get(day_of_week()); } 1018 /// 1019 /// Extract from date_time numerical value of Original number of the day of the week in month. For example 1st Sunday, 1020 /// 2nd Sunday, etc. in Gregorian [1..5] 1021 /// day_of_week_in_month(date_time const & dt)1022 inline int day_of_week_in_month(date_time const &dt) { return dt.get(day_of_week_in_month()); } 1023 /// 1024 /// Extract from date_time numerical value of Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] 1025 /// day_of_week_local(date_time const & dt)1026 inline int day_of_week_local(date_time const &dt) { return dt.get(day_of_week_local()); } 1027 /// 1028 /// Extract from date_time numerical value of 24 clock hour [0..23] 1029 /// hour(date_time const & dt)1030 inline int hour(date_time const &dt) { return dt.get(hour()); } 1031 /// 1032 /// Extract from date_time numerical value of 12 clock hour [0..11] 1033 /// hour_12(date_time const & dt)1034 inline int hour_12(date_time const &dt) { return dt.get(hour_12()); } 1035 /// 1036 /// Extract from date_time numerical value of am or pm marker [0..1] 1037 /// am_pm(date_time const & dt)1038 inline int am_pm(date_time const &dt) { return dt.get(am_pm()); } 1039 /// 1040 /// Extract from date_time numerical value of minute [0..59] 1041 /// minute(date_time const & dt)1042 inline int minute(date_time const &dt) { return dt.get(minute()); } 1043 /// 1044 /// Extract from date_time numerical value of second [0..59] 1045 /// second(date_time const & dt)1046 inline int second(date_time const &dt) { return dt.get(second()); } 1047 /// 1048 /// Extract from date_time numerical value of The week number in the year 1049 /// week_of_year(date_time const & dt)1050 inline int week_of_year(date_time const &dt) { return dt.get(week_of_year()); } 1051 /// 1052 /// Extract from date_time numerical value of The week number within current month 1053 /// week_of_month(date_time const & dt)1054 inline int week_of_month(date_time const &dt) { return dt.get(week_of_month()); } 1055 /// 1056 /// Extract from date_time numerical value of First day of week, constant, for example Sunday in US = 1, Monday in France = 2 1057 /// first_day_of_week(date_time const & dt)1058 inline int first_day_of_week(date_time const &dt) { return dt.get(first_day_of_week()); } 1059 1060 /// 1061 /// Extract from date_time_duration numerical value of duration in Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] 1062 /// era(date_time_duration const & dt)1063 inline int era(date_time_duration const &dt) { return dt.get(era()); } 1064 /// 1065 /// Extract from date_time_duration numerical value of duration in years 1066 /// year(date_time_duration const & dt)1067 inline int year(date_time_duration const &dt) { return dt.get(year()); } 1068 /// 1069 /// Extract from date_time_duration numerical value of duration in extended years (for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1). 1070 /// extended_year(date_time_duration const & dt)1071 inline int extended_year(date_time_duration const &dt) { return dt.get(extended_year()); } 1072 /// 1073 /// Extract from date_time_duration numerical value of duration in months 1074 /// month(date_time_duration const & dt)1075 inline int month(date_time_duration const &dt) { return dt.get(month()); } 1076 /// 1077 /// Extract from date_time_duration numerical value of duration in days of month 1078 /// day(date_time_duration const & dt)1079 inline int day(date_time_duration const &dt) { return dt.get(day()); } 1080 /// 1081 /// Extract from date_time_duration numerical value of duration in days of year 1082 /// day_of_year(date_time_duration const & dt)1083 inline int day_of_year(date_time_duration const &dt) { return dt.get(day_of_year()); } 1084 /// 1085 /// Extract from date_time_duration numerical value of duration in days of week 1086 /// day_of_week(date_time_duration const & dt)1087 inline int day_of_week(date_time_duration const &dt) { return dt.get(day_of_week()); } 1088 /// 1089 /// Extract from date_time_duration numerical value of duration in original number of the day of the week in month 1090 /// day_of_week_in_month(date_time_duration const & dt)1091 inline int day_of_week_in_month(date_time_duration const &dt) { return dt.get(day_of_week_in_month()); } 1092 /// 1093 /// Extract from date_time_duration numerical value of duration in local day of week 1094 /// day_of_week_local(date_time_duration const & dt)1095 inline int day_of_week_local(date_time_duration const &dt) { return dt.get(day_of_week_local()); } 1096 /// 1097 /// Extract from date_time_duration numerical value of duration in hours 1098 /// hour(date_time_duration const & dt)1099 inline int hour(date_time_duration const &dt) { return dt.get(hour()); } 1100 /// 1101 /// Extract from date_time_duration numerical value of duration in 12 clock hours 1102 /// hour_12(date_time_duration const & dt)1103 inline int hour_12(date_time_duration const &dt) { return dt.get(hour_12()); } 1104 /// 1105 /// Extract from date_time_duration numerical value of duration in am or pm markers 1106 /// am_pm(date_time_duration const & dt)1107 inline int am_pm(date_time_duration const &dt) { return dt.get(am_pm()); } 1108 /// 1109 /// Extract from date_time_duration numerical value of duration in minutes 1110 /// minute(date_time_duration const & dt)1111 inline int minute(date_time_duration const &dt) { return dt.get(minute()); } 1112 /// 1113 /// Extract from date_time_duration numerical value of duration in seconds 1114 /// second(date_time_duration const & dt)1115 inline int second(date_time_duration const &dt) { return dt.get(second()); } 1116 /// 1117 /// Extract from date_time_duration numerical value of duration in the week number in the year 1118 /// week_of_year(date_time_duration const & dt)1119 inline int week_of_year(date_time_duration const &dt) { return dt.get(week_of_year()); } 1120 /// 1121 /// Extract from date_time_duration numerical value of duration in The week number within current month 1122 /// week_of_month(date_time_duration const & dt)1123 inline int week_of_month(date_time_duration const &dt) { return dt.get(week_of_month()); } 1124 /// 1125 /// Extract from date_time_duration numerical value of duration in the first day of week 1126 /// first_day_of_week(date_time_duration const & dt)1127 inline int first_day_of_week(date_time_duration const &dt) { return dt.get(first_day_of_week()); } 1128 1129 1130 } 1131 1132 /// @} 1133 1134 1135 } // locale 1136 } // boost 1137 1138 #ifdef BOOST_MSVC 1139 #pragma warning(pop) 1140 #endif 1141 1142 1143 #endif 1144 /// 1145 /// \example calendar.cpp 1146 /// 1147 /// Example of using date_time functions for generating calendar for current year. 1148 /// 1149 1150 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 1151