BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_timezoneformatter.h
Go to the documentation of this file.
1/// @file bdlt_timezoneformatter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_timezoneformatter.h -*-C++-*-
8#ifndef INCLUDED_BDLT_TIMEZONEFORMATTER
9#define INCLUDED_BDLT_TIMEZONEFORMATTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_timezoneformatter bdlt_timezoneformatter
15/// @brief Provide a mechanism for formatting time zones.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_timezoneformatter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_timezoneformatter-purpose"> Purpose</a>
25/// * <a href="#bdlt_timezoneformatter-classes"> Classes </a>
26/// * <a href="#bdlt_timezoneformatter-description"> Description </a>
27///
28/// # Purpose {#bdlt_timezoneformatter-purpose}
29/// Provide a mechanism for formatting time zones.
30///
31/// # Classes {#bdlt_timezoneformatter-classes}
32///
33/// - bdlt::TimeZoneFormatter
34///
35/// # Description {#bdlt_timezoneformatter-description}
36/// This component implements a formatter for time zone
37/// information. Output can be done with the 'z' specifier, which outputs a
38/// 2-digit hour and a 2-digit minute, sometimes but not always separated by a
39/// ':'.
40///
41/// This formatter interprets the following modifiers:
42/// - 'Z' - if the offset is zero, output the time zone as 'Z', otherwise output
43/// it normally.
44/// - ':' (colon) - always print a colon between hours and minutes
45/// - '_' (underscore) - never print a colon between hours and minutes
46/// Note that it is an error for both ':' and '_' to be specified at the same
47/// time.
48///
49/// This formatter interprets only the following format specifier:
50/// - 'z' - output the time zone in default format (subject to any applicable
51/// modifiers).
52/// @}
53/** @} */
54/** @} */
55
56/** @addtogroup bdl
57 * @{
58 */
59/** @addtogroup bdlt
60 * @{
61 */
62/** @addtogroup bdlt_timezoneformatter
63 * @{
64 */
65
66#include <bdlscm_version.h>
67
68#include <bdlt_formatutil.h>
69
70#include <bslmf_assert.h>
71#include <bslmf_issame.h>
72
73#include <bsls_assert.h>
74#include <bsls_exceptionutil.h>
75
76#include <bsl_cmath.h>
77
78
79namespace bdlt {
80
81 // =======================
82 // class TimeZoneFormatter
83 // =======================
84
85/// This `class` provides a specifier formatter for printing time zones.
86///
87/// See @ref bdlt_timezoneformatter
88template <class t_CHAR>
90 // PRIVATE TYPES
91 enum { k_OFFSET_LIMIT = 24 * 60,
92 k_INITIAL_OFFSET = 2 * k_OFFSET_LIMIT };
93
95 typedef typename Util::StringView StringView;
96
97 // DATA
98 int d_numDefaultTimeZones;
99 int d_numIso8601TimeZones;
100 bool d_colon;
101 bool d_noColon;
102 bool d_tzZ;
103
106
107 // PRIVATE ACCESSORS
108
109 /// Format the time zone indicated by the specified `offset` to the
110 /// specified `out`, where the specified `isIso8601` indicates whether the
111 /// time zone is to be formatted Iso8601 style or default style.
112 template <class t_ITERATOR>
113 t_ITERATOR formatImp(t_ITERATOR out, int offset, bool isIso8601) const;
114
115 /// Return `true` if the time zone indicated by the specified `offset`
116 /// should be shown as "Z" and `false` otherwise.
117 bool isTimeZoneZ(int offset) const;
118
119 public:
120 // CREATORS
121
122 /// Create an object in its default initial state.
125
126 // MANIPULATORS
127
128 /// Parse a time zone that will be formatted in default mode.
130
131 /// Parse a time zone that will be formatted in Iso8601 mode.
133
134 /// Examine the first character of the specified `*specInOut` and if it is
135 /// recognized as a modifier by this object, update this object's state to
136 /// reflect it and pop it off the front of `*specInOut` and return `true`,
137 /// and if not, return `false` with no modification to `*specInOut`.
139
140 /// If the first character of the specified `*specInOut` is recognized by
141 /// this specifier formatter, parse it, remove it from `*specInOut`, and
142 /// return `true`, otherwise return `false` with no modification to `*specInOut`.
143 ///
144 /// \pre The behavior is undefined if `*specInOut` is empty.
146 bool parseNextSpecifier(StringView *specInOut);
147
148 /// Read post-processed fields from the specified `spec` that are relevant
149 /// to this specifier formatter.
151
152 // ACCESSORS
153
154 /// Return the `bslfmt::FormatSpecificationParser::Sections` flags that
155 /// apply to this value type.
157 int extraSections() const;
158
159 /// Format the time zone indicated by the specified `offset` to the
160 /// specified `out` using the default format and return `out`.
161 template <class t_ITERATOR>
162 t_ITERATOR formatDefault(t_ITERATOR out, int offset) const;
163
164 /// Format the time zone indicated by the specified `offset` to the
165 /// specified `out` using the Iso8601 format and return `out`.
166 template <class t_ITERATOR>
167 t_ITERATOR formatIso8601(t_ITERATOR out, int offset) const;
168
169 /// If the first character of the specified `*specInOut` is recognized by
170 /// this specifier formatter, use it to format the time zone indicated by
171 /// the specified `offset` to `*outIt`, remove the character from
172 /// `*specInOut`, and return `true`, otherwise return `false` with no
173 /// modification to `*specInOut`.
174 template <class t_ITERATOR>
176 t_ITERATOR *outIt,
177 int offset) const;
178
179 /// Return the anticipated width of output given all the `parse*` calls
180 /// that have been happened thus far and the time zone indicated by the
181 /// specified `offset`.
182 int totalWidth(int offset) const;
183};
184
185 // -----------------------
186 // class TimeZoneFormatter
187 // -----------------------
188
189// PRIVATE ACCESSORS
190template <class t_CHAR>
191template <class t_ITERATOR>
192inline
194 t_ITERATOR out, int offset, bool isIso8601) const
195{
196 if (isTimeZoneZ(offset)) {
197 *out++ = t_CHAR('Z');
198
199 return out; // RETURN
200 }
201
202 *out++ = offset < 0 ? t_CHAR('-') : t_CHAR('+');
203
204 const int absOffset = bsl::abs(offset);
205
206 BSLS_ASSERT_SAFE(absOffset <= k_OFFSET_LIMIT);
207
208 const int hours = absOffset / 60;
209 const int minutes = absOffset % 60;
210
211 out = Util::writeZeroPaddedDigits(out, hours, 2);
212 if (d_colon || (isIso8601 && !d_noColon)) {
213 *out++ = t_CHAR(':');
214 }
215 return Util::writeZeroPaddedDigits(out, minutes, 2);
216}
217
218template <class t_CHAR>
219bool TimeZoneFormatter<t_CHAR>::isTimeZoneZ(int offset) const
220{
221 return d_tzZ && 0 == offset;
222}
223
224// CREATORS
225template <class t_CHAR>
228: d_numDefaultTimeZones(0)
229, d_numIso8601TimeZones(0)
230, d_colon(false)
231, d_noColon(false)
232, d_tzZ(false)
233{}
234
235// MANIPULATORS
236template <class t_CHAR>
239{
240 ++d_numDefaultTimeZones;
241}
242
243template <class t_CHAR>
246{
247 ++d_numIso8601TimeZones;
248}
249
250template <class t_CHAR>
253{
254 BSLS_ASSERT(!specInOut->empty());
255
256 switch (specInOut->front()) {
257 case t_CHAR(':'): {
258 d_colon = true;
259 } break;
260 case t_CHAR('_'): {
261 d_noColon = true;
262 } break;
263 case t_CHAR('Z'): {
264 d_tzZ = true;
265 } break;
266 default: {
267 return false; // RETURN
268 }
269 }
270
271 if (d_colon && d_noColon) {
272 BSLS_THROW(bsl::format_error(
273 "Illegal: both ':' and '_' modifiers specified"));
274 }
275
276 specInOut->remove_prefix(1);
277
278 return true;
279}
280
281template <class t_CHAR>
284{
285 BSLS_ASSERT(!specInOut->empty());
286
287 if (t_CHAR('z') == specInOut->front()) {
288 ++d_numDefaultTimeZones;
289 specInOut->remove_prefix(1);
290
291 return true; // RETURN
292 }
293
294 return false;
295}
296
297template <class t_CHAR>
298inline
302
303// ACCESSORS
304template <class t_CHAR>
307{
308 return 0;
309}
310
311template <class t_CHAR>
312template <class t_ITERATOR>
313inline
315 t_ITERATOR out, int offset) const
316{
317 return formatImp(out, offset, false);
318}
319
320template <class t_CHAR>
321template <class t_ITERATOR>
322inline
324 t_ITERATOR out, int offset) const
325{
326 return formatImp(out, offset, true);
327}
328
329template <class t_CHAR>
330template <class t_ITERATOR>
333 t_ITERATOR *outIt,
334 int offset) const
335{
336 BSLS_ASSERT_SAFE(!specInOut->empty());
337
338 if (t_CHAR('z') == specInOut->front()) {
339 *outIt = formatDefault(*outIt, offset);
340 specInOut->remove_prefix(1);
341
342 return true; // RETURN
343 }
344
345 return false;
346}
347
348template <class t_CHAR>
349inline
351{
352 enum { k_Z_TZ_WIDTH = 1,
353 k_COLON_TZ_WIDTH = 6,
354 k_NO_COLON_TZ_WIDTH = 5 };
355
356 int totalNumTimeZones = d_numDefaultTimeZones + d_numIso8601TimeZones;
357
358 return isTimeZoneZ(offset) ? k_Z_TZ_WIDTH * totalNumTimeZones
359 : d_colon ? k_COLON_TZ_WIDTH * totalNumTimeZones
360 : d_noColon ? k_NO_COLON_TZ_WIDTH * totalNumTimeZones
361
362 : k_NO_COLON_TZ_WIDTH * d_numDefaultTimeZones +
363 k_COLON_TZ_WIDTH * d_numIso8601TimeZones;
364}
365
366} // close package namespace
367
368
369#endif
370
371// ----------------------------------------------------------------------------
372// Copyright 2026 Bloomberg Finance L.P.
373//
374// Licensed under the Apache License, Version 2.0 (the "License");
375// you may not use this file except in compliance with the License.
376// You may obtain a copy of the License at
377//
378// http://www.apache.org/licenses/LICENSE-2.0
379//
380// Unless required by applicable law or agreed to in writing, software
381// distributed under the License is distributed on an "AS IS" BASIS,
382// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
383// See the License for the specific language governing permissions and
384// limitations under the License.
385// ----------------------------- END-OF-FILE ----------------------------------
386
387/** @} */
388/** @} */
389/** @} */
Definition bdlt_formatutil.h:87
Definition bdlt_timezoneformatter.h:89
BSLS_KEYWORD_CONSTEXPR_CPP20 bool parseNextModifier(StringView *specInOut)
Definition bdlt_timezoneformatter.h:252
BSLS_KEYWORD_CONSTEXPR_CPP20 TimeZoneFormatter()
Create an object in its default initial state.
Definition bdlt_timezoneformatter.h:227
int totalWidth(int offset) const
Definition bdlt_timezoneformatter.h:350
void postprocess(const bslfmt::FormatSpecificationParser< t_CHAR > &spec)
Definition bdlt_timezoneformatter.h:299
t_ITERATOR formatDefault(t_ITERATOR out, int offset) const
Definition bdlt_timezoneformatter.h:314
t_ITERATOR formatIso8601(t_ITERATOR out, int offset) const
Definition bdlt_timezoneformatter.h:323
BSLS_KEYWORD_CONSTEXPR_CPP20 bool parseNextSpecifier(StringView *specInOut)
Definition bdlt_timezoneformatter.h:283
BSLS_KEYWORD_CONSTEXPR_CPP20 void parseDefault()
Parse a time zone that will be formatted in default mode.
Definition bdlt_timezoneformatter.h:238
BSLS_KEYWORD_CONSTEXPR_CPP20 int extraSections() const
Definition bdlt_timezoneformatter.h:306
bool formatNextSpecifier(bsl::basic_string_view< t_CHAR > *specInOut, t_ITERATOR *outIt, int offset) const
Definition bdlt_timezoneformatter.h:331
BSLS_KEYWORD_CONSTEXPR_CPP20 void parseIso8601()
Parse a time zone that will be formatted in Iso8601 mode.
Definition bdlt_timezoneformatter.h:245
BSLS_KEYWORD_CONSTEXPR_CPP14 const_reference front() const
Definition bslstl_stringview.h:1966
BSLS_KEYWORD_CONSTEXPR_CPP14 void remove_prefix(size_type numChars)
Definition bslstl_stringview.h:1800
BSLS_KEYWORD_CONSTEXPR bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this view has length 0, and false otherwise.
Definition bslstl_stringview.h:1931
Definition bslfmt_formatspecificationparser.h:151
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_THROW(X)
Definition bsls_exceptionutil.h:374
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR_CPP20
Definition bsls_keyword.h:645
Definition bbldc_basicisma30360.h:112
Definition bslmf_issame.h:146