802f5d031d
- Fixed issues with inspector - Changed the use of boost::mutex - not include entire boost.thread - Updated documentation build script [SVN r73059]
212 lines
8.9 KiB
Plaintext
212 lines
8.9 KiB
Plaintext
//
|
|
// 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.
|
|
|
|
*/
|
|
|
|
|