123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- //
- // 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.
- */
|