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_FACET_HPP_INCLUDED
9 #define BOOST_LOCALE_DATE_TIME_FACET_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/cstdint.hpp>
18 #include <locale>
19 
20 namespace boost {
21     namespace locale {
22         ///
23         /// \brief Namespace that contains various types for manipulation with dates
24         ///
25         namespace period {
26             ///
27             /// \brief This namespace holds a enum of various period types like era, year, month, etc..
28             ///
29             namespace marks {
30                 /// \brief the type that defines a flag that holds a period identifier
31                 enum period_mark {
32                     invalid,                    ///< Special invalid value, should not be used directly
33                     era,                        ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
34                     year,                       ///< Year, it is calendar specific, for example 2011 in Gregorian calendar.
35                     extended_year,              ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
36                     month,                      ///< The month of year, calendar specific, in Gregorian [0..11]
37                     day,                        ///< The day of month, calendar specific, in Gregorian [1..31]
38                     day_of_year,                ///< The number of day in year, starting from 1, in Gregorian  [1..366]
39                     day_of_week,                ///< Day of week, Sunday=1, Monday=2,..., Saturday=7.
40                                                 ///< Note that updating this value respects local day of week, so for example,
41                                                 ///< If first day of week is Monday and the current day is Tuesday then setting
42                                                 ///< the value to Sunday (1) would forward the date by 5 days forward and not backward
43                                                 ///< by two days as it could be expected if the numbers were taken as is.
44                     day_of_week_in_month,       ///< Original number of the day of the week in month. For example 1st Sunday,
45                                                 ///< 2nd Sunday, etc. in Gregorian [1..5]
46                     day_of_week_local,          ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
47                     hour,                       ///< 24 clock hour [0..23]
48                     hour_12,                    ///< 12 clock hour [0..11]
49                     am_pm,                      ///< am or pm marker [0..1]
50                     minute,                     ///< minute [0..59]
51                     second,                     ///< second [0..59]
52                     week_of_year,               ///< The week number in the year
53                     week_of_month,              ///< The week number within current month
54                     first_day_of_week,          ///< First day of week, constant, for example Sunday in US = 1, Monday in France = 2
55                 };
56 
57             } // marks
58 
59             ///
60             /// \brief This class holds a type that represents certain period of time like
61             /// year, hour, second and so on.
62             ///
63             /// It can be created from either marks::period_mark type or by using shortcuts in period
64             /// namespace - calling functions like period::year(), period::hour() and so on.
65             ///
66             /// Basically it represents the same object as enum marks::period_mark but allows to
67             /// provide save operator overloading that would not collide with casing of enum to
68             /// numeric values.
69             ///
70             class period_type {
71             public:
72                 ///
73                 /// Create a period of specific type, default is invalid.
74                 ///
period_type(marks::period_mark m=marks::invalid)75                 period_type(marks::period_mark m = marks::invalid) : mark_(m)
76                 {
77                 }
78 
79                 ///
80                 /// Get the value of marks::period_mark it was created with.
81                 ///
mark() const82                 marks::period_mark mark() const
83                 {
84                     return mark_;
85                 }
86 
87                 ///
88                 /// Check if two periods are the same
89                 ///
operator ==(period_type const & other) const90                 bool operator==(period_type const &other) const
91                 {
92                     return mark()==other.mark();
93                 }
94                 ///
95                 /// Check if two periods are different
96                 ///
operator !=(period_type const & other) const97                 bool operator!=(period_type const &other) const
98                 {
99                     return mark()!=other.mark();
100                 }
101             private:
102                 marks::period_mark mark_;
103             };
104 
105         } // namespace period
106 
107         ///
108         /// Structure that define POSIX time, seconds and milliseconds
109         /// since Jan 1, 1970, 00:00 not including leap seconds.
110         ///
111         struct posix_time {
112             int64_t seconds; ///< Seconds since epoch
113             uint32_t nanoseconds;  ///< Nanoseconds resolution
114         };
115 
116         ///
117         /// This class defines generic calendar class, it is used by date_time and calendar
118         /// objects internally. It is less useful for end users, but it is build for localization
119         /// backend implementation
120         ///
121 
122         class abstract_calendar {
123         public:
124 
125             ///
126             /// Type that defines how to fetch the value
127             ///
128             typedef enum {
129                 absolute_minimum,   ///< Absolute possible minimum for the value, for example for day is 1
130                 actual_minimum,     ///< Actual minimal value for this period.
131                 greatest_minimum,   ///< Maximal minimum value that can be for this period
132                 current,            ///< Current value of this period
133                 least_maximum,      ///< The last maximal value for this period, For example for Gregorian calendar
134                                     ///< day it is 28
135                 actual_maximum,     ///< Actual maximum, for it can be 28, 29, 30, 31 for day according to current month
136                 absolute_maximum,   ///< Maximal value, for Gregorian day it would be 31.
137             } value_type;
138 
139             ///
140             /// A way to update the value
141             ///
142             typedef enum {
143                 move,   ///< Change the value up or down effecting others for example 1990-12-31 + 1 day = 1991-01-01
144                 roll,   ///< Change the value up or down not effecting others for example 1990-12-31 + 1 day = 1990-12-01
145             } update_type;
146 
147             ///
148             /// Information about calendar
149             ///
150             typedef enum {
151                 is_gregorian,   ///< Check if the calendar is Gregorian
152                 is_dst          ///< Check if the current time is in daylight time savings
153             } calendar_option_type;
154 
155             ///
156             /// Make a polymorphic copy of the calendar
157             ///
158             virtual abstract_calendar *clone() const = 0;
159 
160             ///
161             /// Set specific \a value for period \a p, note not all values are settable.
162             ///
163             /// After call of set_value you may want to call normalize() function to make sure
164             /// vall periods are updated, if you set sereral fields that are part of single
165             /// date/time representation you should call set_value several times and then
166             /// call normalize().
167             ///
168             /// If normalize() is not called after set_value, the behavior is undefined
169             ///
170             virtual void set_value(period::marks::period_mark p,int value) = 0;
171 
172             ///
173             /// Recalculate all periods after setting them, should be called after use of set_value() function.
174             ///
175             virtual void normalize() = 0;
176 
177             ///
178             /// Get specific value for period \a p according to a value_type \a v
179             ///
180             virtual int get_value(period::marks::period_mark p,value_type v) const = 0;
181 
182             ///
183             /// Set current time point
184             ///
185             virtual void set_time(posix_time const &p)  = 0;
186             ///
187             /// Get current time point
188             ///
189             virtual posix_time get_time() const  = 0;
190 
191             ///
192             /// Set option for calendar, for future use
193             ///
194             virtual void set_option(calendar_option_type opt,int v) = 0;
195             ///
196             /// Get option for calendar, currently only check if it is Gregorian calendar
197             ///
198             virtual int get_option(calendar_option_type opt) const = 0;
199 
200             ///
201             /// Adjust period's \a p value by \a difference items using a update_type \a u.
202             /// Note: not all values are adjustable
203             ///
204             virtual void adjust_value(period::marks::period_mark p,update_type u,int difference) = 0;
205 
206             ///
207             /// Calculate the difference between this calendar  and \a other in \a p units
208             ///
209             virtual int difference(abstract_calendar const *other,period::marks::period_mark p) const = 0;
210 
211             ///
212             /// Set time zone, empty - use system
213             ///
214             virtual void set_timezone(std::string const &tz) = 0;
215             ///
216             /// Get current time zone, empty - system one
217             ///
218             virtual std::string get_timezone() const = 0;
219 
220             ///
221             /// Check of two calendars have same rules
222             ///
223             virtual bool same(abstract_calendar const *other) const = 0;
224 
~abstract_calendar()225             virtual ~abstract_calendar()
226             {
227             }
228 
229         };
230 
231         ///
232         /// \brief the facet that generates calendar for specific locale
233         ///
234         class BOOST_LOCALE_DECL calendar_facet : public std::locale::facet {
235         public:
236             ///
237             /// Basic constructor
238             ///
calendar_facet(size_t refs=0)239             calendar_facet(size_t refs = 0) : std::locale::facet(refs)
240             {
241             }
242             ///
243             /// Create a new calendar that points to current point of time.
244             ///
245             virtual abstract_calendar *create_calendar() const = 0;
246 
247             ///
248             /// Locale id (needed to work with std::locale)
249             ///
250             static std::locale::id id;
251         };
252 
253     } // locale
254 } // boost
255 
256 #ifdef BOOST_MSVC
257 #pragma warning(pop)
258 #endif
259 
260 
261 #endif
262 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
263 
264