]>
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 | #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 | /// | |
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 | /// | |
63 | date_time_period operator+() const { return *this; } | |
64 | /// | |
65 | /// Operator -, switches the sign of period | |
66 | /// | |
67 | 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 | /// | |
72 | 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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
125 | inline period_type hour(){ return period_type(marks::hour); } | |
126 | /// | |
127 | /// Get period_type for: 12 clock hour [0..11] | |
128 | /// | |
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 | /// | |
133 | inline period_type am_pm(){ return period_type(marks::am_pm); } | |
134 | /// | |
135 | /// Get period_type for: minute [0..59] | |
136 | /// | |
137 | inline period_type minute(){ return period_type(marks::minute); } | |
138 | /// | |
139 | /// Get period_type for: second [0..59] | |
140 | /// | |
141 | inline period_type second(){ return period_type(marks::second); } | |
142 | /// | |
143 | /// Get period_type for: The week number in the year | |
144 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
233 | inline date_time_period january() { return date_time_period(month(),0); } | |
234 | /// | |
235 | /// Get predefined constant for February | |
236 | /// | |
237 | inline date_time_period february() { return date_time_period(month(),1); } | |
238 | /// | |
239 | /// Get predefined constant for March | |
240 | /// | |
241 | inline date_time_period march() { return date_time_period(month(),2); } | |
242 | /// | |
243 | /// Get predefined constant for April | |
244 | /// | |
245 | inline date_time_period april() { return date_time_period(month(),3); } | |
246 | /// | |
247 | /// Get predefined constant for May | |
248 | /// | |
249 | inline date_time_period may() { return date_time_period(month(),4); } | |
250 | /// | |
251 | /// Get predefined constant for June | |
252 | /// | |
253 | inline date_time_period june() { return date_time_period(month(),5); } | |
254 | /// | |
255 | /// Get predefined constant for July | |
256 | /// | |
257 | inline date_time_period july() { return date_time_period(month(),6); } | |
258 | /// | |
259 | /// Get predefined constant for August | |
260 | /// | |
261 | inline date_time_period august() { return date_time_period(month(),7); } | |
262 | /// | |
263 | /// Get predefined constant for September | |
264 | /// | |
265 | inline date_time_period september() { return date_time_period(month(),8); } | |
266 | /// | |
267 | /// Get predefined constant for October | |
268 | /// | |
269 | inline date_time_period october() { return date_time_period(month(),9); } | |
270 | /// | |
271 | /// Get predefined constant for November | |
272 | /// | |
273 | inline date_time_period november() { return date_time_period(month(),10); } | |
274 | /// | |
275 | /// Get predefined constant for December | |
276 | /// | |
277 | inline date_time_period december() { return date_time_period(month(),11); } | |
278 | ||
279 | /// | |
280 | /// Get predefined constant for Sunday | |
281 | /// | |
282 | inline date_time_period sunday() { return date_time_period(day_of_week(),1); } | |
283 | /// | |
284 | /// Get predefined constant for Monday | |
285 | /// | |
286 | inline date_time_period monday() { return date_time_period(day_of_week(),2); } | |
287 | /// | |
288 | /// Get predefined constant for Tuesday | |
289 | /// | |
290 | inline date_time_period tuesday() { return date_time_period(day_of_week(),3); } | |
291 | /// | |
292 | /// Get predefined constant for Wednesday | |
293 | /// | |
294 | inline date_time_period wednesday() { return date_time_period(day_of_week(),4); } | |
295 | /// | |
296 | /// Get predefined constant for Thursday | |
297 | /// | |
298 | inline date_time_period thursday() { return date_time_period(day_of_week(),5); } | |
299 | /// | |
300 | /// Get predefined constant for Friday | |
301 | /// | |
302 | inline date_time_period friday() { return date_time_period(day_of_week(),6); } | |
303 | /// | |
304 | /// Get predefined constant for Saturday | |
305 | /// | |
306 | inline date_time_period saturday() { return date_time_period(day_of_week(),7); } | |
307 | /// | |
308 | /// Get predefined constant for AM (Ante Meridiem) | |
309 | /// | |
310 | inline date_time_period am() { return date_time_period(am_pm(),0); } | |
311 | /// | |
312 | /// Get predefined constant for PM (Post Meridiem) | |
313 | /// | |
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 | /// | |
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 | /// | |
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> | |
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> | |
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> | |
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> | |
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 | /// | |
382 | date_time_period_set() | |
383 | { | |
384 | } | |
385 | /// | |
386 | /// Create a set of single period with value 1 | |
387 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
413 | 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 | /// | |
428 | 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 | /// | |
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 | /// | |
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 | /// | |
657 | 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 | /// | |
665 | 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 | /// | |
673 | 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 | /// | |
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 | /// | |
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 | /// | |
696 | 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 | /// | |
704 | 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 | /// | |
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 | /// | |
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> | |
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> | |
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 | /// | |
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 | /// | |
948 | int get(period::period_type f) const | |
949 | { | |
950 | return start().difference(end(),f); | |
951 | } | |
952 | ||
953 | /// | |
954 | /// Syntactic sugar for get(f) | |
955 | /// | |
956 | int operator / (period::period_type f) const | |
957 | { | |
958 | return start().difference(end(),f); | |
959 | } | |
960 | ||
961 | /// | |
962 | /// Get starting point | |
963 | /// | |
964 | date_time const &start() const { return s_; } | |
965 | /// | |
966 | /// Get ending point | |
967 | /// | |
968 | 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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 | /// | |
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 |