]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
9 | // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 filetype=cpp.doxygen | |
10 | /*! | |
11 | \page dates_times_timezones Working with dates, times, timezones and calendars. | |
12 | ||
13 | \section dates_times_timezones_intro Introduction | |
14 | ||
15 | There are several important flaws in the standard C, C++ and Boost libraries that handle dates and time: | |
16 | ||
17 | -# The biggest flaw of most libraries that provide operations over dates is the fact that they only support | |
18 | the Gregorian calendar. \c boost::date_time , \c std::tm , and standard functions like \c localtime and \c gmtime, | |
19 | all assume the Gregorian calendar. | |
20 | -# The information about local start of week is not provided. | |
21 | \n | |
22 | For example the standard C and C++ library has \c mktime and \c localtime, but they do not give | |
23 | user the information about the first day of week. This information is locale dependent. | |
24 | It is Monday in France and it is Sunday in United States. | |
25 | ||
26 | Boost.Locale provides generic \ref boost::locale::date_time "date_time", and \ref boost::locale::calendar "calendar" classes | |
27 | that allow you to perform operations on dates and times for non-Gregorian calendars such as Hebrew, Islamic, Japanese and others. | |
28 | ||
29 | \ref using_localization_backends "Non-ICU based backends" support the Gregorian calendar only. | |
30 | Unlike \c boost::date_time, they are fully aware of the local first day of week. Thus, | |
31 | if the current day of week is Monday, then setting "current day of week" to Sunday would move the actual date 6 days | |
32 | forward in Russian or French locales and move one day backward in USA and Israeli locales. | |
33 | ||
34 | \section dates_times_timezones_dt Handling Dates and Time | |
35 | ||
36 | - \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. | |
37 | - \ref boost::locale::date_time -- represents a time point. It is constructed from a calendar and allows manipulation of various time periods. | |
38 | - \ref boost::locale::period -- holds a list of functions that represent various periods, such as month, year, day, and hour, allowing | |
39 | manipulation of dates and times. You can add periods, multiply them by integers, get or set them, or add them to | |
40 | \ref boost::locale::date_time "date_time" objects. | |
41 | ||
42 | ||
43 | For example: | |
44 | ||
45 | \code | |
46 | using namespace boost::locale; | |
47 | date_time now; // Create date_time class with default calendar initialized to current time | |
48 | date_time tomorrow = now + period::day(); | |
49 | cout << "Let's meet tomorrow at " << as::date << tomorrow << endl; | |
50 | date_time some_point = period::year(1995) + period::january() + period::day(1); | |
51 | // Set some_point's date to 1995-Jan-1. | |
52 | cout << "The "<< as::date << some_point << " is the " | |
53 | << as::ordinal << some_point / period::day_of_week_local() << " day of the week" << endl; | |
54 | \endcode | |
55 | ||
56 | You can calculate the difference between dates by dividing the difference by a period: | |
57 | ||
58 | \code | |
59 | date_time now; | |
60 | cout << " There are " << (now + 2 * period::month() - now) / period::day() << " days " | |
61 | "between " << as::date << now << " and " << now + 2*period::month() << endl; | |
62 | \endcode | |
63 | ||
64 | You can also use different syntax (less operator overloading) | |
65 | ||
66 | \code | |
67 | date_time now; | |
68 | cout << " There are " << period::day(now + period::month(2) - now) << " days " | |
69 | "between " << as::date << now << " and " << now + period::month(2) << endl; | |
70 | \endcode | |
71 | ||
72 | ||
73 | ||
74 | \ref boost::locale::date_time "date_time" -- provides the member functions \ref boost::locale::date_time::minimum() "minimum" and | |
75 | \ref boost::locale::date_time::maximum() "maximum" to get the information about smallest and largest | |
76 | possible values of a certain period for a specific time. | |
77 | ||
78 | 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. | |
79 | ||
80 | \note Be very careful with assumptions about calendars. For example, in the Hebrew calendar, the | |
81 | number of months is different for leap years and non-leap years. | |
82 | ||
83 | We recommend you to look at the \c calendar.cpp example provided with this library to get an understanding of how | |
84 | to manipulate dates and times using these classes. | |
85 | ||
86 | To convert between various calendar dates, you may get the current POSIX time via the | |
87 | \ref boost::locale::date_time::time "time" member function. | |
88 | ||
89 | For example: | |
90 | ||
91 | \code | |
92 | using namespace boost::locale; | |
93 | using namespace boost::locale::period; | |
94 | generator gen; | |
95 | // Create locales with Hebrew and Gregorian (default) calendars. | |
96 | std::locale l_hebrew=gen("en_US.UTF-8@calendar=hebrew"); | |
97 | std::locale l_gregorian=gen("en_US.UTF-8"); | |
98 | ||
99 | // Create a Gregorian date from fields | |
100 | date_time greg(year(2010) + february() + day(5),l_gregorian); | |
101 | // Assign a time point taken from the Gregorian date to date_time with | |
102 | // the Hebrew calendar | |
103 | date_time heb(greg.time(),l_hebrew); | |
104 | // Now we can query the year. | |
105 | std::cout << "Hebrew year is " << heb / year << std::endl; | |
106 | \endcode | |
107 | ||
108 | \note | |
109 | ||
110 | Non-ICU based backends support the same date-time range as \c mktime and \c localtime C library functions. | |
111 | ||
112 | - Unix 32 bit: dates between 1901 and 2038 | |
113 | - Unix 64 bit: dates from 1 BC | |
114 | - Windows: dates from 1970. If the \c time_t is 32 bits wide (mingw), then the upper limit is year 2038 | |
115 | ||
116 | \section dates_times_timezones_tz Time Zone | |
117 | ||
118 | The current operating system's time zone is used by default, however the time zone can be modified at | |
119 | several different levels: | |
120 | ||
121 | -# Calendar level: you can specify a timezone when creating a new instance of \ref boost::locale::calendar | |
122 | in its constructor. | |
123 | -# iostream level: you can use \ref boost::locale::as::time_zone "as::time_zone" manipulator to set a specific | |
124 | time zone to the iostream so all dates and times would be represented in this time zone | |
125 | -# You can specify the default global time zone by calling: \ref boost::locale::time_zone::global(std::string const &). | |
126 | This time zone would be the default one for newly created iostream object and calendar instances. | |
127 | ||
128 | \note | |
129 | ||
130 | \ref using_localization_backends "Non-ICU based backends" support only two kinds of time zones: | |
131 | ||
132 | -# The current OS time zone, as it is handled by \c localtime and \c mktime the standard | |
133 | library functions - the default time zone | |
134 | -# Simple time zone in format "GMT+HH:MM" - the time zone represented using fixed shift from | |
135 | the UTC without support of daylight saving time. | |
136 | ||
137 | ||
138 | \section dates_times_timezones_io I/O Operations on date_time objects | |
139 | ||
140 | Writing a \ref boost::locale::date_time "date_time" is equivalent | |
141 | to: | |
142 | ||
143 | - Applying \ref boost::locale::as::datetime "as::datetime" manipulator on the stream | |
144 | - Writing POSIX time as number that is fetched by calling \ref boost::locale::date_time::time() | |
145 | "date_time::time()" function. | |
146 | - Reverting the manipulator effect back. | |
147 | ||
148 | For example this code: | |
149 | ||
150 | \code | |
151 | using namespace boost::locale; | |
152 | date_time now; | |
153 | std::cout << now << std::endl; | |
154 | \endcode | |
155 | ||
156 | Would print in the default format, something like: | |
157 | ||
158 | \verbatim | |
159 | 2/3/2011 12:00 am | |
160 | \endverbatim | |
161 | ||
162 | However if you need to change the default behavior (for example show only date), | |
163 | then you need to use specific iostream manipulator in order to display current date or time, | |
164 | it would override the default formatting. | |
165 | ||
166 | For example | |
167 | ||
168 | \code | |
169 | using namespace boost::locale; | |
170 | date_time now; | |
171 | std::cout << as::date << now << std::endl; | |
172 | \endcode | |
173 | ||
174 | Would print something like: | |
175 | ||
176 | \verbatim | |
177 | 2/3/2011 | |
178 | \endverbatim | |
179 | ||
180 | This is important to remember that \c date_time object is always rendered and parsed in the context | |
181 | of the \c iostream's locale and time zone and not in the context of specific \c date_time object. | |
182 | ||
183 | \section dates_times_timezones_qna Questions and Answers | |
184 | ||
185 | ||
186 | <b>Why should I use Boost.Locale over Boost.DateTime when I need Gregorian calendar only?</b> | |
187 | ||
188 | - Boost.DateTime is locale agnostic library and ignores the fact that the first day of week | |
189 | varies by the locale. | |
190 | - Boost.Locale provides a unified access to date and time in time zone aware way. | |
191 | It represents a time as universal scalar - the POSIX time and over that builds dates, | |
192 | local times and time-zones handling. | |
193 | \n | |
194 | For example, <tt>date_time(some_time.time() + 3600)</tt> may be not equal to | |
195 | <tt>some_time + hour()</tt>, because of the daylight savings time. | |
196 | ||
197 | <b>Why don't you use Boost.DateTime time zone support?</b> | |
198 | ||
199 | Boost.DateTime's time zone support is broken. Time zones can not be represented with | |
200 | a simple table of rules where daylight saving depend only on certain n'th day of week in month. | |
201 | The daylight savings time may vary by year, political issues and many other things. | |
202 | ||
203 | Most of the modern operating systems (Linux, *BSD, Mac OS X, OpenVMS) and many important software packages | |
204 | (ICU, Java, Python) use so called Olson database in order to handle daylight saving time | |
205 | correctly. | |
206 | ||
207 | If you need full time zone database support, then you should use ICU library. | |
208 | ||
209 | */ | |
210 | ||
211 |