| // |
| // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 filetype=cpp.doxygen |
| /*! |
| \page dates_times_timezones Working with dates, times, timezones and calendars. |
| |
| \section dates_times_timezones_intro Introduction |
| |
| There are several important flaws in the standard C, C++ and Boost libraries that handle dates and time: |
| |
| -# The biggest flaw of most libraries that provide operations over dates is the fact that they only support |
| the Gregorian calendar. \c boost::date_time , \c std::tm , and standard functions like \c localtime and \c gmtime, |
| all assume the Gregorian calendar. |
| -# The information about local start of week is not provided. |
| \n |
| For example the standard C and C++ library has \c mktime and \c localtime, but they do not give |
| user the information about the first day of week. This information is locale dependent. |
| It is Monday in France and it is Sunday in United States. |
| |
| Boost.Locale provides generic \ref boost::locale::date_time "date_time", and \ref boost::locale::calendar "calendar" classes |
| that allow you to perform operations on dates and times for non-Gregorian calendars such as Hebrew, Islamic, Japanese and others. |
| |
| \ref using_localization_backends "Non-ICU based backends" support the Gregorian calendar only. |
| Unlike \c boost::date_time, they are fully aware of the local first day of week. Thus, |
| if the current day of week is Monday, then setting "current day of week" to Sunday would move the actual date 6 days |
| forward in Russian or French locales and move one day backward in USA and Israeli locales. |
| |
| \section dates_times_timezones_dt Handling Dates and Time |
| |
| - \ref boost::locale::calendar -- represents generic information about the calendar, independent from a specific time point. For example, you can get the maximum number of days in a month for a specific calendar. |
| - \ref boost::locale::date_time -- represents a time point. It is constructed from a calendar and allows manipulation of various time periods. |
| - \ref boost::locale::period -- holds a list of functions that represent various periods, such as month, year, day, and hour, allowing |
| manipulation of dates and times. You can add periods, multiply them by integers, get or set them, or add them to |
| \ref boost::locale::date_time "date_time" objects. |
| |
| |
| For example: |
| |
| \code |
| using namespace boost::locale; |
| date_time now; // Create date_time class with default calendar initialized to current time |
| date_time tomorrow = now + period::day(); |
| cout << "Let's meet tomorrow at " << as::date << tomorrow << endl; |
| date_time some_point = period::year(1995) + period::january() + period::day(1); |
| // Set some_point's date to 1995-Jan-1. |
| cout << "The "<< as::date << some_point << " is the " |
| << as::ordinal << some_point / period::day_of_week_local() << " day of the week" << endl; |
| \endcode |
| |
| You can calculate the difference between dates by dividing the difference by a period: |
| |
| \code |
| date_time now; |
| cout << " There are " << (now + 2 * period::month() - now) / period::day() << " days " |
| "between " << as::date << now << " and " << now + 2*period::month() << endl; |
| \endcode |
| |
| You can also use different syntax (less operator overloading) |
| |
| \code |
| date_time now; |
| cout << " There are " << period::day(now + period::month(2) - now) << " days " |
| "between " << as::date << now << " and " << now + period::month(2) << endl; |
| \endcode |
| |
| |
| |
| \ref boost::locale::date_time "date_time" -- provides the member functions \ref boost::locale::date_time::minimum() "minimum" and |
| \ref boost::locale::date_time::maximum() "maximum" to get the information about smallest and largest |
| possible values of a certain period for a specific time. |
| |
| For example, for February the <tt>maximum(period::day())</tt> would be 28 (or 29 for a leap year), and for January it would be 31. |
| |
| \note Be very careful with assumptions about calendars. For example, in the Hebrew calendar, the |
| number of months is different for leap years and non-leap years. |
| |
| We recommend you to look at the \c calendar.cpp example provided with this library to get an understanding of how |
| to manipulate dates and times using these classes. |
| |
| To convert between various calendar dates, you may get the current POSIX time via the |
| \ref boost::locale::date_time::time "time" member function. |
| |
| For example: |
| |
| \code |
| using namespace boost::locale; |
| using namespace boost::locale::period; |
| generator gen; |
| // Create locales with Hebrew and Gregorian (default) calendars. |
| std::locale l_hebrew=gen("en_US.UTF-8@calendar=hebrew"); |
| std::locale l_gregorian=gen("en_US.UTF-8"); |
| |
| // Create a Gregorian date from fields |
| date_time greg(year(2010) + february() + day(5),l_gregorian); |
| // Assign a time point taken from the Gregorian date to date_time with |
| // the Hebrew calendar |
| date_time heb(greg.time(),l_hebrew); |
| // Now we can query the year. |
| std::cout << "Hebrew year is " << heb / year << std::endl; |
| \endcode |
| |
| \note |
| |
| Non-ICU based backends support the same date-time range as \c mktime and \c localtime C library functions. |
| |
| - Unix 32 bit: dates between 1901 and 2038 |
| - Unix 64 bit: dates from 1 BC |
| - Windows: dates from 1970. If the \c time_t is 32 bits wide (mingw), then the upper limit is year 2038 |
| |
| \section dates_times_timezones_tz Time Zone |
| |
| The current operating system's time zone is used by default, however the time zone can be modified at |
| several different levels: |
| |
| -# Calendar level: you can specify a timezone when creating a new instance of \ref boost::locale::calendar |
| in its constructor. |
| -# iostream level: you can use \ref boost::locale::as::time_zone "as::time_zone" manipulator to set a specific |
| time zone to the iostream so all dates and times would be represented in this time zone |
| -# You can specify the default global time zone by calling: \ref boost::locale::time_zone::global(std::string const &). |
| This time zone would be the default one for newly created iostream object and calendar instances. |
| |
| \note |
| |
| \ref using_localization_backends "Non-ICU based backends" support only two kinds of time zones: |
| |
| -# The current OS time zone, as it is handled by \c localtime and \c mktime the standard |
| library functions - the default time zone |
| -# Simple time zone in format "GMT+HH:MM" - the time zone represented using fixed shift from |
| the UTC without support of daylight saving time. |
| |
| |
| \section dates_times_timezones_io I/O Operations on date_time objects |
| |
| Writing a \ref boost::locale::date_time "date_time" is equivalent |
| to: |
| |
| - Applying \ref boost::locale::as::datetime "as::datetime" manipulator on the stream |
| - Writing POSIX time as number that is fetched by calling \ref boost::locale::date_time::time() |
| "date_time::time()" function. |
| - Reverting the manipulator effect back. |
| |
| For example this code: |
| |
| \code |
| using namespace boost::locale; |
| date_time now; |
| std::cout << now << std::endl; |
| \endcode |
| |
| Would print in the default format, something like: |
| |
| \verbatim |
| 2/3/2011 12:00 am |
| \endverbatim |
| |
| However if you need to change the default behavior (for example show only date), |
| then you need to use specific iostream manipulator in order to display current date or time, |
| it would override the default formatting. |
| |
| For example |
| |
| \code |
| using namespace boost::locale; |
| date_time now; |
| std::cout << as::date << now << std::endl; |
| \endcode |
| |
| Would print something like: |
| |
| \verbatim |
| 2/3/2011 |
| \endverbatim |
| |
| This is important to remember that \c date_time object is always rendered and parsed in the context |
| of the \c iostream's locale and time zone and not in the context of specific \c date_time object. |
| |
| \section dates_times_timezones_qna Questions and Answers |
| |
| |
| <b>Why should I use Boost.Locale over Boost.DateTime when I need Gregorian calendar only?</b> |
| |
| - Boost.DateTime is locale agnostic library and ignores the fact that the first day of week |
| varies by the locale. |
| - Boost.Locale provides a unified access to date and time in time zone aware way. |
| It represents a time as universal scalar - the POSIX time and over that builds dates, |
| local times and time-zones handling. |
| \n |
| For example, <tt>date_time(some_time.time() + 3600)</tt> may be not equal to |
| <tt>some_time + hour()</tt>, because of the daylight savings time. |
| |
| <b>Why don't you use Boost.DateTime time zone support?</b> |
| |
| Boost.DateTime's time zone support is broken. Time zones can not be represented with |
| a simple table of rules where daylight saving depend only on certain n'th day of week in month. |
| The daylight savings time may vary by year, political issues and many other things. |
| |
| Most of the modern operating systems (Linux, *BSD, Mac OS X, OpenVMS) and many important software packages |
| (ICU, Java, Python) use so called Olson database in order to handle daylight saving time |
| correctly. |
| |
| If you need full time zone database support, then you should use ICU library. |
| |
| */ |
| |
| |