1//
2// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3//
4// Distributed under the Boost Software License, Version 1.0.
5// https://www.boost.org/LICENSE_1_0.txt
6
7#ifndef BOOST_LOCALE_DATE_TIME_FACET_HPP_INCLUDED
8#define BOOST_LOCALE_DATE_TIME_FACET_HPP_INCLUDED
9
10#include <boost/locale/config.hpp>
11#include <boost/locale/detail/facet_id.hpp>
12#include <cstdint>
13#include <locale>
14
15#ifdef BOOST_MSVC
16# pragma warning(push)
17# pragma warning(disable : 4275 4251 4231 4660)
18#endif
19
20namespace boost { namespace locale {
21
22 /// \brief Namespace that contains various types for manipulation with dates
23 namespace period {
24
25 /// \brief This namespace holds a enum of various period types like era, year, month, etc..
26 namespace marks {
27
28 /// \brief the type that defines a flag that holds a period identifier
29 enum period_mark {
30 invalid, ///< Special invalid value, should not be used directly
31 era, ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
32 year, ///< Year, it is calendar specific, for example 2011 in Gregorian calendar.
33 extended_year, ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
34 month, ///< The month of year, calendar specific, in Gregorian [0..11]
35 day, ///< The day of month, calendar specific, in Gregorian [1..31]
36 day_of_year, ///< The number of day in year, starting from 1, in Gregorian [1..366]
37 day_of_week, ///< Day of week, Sunday=1, Monday=2,..., Saturday=7.
38 ///< Note that updating this value respects local day of week, so for example,
39 ///< If first day of week is Monday and the current day is Tuesday then setting
40 ///< the value to Sunday (1) would forward the date by 5 days forward and not backward
41 ///< by two days as it could be expected if the numbers were taken as is.
42 day_of_week_in_month, ///< Original number of the day of the week in month. For example 1st Sunday,
43 ///< 2nd Sunday, etc. in Gregorian [1..5]
44 day_of_week_local, ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
45 hour, ///< 24 clock hour [0..23]
46 hour_12, ///< 12 clock hour [0..11]
47 am_pm, ///< am or pm marker [0..1]
48 minute, ///< minute [0..59]
49 second, ///< second [0..59]
50 week_of_year, ///< The week number in the year
51 week_of_month, ///< The week number within current month
52 first_day_of_week, ///< First day of week, constant, for example Sunday in US = 1, Monday in France = 2
53 };
54
55 } // namespace marks
56
57 /// \brief This class holds a type that represents certain period of time like
58 /// year, hour, second and so on.
59 ///
60 /// It can be created from either marks::period_mark type or by using shortcuts in period
61 /// namespace - calling functions like period::year(), period::hour() and so on.
62 ///
63 /// Basically it represents the same object as enum marks::period_mark but allows to
64 /// provide save operator overloading that would not collide with casing of enum to
65 /// numeric values.
66 class period_type {
67 public:
68 /// Create a period of specific type, default is invalid.
69 period_type(marks::period_mark m = marks::invalid) : mark_(m) {}
70
71 /// Get the value of marks::period_mark it was created with.
72 marks::period_mark mark() const { return mark_; }
73
74 /// Check if two periods are the same
75 bool operator==(const period_type& other) const { return mark() == other.mark(); }
76 /// Check if two periods are different
77 bool operator!=(const period_type& other) const { return mark() != other.mark(); }
78
79 private:
80 marks::period_mark mark_;
81 };
82
83 } // namespace period
84
85 /// Structure that define POSIX time, seconds and milliseconds
86 /// since Jan 1, 1970, 00:00 not including leap seconds.
87 struct posix_time {
88 int64_t seconds; ///< Seconds since epoch
89 uint32_t nanoseconds; ///< Nanoseconds resolution
90 };
91
92 /// This class defines generic calendar class, it is used by date_time and calendar
93 /// objects internally. It is less useful for end users, but it is build for localization
94 /// backend implementation
95 class BOOST_SYMBOL_VISIBLE abstract_calendar {
96 public:
97 /// Type that defines how to fetch the value
98 enum value_type {
99 absolute_minimum, ///< Absolute possible minimum for the value, for example for day is 1
100 actual_minimum, ///< Actual minimal value for this period.
101 greatest_minimum, ///< Maximal minimum value that can be for this period
102 current, ///< Current value of this period
103 least_maximum, ///< The last maximal value for this period, For example for Gregorian calendar
104 ///< day it is 28
105 actual_maximum, ///< Actual maximum, for it can be 28, 29, 30, 31 for day according to current month
106 absolute_maximum, ///< Maximal value, for Gregorian day it would be 31.
107 };
108
109 /// A way to update the value
110 enum update_type {
111 move, ///< Change the value up or down effecting others for example 1990-12-31 + 1 day = 1991-01-01
112 roll, ///< Change the value up or down not effecting others for example 1990-12-31 + 1 day = 1990-12-01
113 };
114
115 /// Information about calendar
116 enum calendar_option_type {
117 is_gregorian, ///< Check if the calendar is Gregorian
118 is_dst ///< Check if the current time is in daylight time savings
119 };
120
121 /// Make a polymorphic copy of the calendar
122 virtual abstract_calendar* clone() const = 0;
123
124 /// Set specific \a value for period \a p, note not all values are settable.
125 ///
126 /// After calling set_value you may want to call normalize() function to make sure
127 /// all periods are updated, if you set several fields that are part of a single
128 /// date/time representation you should call set_value several times and then
129 /// call normalize().
130 ///
131 /// If normalize() is not called after set_value, the behavior is undefined
132 virtual void set_value(period::marks::period_mark m, int value) = 0;
133
134 /// Recalculate all periods after setting them, should be called after use of set_value() function.
135 virtual void normalize() = 0;
136
137 /// Get specific value for period \a p according to a value_type \a v
138 virtual int get_value(period::marks::period_mark m, value_type v) const = 0;
139
140 /// Set current time point
141 virtual void set_time(const posix_time& p) = 0;
142 /// Get current time point
143 virtual posix_time get_time() const = 0;
144 /// Get current time since epoch in milliseconds
145 virtual double get_time_ms() const = 0;
146
147 /// Set option for calendar, for future use
148 virtual void set_option(calendar_option_type opt, int v) = 0;
149 /// Get option for calendar, currently only check if it is Gregorian calendar
150 virtual int get_option(calendar_option_type opt) const = 0;
151
152 /// Adjust period's \a p value by \a difference items using a update_type \a u.
153 /// Note: not all values are adjustable
154 virtual void adjust_value(period::marks::period_mark m, update_type u, int difference) = 0;
155
156 /// Calculate the difference between this calendar and \a other in \a p units
157 virtual int difference(const abstract_calendar& other, period::marks::period_mark m) const = 0;
158
159 /// Set time zone, empty - use system
160 virtual void set_timezone(const std::string& tz) = 0;
161 /// Get current time zone, empty - system one
162 virtual std::string get_timezone() const = 0;
163
164 /// Check of two calendars have same rules
165 virtual bool same(const abstract_calendar* other) const = 0;
166
167 virtual ~abstract_calendar() = default;
168 };
169
170 /// \brief the facet that generates calendar for specific locale
171 class BOOST_SYMBOL_VISIBLE calendar_facet : public std::locale::facet, public detail::facet_id<calendar_facet> {
172 public:
173 /// Basic constructor
174 calendar_facet(size_t refs = 0) : std::locale::facet(refs) {}
175 /// Create a new calendar that points to current point of time.
176 virtual abstract_calendar* create_calendar() const = 0;
177 };
178
179}} // namespace boost::locale
180
181#ifdef BOOST_MSVC
182# pragma warning(pop)
183#endif
184
185#endif
186

source code of boost/libs/locale/include/boost/locale/date_time_facet.hpp