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