BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_formatdoc.h
Go to the documentation of this file.
1
/// @file bdlt_formatdoc.h
2
///
3
/// The content of this file has been pre-processed for Doxygen.
4
///
5
6
7
// bdlt_formatdoc.h -*-C++-*-
8
#ifndef INCLUDED_BDLT_FORMATDOC
9
#define INCLUDED_BDLT_FORMATDOC
10
11
#include <
bsls_ident.h
>
12
BSLS_IDENT
(
"$Id: $"
)
13
14
/// @defgroup bdlt_formatdoc bdlt_formatdoc
15
/// @brief Provide documentation for `bsl::format` of bdlt value types
16
/// @addtogroup bdl
17
/// @{
18
/// @addtogroup bdlt
19
/// @{
20
/// @addtogroup bdlt_formatdoc
21
/// @{
22
///
23
/// <h1> Outline </h1>
24
/// * <a href="#bdlt_formatdoc-purpose"> Purpose</a>
25
/// * <a href="#bdlt_formatdoc-description"> Description </a>
26
/// * <a href="#bdlt_formatdoc-usage"> Usage </a>
27
///
28
/// # Purpose {#bdlt_formatdoc-purpose}
29
/// Provide documentation for `bsl::format` of bdlt value types
30
///
31
/// # Description {#bdlt_formatdoc-description}
32
/// This component provides documentation and a usage example
33
/// demonstrating the behavior and features of `bsl::format` as applied to bdlt
34
/// value types.
35
///
36
///@SEE ALSO: bdlt_dateformatter, bdlt_datetzformatter, bdlt_timeformatter,
37
/// bdlt_timetzformatter, bdlt_datetimeformatter, bdlt_datetimetzformatter
38
///
39
/// `bsl::format` is a powerful formatting function that can be used to format,
40
/// among other things, `bdlt` value types. The formatting of types is
41
/// controlled by a set of formatting options that are specified in the format
42
/// string passed to `bsl::format` in a way very similar to how the format
43
/// string in `printf` formats types being printed. While `printf` can only
44
/// format a few hard-coded types, `bsl::format` can be extended to format more
45
/// sophisticated types, and all `bdlt` value types are supported with such
46
/// extensions.
47
///
48
/// The format string passed to `bsl::format` can contain any number of `%`
49
/// sequences, which are replaced by the formatted value of the corresponding
50
/// argument, or part of the corresponding argument. Each type has a specific,
51
/// limited set of `%`-sequences that can be used with it, and using any other
52
/// `%`-sequence is an error. The formatting options for `bdlt` value types
53
/// are described both in this component and in the component documentation of
54
/// each `bdlt` value type.
55
///
56
/// The following is a list of `%`-sequences supported for `bdlt` value types,
57
/// though not all the sequences are supported for all the types. Many of the
58
/// sequences are copied from `std::format`s support for
59
/// `std::chrono::duration`, see
60
/// https://en.cppreference.com/w/cpp/chrono/duration.html, but some other ones
61
/// are specific to `bdlt` value types.
62
///
63
/// Just like for all other `bsl::format` errors, errors will be detected at
64
/// compile time in C++20 and later, but in C++17 and earlier, errors will
65
/// result in an exception being thrown at run time.
66
///
67
/// Literal `%` sequences that just output one fixed character are:
68
/// * Literal: `"%%"` - outputs (`"%"`)
69
/// * Literal: `"%n"` - outputs newline (`"\n"`)
70
/// * Literal: `"%t"` - outputs tab (`"\t"`)
71
///
72
/// All `%` sequences supported for `bdlt` value types are:
73
/// * Date alone: `"%D"` same as `"{:%d%h%Y}"`
74
/// * Date alone: `"%F"` Iso8601, like `"{:%Y-%m-%d}"`
75
/// * Time alone: `"%T"`, same as `"{:%H:%M:%S}"`, 6 digit fraction
76
/// * Time zone: `"%z"`, 2 digit hour and 2-digit minute offset from UTC, with
77
/// or without a colon separating hours and minutes
78
/// * Year: `"%Y"` (4-digit), `"%y"` (2-digit)
79
/// * Century: `"%C"` (2-digit)
80
/// * Numeric month: `"%m"` (2-digit)
81
/// * Abbreviation of month: (always 3-letter upper case): `"%b"` or `"%h"`
82
/// * Day of month: (always 2-digit) `"%d"` (`0`-padded), `"%e"` (space-padded)
83
///
84
/// * Abbreviated day of week: `"%a"` (3 letter upper case)
85
/// * Day of week: `"%u"` (numeric 1-7, Monday is 1)
86
/// * Day of week: `"%w"` (numeric 0-6, Sunday is 0)
87
/// * Day of year: `"%j"` (numeric 3-digit)
88
/// * Hour: `"%H"` (2 digit) `00` - `24`
89
/// * Hour: `"%I"` (2 digit) `01` - `12`
90
/// * AM/PM: `"%p"` - `AM` or `PM`
91
/// * Minute: `"%M"` (2 digits) `00` - `59`
92
/// * Second: `"%S"` (2 digits `00` - `59` + `.` + fraction)
93
///
94
/// * Composite: `"{}"` formats the value as if streamed by `<<`, default 6
95
/// digit precision for seconds, no `:` between hours and minutes of any
96
/// time zone
97
/// * Composite: `"%i"` for bdlt value types formats the entire value like
98
/// Iso8601, were precision defaults to 3 digit and there's a `:` between
99
/// hours and minutes of any time zone.
100
///
101
/// It is an error to specify a `%`-sequence that does not apply to the type
102
/// being formatted, or a sub-type of it -- for example, all sequences that
103
/// apply to `Date` or `Time` can be used on a `Datetime` object.
104
///
105
/// `bsl::format` strings of bdlt value types take the form of either `"{}"` or
106
/// `"{:[padding][precision][bdlt-modifiers]["%"-sequences]}"` where all fields
107
/// surrounded by `"[]"`s are optional. While in `printf` the modifiers of a
108
/// `%`-sequence occur between the `%` and the type specifier, in
109
/// `bsl::format` the modifiers occur between the first `:` and the first `%`
110
/// (if any).
111
///
112
/// * The `padding` takes the form of
113
/// `<pad character><alignment command><width>` where
114
/// - `<pad character>` is the character to pad with, which defaults to space
115
/// if omitted, and must be a single character
116
/// - `<alignment command>` is one of: `<` for left, `>` for right, and `^`
117
/// for centered, and
118
/// - `<width>` is the minimum total width of the padded value output
119
/// * The `precision` is indicated by a `.` followed by an integral number of
120
/// digits.
121
/// * The `bdlt`-modifiers are specific to `bdlt` value types. One affects the
122
/// output of seconds, and three affect the output of time zones:
123
/// - `,` decimal between integral seconds and fraction is a comma instead
124
/// of a period
125
/// - `:` separate hours and minutes in time zone with `:`
126
/// - `_` suppress `:` between hours and minutes in time zone
127
/// - `Z` if time zone offset is 0, display it as `Z`
128
/// Characters after the first `%` that are not part of a valid `%`-sequence
129
/// are copied to output without modification. The modifiers must come in the
130
/// order `"<padding><precision><bdlt-specific modifiers>"`. The bdlt-specific
131
/// modifiers must come last, but among themselves, may occur in any order.
132
///
133
/// ## Usage {#bdlt_formatdoc-usage}
134
///
135
///
136
/// First, include the files necessary to declare the `bdlt` value types that we
137
/// will use and their formatters:
138
/// @code
139
/// #include <bdlt_date.h>
140
/// #include <bdlt_dateformatter.h>
141
/// #include <bdlt_datetimetz.h>
142
/// #include <bdlt_datetimetzformatter.h>
143
/// #include <bdlt_timetz.h>
144
/// #include <bdlt_timetzformatter.h>
145
/// @endcode
146
/// Next, create a form of assertion macro that will compare a literal string to
147
/// the result of an expression and output the value of the expression if they
148
/// don't match (continuations elided in .h to suppress compiler errors):
149
/// @code
150
/// #undef U_EQ
151
/// #define U_EQ(expectedString, rhsExpr) do {
152
/// const bsl::string& s = rhsExpr;
153
/// if (expectedString != s) {
154
/// cout << "Error:(" << __LINE__ << "): " <<
155
/// "\"" expectedString "\"" <<
156
/// " != " << "(" #rhsExpr ": \"" << s << "\")" << endl;
157
/// assert(0);
158
/// }
159
/// } while (false)
160
/// @endcode
161
/// Declare a few variables of bdlt value types:
162
/// @code
163
/// const bdlt::Time TIME(14, 32, 17, 123, 456);
164
/// const bdlt::TimeTz TIME_TZ(TIME, 300);
165
/// const bdlt::Date DATE(1776, 7, 4);
166
/// const bdlt::Datetime DATETIME(DATE, TIME);
167
/// const bdlt::DatetimeTz DATETIME_TZ(DATETIME, 0);
168
///
169
/// bsl::ostringstream oss;
170
/// @endcode
171
/// The simplest way to format a bdlt type using `bsl::format` is to use the
172
/// "{}" format string. In this case, `bsl::format` will produce the same
173
/// output as streaming that value into a `bsl::ostream`. If more control is
174
/// required, we can use `%`-sequences to select which parts of the value are
175
/// formatted, in which order, and to add any text to separate them.
176
///
177
/// A `Time` can also be formatted with `"%T"`:
178
/// @code
179
/// oss.str(""); oss << TIME;
180
/// U_EQ("14:32:17.123456", oss.str());
181
/// U_EQ("14:32:17.123456", bsl::format("{}", TIME));
182
/// U_EQ("14:32:17.123456", bsl::format("{:%T}", TIME));
183
/// U_EQ("14:32:17.123456 -- boo!", bsl::format("{:%T -- boo!}", TIME));
184
/// @endcode
185
/// A `Date` can be formatted with `"%D"`:
186
/// @code
187
/// oss.str(""); oss << DATE;
188
/// U_EQ("04JUL1776", oss.str());
189
/// U_EQ("04JUL1776", bsl::format("{}", DATE));
190
/// U_EQ("04JUL1776", bsl::format("{:%D}", DATE));
191
/// @endcode
192
/// The `format` function can print multiple variables in a single call:
193
/// @code
194
/// U_EQ("04JUL1776 .. 14:32:17.123456", bsl::format("{} .. {}", DATE, TIME));
195
/// @endcode
196
/// In bdlt formatting, any `%`-sequence that works on a type also works on
197
/// other types that contain that type, and time zones can be formatted as
198
/// `"%z"`.
199
/// @code
200
/// oss.str(""); oss << TIME_TZ;
201
/// U_EQ("14:32:17.123456+0500", oss.str());
202
/// U_EQ("14:32:17.123456+0500", bsl::format("{}", TIME_TZ));
203
/// U_EQ("14:32:17.123456+0500", bsl::format("{:%T%z}", TIME_TZ));
204
///
205
/// oss.str(""); oss << DATETIME;
206
/// U_EQ("04JUL1776_14:32:17.123456", oss.str());
207
/// U_EQ("04JUL1776_14:32:17.123456", bsl::format("{}", DATETIME));
208
/// U_EQ("04JUL1776_14:32:17.123456", bsl::format("{:%D_%T}", DATETIME));
209
///
210
/// oss.str(""); oss << DATETIME_TZ;
211
/// U_EQ("04JUL1776_14:32:17.123456+0000", oss.str());
212
/// U_EQ("04JUL1776_14:32:17.123456+0000", bsl::format("{}", DATETIME_TZ));
213
/// U_EQ("04JUL1776_14:32:17.123456+0000",
214
/// bsl::format("{:%D_%T%z}", DATETIME_TZ));
215
/// @endcode
216
/// `%`-sequences can appear any number of times:
217
/// @code
218
/// U_EQ("04JUL1776 == 04JUL1776 == 04JUL1776!!!",
219
/// bsl::format("{:%D == %D == %D!!!}", DATETIME_TZ));
220
/// @endcode
221
/// After the first `:` and before the first `%`, if any, one can indicate
222
/// padding with "<pad char><alignment char><width>" where:
223
/// * <pad char> -- the character to pad with, (space if omitted)
224
/// * <alignment char> -- `<` for left, `>` for right, `^` for centered
225
/// * <width> -- minimum total width of the value output
226
///
227
/// @code
228
/// U_EQ("14:32:17.123456 ", bsl::format("{:<25%T}", TIME));
229
/// U_EQ("*****14:32:17.123456*****", bsl::format("{:*^25%T}", TIME));
230
/// U_EQ("++++++++++14:32:17.123456", bsl::format("{:+>25}", TIME));
231
/// @endcode
232
/// After the padding specification (if any) and before the first `%` (if any),
233
/// one can indicate the `precision`, the number of digits of fractional
234
/// seconds. This is specified as a period followed by a non-negative integral
235
/// number of digits to occur after the decimal. If the precision is 0, no
236
/// decimal will be shown:
237
/// @code
238
/// U_EQ("14:32:17.12", bsl::format("{:.2}", TIME));
239
/// U_EQ("14:32:17.12", bsl::format("{:.2%T}", TIME));
240
/// U_EQ("14:32:17", bsl::format("{:.0}", TIME));
241
/// U_EQ("14:32:17.123456000000000", bsl::format("{:.15}", TIME));
242
/// @endcode
243
/// After the padding and/or precision specifiers (if any), when formatting
244
/// `bdlt` types, one can provide modifiers that change the behavior of the
245
/// correlating `%`-sequences. Currently, there is one modifier that affects
246
/// the formatting of fractional seconds and three modifiers that affect time
247
/// zone formatting:
248
/// * `,` the decimal in `seconds` is to be a comma rather than a period
249
/// * `:` always separate time zone hours and minutes by colon
250
/// * `_` never separate time zone hours and minutes by colon
251
/// * `Z` if the time zone offset is zero, print it as `Z`, otherwise, the `Z`
252
/// modifier is ignored
253
///
254
/// @code
255
/// U_EQ("14:32:17.12", bsl::format("{:.2%T}", TIME_TZ));
256
/// U_EQ("14:32:17,12", bsl::format("{:.2,%T}", TIME_TZ)); // comma
257
/// U_EQ("14:32:17+05:00", bsl::format("{:.0:}", TIME_TZ)); // colon
258
/// U_EQ("14:32:17+0500", bsl::format("{:.0}", TIME_TZ)); // default tz
259
/// U_EQ("14:32:17+0500", bsl::format("{:.0Z}", TIME_TZ)); // `Z` ignored
260
///
261
/// U_EQ("14:32:17+00:00", bsl::format("{:.0:%T%z}", DATETIME_TZ)); // no `Z`
262
/// U_EQ("14:32:17Z", bsl::format("{:.0:Z%T%z}", DATETIME_TZ)); // `Z`
263
/// @endcode
264
/// Errors in the format string such as:
265
/// * using a `%`-sequence that is not supported for that type
266
/// * Specifying padding, precision, and bdlt-modifiers in the wrong order
267
/// (among themselves, bdlt-modifiers may appear in any order)
268
/// * Specifying bdlt-modifiers that are inapplicable to the type
269
/// * any characters between the first `:` and the first `%`-sequence that are
270
/// not part of a valid padding specification, precision, or bdlt-modifier
271
/// will cause a compilation error in C++20 or later, or cause a
272
/// `bsl::format_error` exception to be thrown at runtime in C++17 or earlier.
273
///
274
/// Padding width and precision can be passed through the argument list at run
275
/// time:
276
/// @code
277
/// U_EQ("+++14:32:17,12+++", bsl::format("{:+^{}.{},}", TIME, 17, 2));
278
/// @endcode
279
/// `"%i"` - format the whole value according to the same format as
280
/// `bdlt::Iso8601::generate`. Iso8601 formatting differs from formatting the
281
/// value with the "{}" format string in several ways:
282
/// * precision defaults to 3 rather than 6
283
/// * time zones default to having a `:` between hours and minutes, rather than
284
/// no separator
285
/// * `Date`s are done in the format "YYYY-MM-DD" rather than "DDMMMYYYY", so
286
/// that when sorted, they will sort chronologically
287
/// * the date and time in a `Datetime` are separated by `T` rather than `_`
288
///
289
/// `"%i"`-sequences are supported for all bdlt value types:
290
/// @code
291
/// U_EQ("14:32:17.123", bsl::format("{:%i}", TIME));
292
/// U_EQ("14:32:17.123+05:00", bsl::format("{:%i}", TIME_TZ));
293
/// U_EQ("1776-07-04", bsl::format("{:%i}", DATE));
294
/// U_EQ("1776-07-04T14:32:17.123+00:00", bsl::format("{:%i}", DATETIME_TZ));
295
/// @endcode
296
/// The `_` bdlt-modifier can be used to suppress the colon in the time zone:
297
/// @code
298
/// U_EQ("14:32:17.123+0500", bsl::format("{:_%i}", TIME_TZ));
299
/// @endcode
300
/// `bsl::format` does not support showing names or abbreviations of time zones,
301
/// they are always listed as numerical hours & minutes.
302
///
303
/// Using various `%`-sequences, one can arrange different pieces of the value
304
/// in any desired order. For example, it is possible to replicate the `"%i"`
305
/// format using other sequences:
306
/// @code
307
/// U_EQ("1776-07-04T14:32:17.123+00:00", bsl::format("{:%i}", DATETIME_TZ));
308
/// U_EQ("1776-07-04T14:32:17.123+00:00",
309
/// bsl::format("{:.3:%FT%T%z}", DATETIME_TZ));
310
/// U_EQ("1776-07-04T14:32:17.123+00:00",
311
/// bsl::format("{:.3:%Y-%m-%dT%H:%M:%S%z}", DATETIME_TZ));
312
/// @endcode
313
/// Other `%`-sequences can be used to arrange the value in other ways, or to
314
/// achieve specific output formats. For example:
315
/// @code
316
/// U_EQ("THU, JUL 04, 02:32:17 PM, 1776",
317
/// bsl::format("{:.0%a, %b %d, %I:%M:%S %p, %Y}", DATETIME));
318
///
319
/// U_EQ("JUL 4 1776", bsl::format("{:%h %e %C%y}", DATE));
320
///
321
/// const bdlt::Date SUNDAY(1776, 6, 30);
322
///
323
/// U_EQ("Sunday %a: SUN, Sunday %u: 7, Sunday %w: 0", bsl::format(
324
/// "Sunday %a: {:%a, Sunday %%u: %u, Sunday %%w: %w}", SUNDAY));
325
///
326
/// U_EQ("Day of year Sunday: 182, Thursday: 186", bsl::format(
327
/// "Day of year Sunday: {:%j}, Thursday: {:%j}", SUNDAY, DATE));
328
/// @endcode
329
/// @}
330
/** @} */
331
/** @} */
332
333
/** @addtogroup bdl
334
* @{
335
*/
336
/** @addtogroup bdlt
337
* @{
338
*/
339
/** @addtogroup bdlt_formatdoc
340
* @{
341
*/
342
343
#include <bdlscm_version.h>
344
345
#endif
346
347
// ----------------------------------------------------------------------------
348
// Copyright 2026 Bloomberg Finance L.P.
349
//
350
// Licensed under the Apache License, Version 2.0 (the "License");
351
// you may not use this file except in compliance with the License.
352
// You may obtain a copy of the License at
353
//
354
// http://www.apache.org/licenses/LICENSE-2.0
355
//
356
// Unless required by applicable law or agreed to in writing, software
357
// distributed under the License is distributed on an "AS IS" BASIS,
358
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
359
// See the License for the specific language governing permissions and
360
// limitations under the License.
361
// ----------------------------- END-OF-FILE ----------------------------------
362
363
/** @} */
364
/** @} */
365
/** @} */
bsls_ident.h
BSLS_IDENT
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition
bsls_ident.h:238
doxygen_input
bde
groups
bdl
bdlt
bdlt_formatdoc.h
Generated by
1.9.8