Chris@16
|
1 /*
|
Chris@101
|
2 * Copyright Andrey Semashev 2007 - 2015.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file support/date_time.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 07.11.2012
|
Chris@16
|
11 *
|
Chris@16
|
12 * This header enables Boost.DateTime support for Boost.Log.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
|
Chris@16
|
16 #define BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
|
Chris@16
|
17
|
Chris@16
|
18 #include <ctime>
|
Chris@16
|
19 #include <string>
|
Chris@16
|
20 #include <locale>
|
Chris@16
|
21 #include <ostream>
|
Chris@16
|
22 #include <iterator>
|
Chris@16
|
23 #include <boost/cstdint.hpp>
|
Chris@16
|
24 #include <boost/move/core.hpp>
|
Chris@16
|
25 #include <boost/move/utility.hpp>
|
Chris@16
|
26 #include <boost/date_time/time.hpp>
|
Chris@16
|
27 #include <boost/date_time/date.hpp>
|
Chris@16
|
28 #include <boost/date_time/gregorian/gregorian_types.hpp>
|
Chris@16
|
29 #include <boost/date_time/local_time/local_time_types.hpp>
|
Chris@16
|
30 #include <boost/date_time/posix_time/posix_time_types.hpp>
|
Chris@16
|
31 #include <boost/log/detail/config.hpp>
|
Chris@16
|
32 #include <boost/log/detail/date_time_format_parser.hpp>
|
Chris@16
|
33 #include <boost/log/detail/light_function.hpp>
|
Chris@16
|
34 #include <boost/log/detail/decomposed_time.hpp>
|
Chris@16
|
35 #include <boost/log/detail/date_time_fmt_gen_traits_fwd.hpp>
|
Chris@16
|
36 #include <boost/log/utility/formatting_ostream.hpp>
|
Chris@16
|
37 #include <boost/log/detail/header.hpp>
|
Chris@16
|
38
|
Chris@16
|
39 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
40 #pragma once
|
Chris@16
|
41 #endif
|
Chris@16
|
42
|
Chris@16
|
43 namespace boost {
|
Chris@16
|
44
|
Chris@16
|
45 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
46
|
Chris@16
|
47 namespace expressions {
|
Chris@16
|
48
|
Chris@16
|
49 namespace aux {
|
Chris@16
|
50
|
Chris@16
|
51 namespace date_time_support {
|
Chris@16
|
52
|
Chris@16
|
53 template< typename DateT, typename ValueT >
|
Chris@16
|
54 inline void decompose_date(DateT const& d, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
|
Chris@16
|
55 {
|
Chris@16
|
56 typedef typename DateT::ymd_type ymd_type;
|
Chris@16
|
57 ymd_type ymd = d.year_month_day();
|
Chris@16
|
58 v.year = ymd.year;
|
Chris@16
|
59 v.month = ymd.month;
|
Chris@16
|
60 v.day = ymd.day;
|
Chris@16
|
61 }
|
Chris@16
|
62
|
Chris@16
|
63 template< typename TimeDurationT, typename ValueT >
|
Chris@16
|
64 inline void decompose_time_of_day(TimeDurationT const& tod, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
|
Chris@16
|
65 {
|
Chris@16
|
66 v.hours = tod.hours();
|
Chris@16
|
67 v.minutes = tod.minutes();
|
Chris@16
|
68 v.seconds = tod.seconds();
|
Chris@16
|
69
|
Chris@16
|
70 typedef typename TimeDurationT::traits_type traits_type;
|
Chris@16
|
71 enum
|
Chris@16
|
72 {
|
Chris@16
|
73 adjustment_ratio = (traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ?
|
Chris@16
|
74 traits_type::ticks_per_second / boost::log::aux::decomposed_time::subseconds_per_second :
|
Chris@16
|
75 boost::log::aux::decomposed_time::subseconds_per_second / traits_type::ticks_per_second)
|
Chris@16
|
76 };
|
Chris@16
|
77 uint64_t frac = tod.fractional_seconds();
|
Chris@16
|
78 v.subseconds = static_cast< uint32_t >(traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ? frac / adjustment_ratio : frac * adjustment_ratio);
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 template< typename TimeDurationT, typename ValueT >
|
Chris@16
|
82 inline void decompose_time_duration(TimeDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
|
Chris@16
|
83 {
|
Chris@16
|
84 if (dur.is_negative())
|
Chris@16
|
85 {
|
Chris@16
|
86 v.negative = true;
|
Chris@16
|
87 (decompose_time_of_day)(-dur, v);
|
Chris@16
|
88 }
|
Chris@16
|
89 else
|
Chris@16
|
90 (decompose_time_of_day)(dur, v);
|
Chris@16
|
91 }
|
Chris@16
|
92
|
Chris@16
|
93 template< typename DateDurationT, typename ValueT >
|
Chris@16
|
94 inline void decompose_date_duration(DateDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
|
Chris@16
|
95 {
|
Chris@16
|
96 if (dur.is_negative())
|
Chris@16
|
97 {
|
Chris@16
|
98 v.negative = true;
|
Chris@16
|
99 v.day = (-dur).days();
|
Chris@16
|
100 }
|
Chris@16
|
101 else
|
Chris@16
|
102 v.day = dur.days();
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 template< typename TimeT, typename ValueT >
|
Chris@16
|
106 inline void decompose_time(TimeT const& t, boost::log::aux::decomposed_time_wrapper< ValueT >& v)
|
Chris@16
|
107 {
|
Chris@16
|
108 (decompose_date)(t.date(), v);
|
Chris@16
|
109 (decompose_time_of_day)(t.time_of_day(), v);
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 } // namespace date_time_support
|
Chris@16
|
113
|
Chris@16
|
114 template< typename TimeT, typename CharT >
|
Chris@16
|
115 struct date_time_formatter_generator_traits_impl
|
Chris@16
|
116 {
|
Chris@16
|
117 //! Character type
|
Chris@16
|
118 typedef CharT char_type;
|
Chris@16
|
119 //! String type
|
Chris@16
|
120 typedef std::basic_string< char_type > string_type;
|
Chris@16
|
121 //! Formatting stream type
|
Chris@16
|
122 typedef basic_formatting_ostream< char_type > stream_type;
|
Chris@16
|
123 //! Value type
|
Chris@16
|
124 typedef TimeT value_type;
|
Chris@16
|
125
|
Chris@16
|
126 //! Formatter function
|
Chris@16
|
127 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
|
Chris@16
|
128
|
Chris@16
|
129 //! Formatter implementation
|
Chris@16
|
130 class formatter :
|
Chris@16
|
131 public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
|
Chris@16
|
132 {
|
Chris@16
|
133 BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
|
Chris@16
|
134
|
Chris@16
|
135 private:
|
Chris@16
|
136 // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
|
Chris@16
|
137 typedef typename formatter::date_time_formatter_ base_type;
|
Chris@16
|
138
|
Chris@16
|
139 public:
|
Chris@16
|
140 typedef typename base_type::result_type result_type;
|
Chris@16
|
141 // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
|
Chris@16
|
142 typedef typename date_time_formatter_generator_traits_impl< TimeT, CharT >::value_type value_type;
|
Chris@16
|
143
|
Chris@16
|
144 public:
|
Chris@16
|
145 BOOST_DEFAULTED_FUNCTION(formatter(), {})
|
Chris@16
|
146 formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
|
Chris@16
|
147 formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
|
Chris@16
|
148
|
Chris@16
|
149 formatter& operator= (formatter that)
|
Chris@16
|
150 {
|
Chris@16
|
151 this->swap(that);
|
Chris@16
|
152 return *this;
|
Chris@16
|
153 }
|
Chris@16
|
154
|
Chris@16
|
155 result_type operator() (stream_type& strm, value_type const& value) const
|
Chris@16
|
156 {
|
Chris@16
|
157 if (value.is_not_a_date_time())
|
Chris@16
|
158 strm << "not-a-date-time";
|
Chris@16
|
159 else if (value.is_pos_infinity())
|
Chris@16
|
160 strm << "+infinity";
|
Chris@16
|
161 else if (value.is_neg_infinity())
|
Chris@16
|
162 strm << "-infinity";
|
Chris@16
|
163 else
|
Chris@16
|
164 {
|
Chris@16
|
165 boost::log::aux::decomposed_time_wrapper< value_type > val(value);
|
Chris@16
|
166 date_time_support::decompose_time(value, val);
|
Chris@16
|
167 base_type::operator() (strm, val);
|
Chris@16
|
168 }
|
Chris@16
|
169 }
|
Chris@16
|
170 };
|
Chris@16
|
171
|
Chris@16
|
172 //! The function parses format string and constructs formatter function
|
Chris@16
|
173 static formatter_function_type parse(string_type const& format)
|
Chris@16
|
174 {
|
Chris@16
|
175 formatter fmt;
|
Chris@16
|
176 boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
|
Chris@16
|
177 boost::log::aux::parse_date_time_format(format, builder);
|
Chris@16
|
178 return formatter_function_type(boost::move(fmt));
|
Chris@16
|
179 }
|
Chris@16
|
180 };
|
Chris@16
|
181
|
Chris@16
|
182 template< typename CharT, typename VoidT >
|
Chris@16
|
183 struct date_time_formatter_generator_traits< posix_time::ptime, CharT, VoidT > :
|
Chris@16
|
184 public date_time_formatter_generator_traits_impl< posix_time::ptime, CharT >
|
Chris@16
|
185 {
|
Chris@16
|
186 };
|
Chris@16
|
187
|
Chris@16
|
188 template< typename TimeT, typename TimeZoneT, typename CharT, typename VoidT >
|
Chris@16
|
189 struct date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT >
|
Chris@16
|
190 {
|
Chris@16
|
191 //! Character type
|
Chris@16
|
192 typedef CharT char_type;
|
Chris@16
|
193 //! String type
|
Chris@16
|
194 typedef std::basic_string< char_type > string_type;
|
Chris@16
|
195 //! Formatting stream type
|
Chris@16
|
196 typedef basic_formatting_ostream< char_type > stream_type;
|
Chris@16
|
197 //! Value type
|
Chris@16
|
198 typedef local_time::local_date_time_base< TimeT, TimeZoneT > value_type;
|
Chris@16
|
199
|
Chris@16
|
200 //! Formatter function
|
Chris@16
|
201 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
|
Chris@16
|
202
|
Chris@16
|
203 //! Formatter implementation
|
Chris@16
|
204 class formatter :
|
Chris@16
|
205 public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
|
Chris@16
|
206 {
|
Chris@16
|
207 BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
|
Chris@16
|
208
|
Chris@16
|
209 private:
|
Chris@16
|
210 // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
|
Chris@16
|
211 typedef typename formatter::date_time_formatter_ base_type;
|
Chris@16
|
212
|
Chris@16
|
213 public:
|
Chris@16
|
214 typedef typename base_type::result_type result_type;
|
Chris@16
|
215 typedef typename base_type::context context;
|
Chris@16
|
216 // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
|
Chris@16
|
217 typedef typename date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT >::value_type value_type;
|
Chris@16
|
218
|
Chris@16
|
219 public:
|
Chris@16
|
220 BOOST_DEFAULTED_FUNCTION(formatter(), {})
|
Chris@16
|
221 formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
|
Chris@16
|
222 formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
|
Chris@16
|
223
|
Chris@16
|
224 formatter& operator= (formatter that)
|
Chris@16
|
225 {
|
Chris@16
|
226 this->swap(that);
|
Chris@16
|
227 return *this;
|
Chris@16
|
228 }
|
Chris@16
|
229
|
Chris@16
|
230 result_type operator() (stream_type& strm, value_type const& value) const
|
Chris@16
|
231 {
|
Chris@16
|
232 if (value.is_not_a_date_time())
|
Chris@16
|
233 strm << "not-a-date-time";
|
Chris@16
|
234 else if (value.is_pos_infinity())
|
Chris@16
|
235 strm << "+infinity";
|
Chris@16
|
236 else if (value.is_neg_infinity())
|
Chris@16
|
237 strm << "-infinity";
|
Chris@16
|
238 else
|
Chris@16
|
239 {
|
Chris@16
|
240 boost::log::aux::decomposed_time_wrapper< value_type > val(value);
|
Chris@16
|
241 date_time_support::decompose_time(value.local_time(), val);
|
Chris@16
|
242 base_type::operator() (strm, val);
|
Chris@16
|
243 }
|
Chris@16
|
244 }
|
Chris@16
|
245
|
Chris@16
|
246 public:
|
Chris@16
|
247 static void format_iso_time_zone(context& ctx)
|
Chris@16
|
248 {
|
Chris@16
|
249 ctx.strm << ctx.value.m_time.zone_abbrev(true);
|
Chris@16
|
250 ctx.strm.flush();
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 static void format_extended_iso_time_zone(context& ctx)
|
Chris@16
|
254 {
|
Chris@16
|
255 ctx.strm << ctx.value.m_time.zone_name(true);
|
Chris@16
|
256 ctx.strm.flush();
|
Chris@16
|
257 }
|
Chris@16
|
258 };
|
Chris@16
|
259
|
Chris@16
|
260 class formatter_builder :
|
Chris@16
|
261 public boost::log::aux::decomposed_time_formatter_builder< formatter, char_type >
|
Chris@16
|
262 {
|
Chris@16
|
263 private:
|
Chris@16
|
264 typedef boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > base_type;
|
Chris@16
|
265
|
Chris@16
|
266 public:
|
Chris@16
|
267 explicit formatter_builder(formatter& fmt) : base_type(fmt)
|
Chris@16
|
268 {
|
Chris@16
|
269 }
|
Chris@16
|
270
|
Chris@16
|
271 void on_iso_time_zone()
|
Chris@16
|
272 {
|
Chris@16
|
273 this->m_formatter.add_formatter(&formatter::format_iso_time_zone);
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 void on_extended_iso_time_zone()
|
Chris@16
|
277 {
|
Chris@16
|
278 this->m_formatter.add_formatter(&formatter::format_extended_iso_time_zone);
|
Chris@16
|
279 }
|
Chris@16
|
280 };
|
Chris@16
|
281
|
Chris@16
|
282 //! The function parses format string and constructs formatter function
|
Chris@16
|
283 static formatter_function_type parse(string_type const& format)
|
Chris@16
|
284 {
|
Chris@16
|
285 formatter fmt;
|
Chris@16
|
286 formatter_builder builder(fmt);
|
Chris@16
|
287 boost::log::aux::parse_date_time_format(format, builder);
|
Chris@16
|
288 return formatter_function_type(boost::move(fmt));
|
Chris@16
|
289 }
|
Chris@16
|
290 };
|
Chris@16
|
291
|
Chris@16
|
292 template< typename DateT, typename CharT >
|
Chris@16
|
293 struct date_formatter_generator_traits_impl
|
Chris@16
|
294 {
|
Chris@16
|
295 //! Character type
|
Chris@16
|
296 typedef CharT char_type;
|
Chris@16
|
297 //! String type
|
Chris@16
|
298 typedef std::basic_string< char_type > string_type;
|
Chris@16
|
299 //! Formatting stream type
|
Chris@16
|
300 typedef basic_formatting_ostream< char_type > stream_type;
|
Chris@16
|
301 //! Value type
|
Chris@16
|
302 typedef DateT value_type;
|
Chris@16
|
303
|
Chris@16
|
304 //! Formatter function
|
Chris@16
|
305 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
|
Chris@16
|
306
|
Chris@16
|
307 //! Formatter implementation
|
Chris@16
|
308 class formatter :
|
Chris@16
|
309 public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
|
Chris@16
|
310 {
|
Chris@16
|
311 BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
|
Chris@16
|
312
|
Chris@16
|
313 private:
|
Chris@16
|
314 // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
|
Chris@16
|
315 typedef typename formatter::date_time_formatter_ base_type;
|
Chris@16
|
316
|
Chris@16
|
317 public:
|
Chris@16
|
318 typedef typename base_type::result_type result_type;
|
Chris@16
|
319 // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
|
Chris@16
|
320 typedef typename date_formatter_generator_traits_impl< DateT, CharT >::value_type value_type;
|
Chris@16
|
321
|
Chris@16
|
322 public:
|
Chris@16
|
323 BOOST_DEFAULTED_FUNCTION(formatter(), {})
|
Chris@16
|
324 formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
|
Chris@16
|
325 formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
|
Chris@16
|
326
|
Chris@16
|
327 formatter& operator= (formatter that)
|
Chris@16
|
328 {
|
Chris@16
|
329 this->swap(that);
|
Chris@16
|
330 return *this;
|
Chris@16
|
331 }
|
Chris@16
|
332
|
Chris@16
|
333 result_type operator() (stream_type& strm, value_type const& value) const
|
Chris@16
|
334 {
|
Chris@16
|
335 if (value.is_not_a_date())
|
Chris@16
|
336 strm << "not-a-date-time";
|
Chris@16
|
337 else if (value.is_pos_infinity())
|
Chris@16
|
338 strm << "+infinity";
|
Chris@16
|
339 else if (value.is_neg_infinity())
|
Chris@16
|
340 strm << "-infinity";
|
Chris@16
|
341 else
|
Chris@16
|
342 {
|
Chris@16
|
343 boost::log::aux::decomposed_time_wrapper< value_type > val(value);
|
Chris@16
|
344 date_time_support::decompose_date(value, val);
|
Chris@16
|
345 base_type::operator() (strm, val);
|
Chris@16
|
346 }
|
Chris@16
|
347 }
|
Chris@16
|
348 };
|
Chris@16
|
349
|
Chris@16
|
350 //! The function parses format string and constructs formatter function
|
Chris@16
|
351 static formatter_function_type parse(string_type const& format)
|
Chris@16
|
352 {
|
Chris@16
|
353 formatter fmt;
|
Chris@16
|
354 boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
|
Chris@16
|
355 boost::log::aux::parse_date_format(format, builder);
|
Chris@16
|
356 return formatter_function_type(boost::move(fmt));
|
Chris@16
|
357 }
|
Chris@16
|
358 };
|
Chris@16
|
359
|
Chris@16
|
360 template< typename CharT, typename VoidT >
|
Chris@16
|
361 struct date_time_formatter_generator_traits< gregorian::date, CharT, VoidT > :
|
Chris@16
|
362 public date_formatter_generator_traits_impl< gregorian::date, CharT >
|
Chris@16
|
363 {
|
Chris@16
|
364 };
|
Chris@16
|
365
|
Chris@16
|
366 template< typename TimeDurationT, typename CharT >
|
Chris@16
|
367 struct time_duration_formatter_generator_traits_impl
|
Chris@16
|
368 {
|
Chris@16
|
369 //! Character type
|
Chris@16
|
370 typedef CharT char_type;
|
Chris@16
|
371 //! String type
|
Chris@16
|
372 typedef std::basic_string< char_type > string_type;
|
Chris@16
|
373 //! Formatting stream type
|
Chris@16
|
374 typedef basic_formatting_ostream< char_type > stream_type;
|
Chris@16
|
375 //! Value type
|
Chris@16
|
376 typedef TimeDurationT value_type;
|
Chris@16
|
377
|
Chris@16
|
378 //! Formatter function
|
Chris@16
|
379 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
|
Chris@16
|
380
|
Chris@16
|
381 //! Formatter implementation
|
Chris@16
|
382 class formatter :
|
Chris@16
|
383 public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
|
Chris@16
|
384 {
|
Chris@16
|
385 BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
|
Chris@16
|
386
|
Chris@16
|
387 private:
|
Chris@16
|
388 // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
|
Chris@16
|
389 typedef typename formatter::date_time_formatter_ base_type;
|
Chris@16
|
390
|
Chris@16
|
391 public:
|
Chris@16
|
392 typedef typename base_type::result_type result_type;
|
Chris@16
|
393 // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
|
Chris@16
|
394 typedef typename time_duration_formatter_generator_traits_impl< TimeDurationT, CharT >::value_type value_type;
|
Chris@16
|
395
|
Chris@16
|
396 public:
|
Chris@16
|
397 BOOST_DEFAULTED_FUNCTION(formatter(), {})
|
Chris@16
|
398 formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
|
Chris@16
|
399 formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
|
Chris@16
|
400
|
Chris@16
|
401 formatter& operator= (formatter that)
|
Chris@16
|
402 {
|
Chris@16
|
403 this->swap(that);
|
Chris@16
|
404 return *this;
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 result_type operator() (stream_type& strm, value_type const& value) const
|
Chris@16
|
408 {
|
Chris@16
|
409 if (value.is_not_a_date_time())
|
Chris@16
|
410 strm << "not-a-date-time";
|
Chris@16
|
411 else if (value.is_pos_infinity())
|
Chris@16
|
412 strm << "+infinity";
|
Chris@16
|
413 else if (value.is_neg_infinity())
|
Chris@16
|
414 strm << "-infinity";
|
Chris@16
|
415 else
|
Chris@16
|
416 {
|
Chris@16
|
417 boost::log::aux::decomposed_time_wrapper< value_type > val(value);
|
Chris@16
|
418 date_time_support::decompose_time_duration(value, val);
|
Chris@16
|
419 base_type::operator() (strm, val);
|
Chris@16
|
420 }
|
Chris@16
|
421 }
|
Chris@16
|
422 };
|
Chris@16
|
423
|
Chris@16
|
424 //! The function parses format string and constructs formatter function
|
Chris@16
|
425 static formatter_function_type parse(string_type const& format)
|
Chris@16
|
426 {
|
Chris@16
|
427 formatter fmt;
|
Chris@16
|
428 boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
|
Chris@16
|
429 boost::log::aux::parse_time_format(format, builder);
|
Chris@16
|
430 return formatter_function_type(boost::move(fmt));
|
Chris@16
|
431 }
|
Chris@16
|
432 };
|
Chris@16
|
433
|
Chris@16
|
434 template< typename CharT, typename VoidT >
|
Chris@16
|
435 struct date_time_formatter_generator_traits< posix_time::time_duration, CharT, VoidT > :
|
Chris@16
|
436 public time_duration_formatter_generator_traits_impl< posix_time::time_duration, CharT >
|
Chris@16
|
437 {
|
Chris@16
|
438 };
|
Chris@16
|
439
|
Chris@16
|
440 template< typename CharT, typename VoidT >
|
Chris@16
|
441 struct date_time_formatter_generator_traits< posix_time::hours, CharT, VoidT > :
|
Chris@16
|
442 public time_duration_formatter_generator_traits_impl< posix_time::hours, CharT >
|
Chris@16
|
443 {
|
Chris@16
|
444 };
|
Chris@16
|
445
|
Chris@16
|
446 template< typename CharT, typename VoidT >
|
Chris@16
|
447 struct date_time_formatter_generator_traits< posix_time::minutes, CharT, VoidT > :
|
Chris@16
|
448 public time_duration_formatter_generator_traits_impl< posix_time::minutes, CharT >
|
Chris@16
|
449 {
|
Chris@16
|
450 };
|
Chris@16
|
451
|
Chris@16
|
452 template< typename CharT, typename VoidT >
|
Chris@16
|
453 struct date_time_formatter_generator_traits< posix_time::seconds, CharT, VoidT > :
|
Chris@16
|
454 public time_duration_formatter_generator_traits_impl< posix_time::seconds, CharT >
|
Chris@16
|
455 {
|
Chris@16
|
456 };
|
Chris@16
|
457
|
Chris@16
|
458 template< typename BaseDurationT, uint64_t FracOfSecondV, typename CharT, typename VoidT >
|
Chris@16
|
459 struct date_time_formatter_generator_traits< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT, VoidT > :
|
Chris@16
|
460 public time_duration_formatter_generator_traits_impl< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT >
|
Chris@16
|
461 {
|
Chris@16
|
462 };
|
Chris@16
|
463
|
Chris@16
|
464 template< typename DateDurationT, typename CharT >
|
Chris@16
|
465 struct date_duration_formatter_generator_traits_impl
|
Chris@16
|
466 {
|
Chris@16
|
467 //! Character type
|
Chris@16
|
468 typedef CharT char_type;
|
Chris@16
|
469 //! String type
|
Chris@16
|
470 typedef std::basic_string< char_type > string_type;
|
Chris@16
|
471 //! Formatting stream type
|
Chris@16
|
472 typedef basic_formatting_ostream< char_type > stream_type;
|
Chris@16
|
473 //! Value type
|
Chris@16
|
474 typedef DateDurationT value_type;
|
Chris@16
|
475
|
Chris@16
|
476 //! Formatter function
|
Chris@16
|
477 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
|
Chris@16
|
478
|
Chris@16
|
479 //! Formatter implementation
|
Chris@16
|
480 class formatter :
|
Chris@16
|
481 public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type >
|
Chris@16
|
482 {
|
Chris@16
|
483 BOOST_COPYABLE_AND_MOVABLE_ALT(formatter)
|
Chris@16
|
484
|
Chris@16
|
485 private:
|
Chris@16
|
486 // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type.
|
Chris@16
|
487 typedef typename formatter::date_time_formatter_ base_type;
|
Chris@16
|
488
|
Chris@16
|
489 public:
|
Chris@16
|
490 typedef typename base_type::result_type result_type;
|
Chris@16
|
491 // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead.
|
Chris@16
|
492 typedef typename date_duration_formatter_generator_traits_impl< DateDurationT, CharT >::value_type value_type;
|
Chris@16
|
493
|
Chris@16
|
494 public:
|
Chris@16
|
495 BOOST_DEFAULTED_FUNCTION(formatter(), {})
|
Chris@16
|
496 formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {}
|
Chris@16
|
497 formatter(BOOST_RV_REF(formatter) that) { this->swap(that); }
|
Chris@16
|
498
|
Chris@16
|
499 formatter& operator= (formatter that)
|
Chris@16
|
500 {
|
Chris@16
|
501 this->swap(that);
|
Chris@16
|
502 return *this;
|
Chris@16
|
503 }
|
Chris@16
|
504
|
Chris@16
|
505 result_type operator() (stream_type& strm, value_type const& value) const
|
Chris@16
|
506 {
|
Chris@16
|
507 if (value.is_not_a_date())
|
Chris@16
|
508 strm << "not-a-date-time";
|
Chris@16
|
509 else if (value.is_pos_infinity())
|
Chris@16
|
510 strm << "+infinity";
|
Chris@16
|
511 else if (value.is_neg_infinity())
|
Chris@16
|
512 strm << "-infinity";
|
Chris@16
|
513 else
|
Chris@16
|
514 {
|
Chris@16
|
515 boost::log::aux::decomposed_time_wrapper< value_type > val(value);
|
Chris@16
|
516 date_time_support::decompose_date_duration(value, val);
|
Chris@16
|
517 base_type::operator() (strm, val);
|
Chris@16
|
518 }
|
Chris@16
|
519 }
|
Chris@16
|
520 };
|
Chris@16
|
521
|
Chris@16
|
522 //! The function parses format string and constructs formatter function
|
Chris@16
|
523 static formatter_function_type parse(string_type const& format)
|
Chris@16
|
524 {
|
Chris@16
|
525 formatter fmt;
|
Chris@16
|
526 boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt);
|
Chris@16
|
527 boost::log::aux::parse_date_format(format, builder);
|
Chris@16
|
528 return formatter_function_type(boost::move(fmt));
|
Chris@16
|
529 }
|
Chris@16
|
530 };
|
Chris@16
|
531
|
Chris@16
|
532 template< typename CharT, typename VoidT >
|
Chris@16
|
533 struct date_time_formatter_generator_traits< gregorian::date_duration, CharT, VoidT > :
|
Chris@16
|
534 public date_formatter_generator_traits_impl< gregorian::date_duration, CharT >
|
Chris@16
|
535 {
|
Chris@16
|
536 };
|
Chris@16
|
537
|
Chris@16
|
538 } // namespace aux
|
Chris@16
|
539
|
Chris@16
|
540 } // namespace expressions
|
Chris@16
|
541
|
Chris@16
|
542 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
543
|
Chris@16
|
544 } // namespace boost
|
Chris@16
|
545
|
Chris@16
|
546 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
547
|
Chris@16
|
548 #endif // BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_
|