Boost.Locale
Numbers, Time and Currency formatting and parsing

All formatting and parsing is performed via the standard I/O streams. Each of the above information types is represented as a number. The formatting information is set using iostream manipulators. All manipulators are placed in the boost::locale::as namespace.

For example:

cout << as::currency << 123.45 << endl;
// display 123.45 in local currency representation.
cin >> as::currency >> x ;
// Parse currency representation and store it in x

There is a special manipulator as::posix that "unsets" locale-specific settings and returns them to the default iostream formatting and parsing methods. Please note, such formats may still be localized by the default std::num_put and std::num_get facets.

Numbers and number manipulators

Here are the manipulators for number formatting:

  • as::number – format number according to local specifications, it takes into account various std::ios_base flags like scientific format and precision.
  • as::percent – format number as "percent" format. For example:
    cout << as::percent << 0.25 <<endl;
    Would create an output that may look like this:
        25%

  • as::spellout – spell the number. For example, under the English locale, 103 may be displayed as "one hundred three". Note: not all locales provide rules for spelling numbers. In such a case the number would be displayed in decimal format.
  • as::ordinal – display an order-of element. For example "2" would be displayed as "2nd" under the English locale. As in the above case, not all locales provide ordinal rules.

Currency formatting

These are the manipulators for currency formatting:

  • as::currency – set the format to currency mode.
  • as::currency_iso – change the currency format to international, like "USD" instead of "$". This flag is supported when using ICU 4.2 and above.
  • as::currency_national – change currency format to national, like "$".
  • as::currency_default – return to the default (national) currency format.
Note
as::currency_XYZ manipulators have no effect on general formatting, only on the currency format. You must use both currency and number manipulators to use a non-default format.

Date and Time formatting

Dates and times are represented as POSIX time. When date-time formatting is turned on in the iostream, each number is treated as a POSIX time. The number may be an integer or a double.

There are four major manipulators for Date and Time formatting:

  • as::date – date only
  • as::time – time only
  • as::datetime – both date and time
  • as::ftime – parameterized manipulator that allows specification of time in the format that is used in the strftime function. Note: not all formatting flags of strftime are supported.

For example:

time_t now=time(0);
cout << "Today is "<< as::date << now << " and tomorrow is " << now+24*3600 << endl;
cout << "Current time is "<< as::time << now << endl;
cout << "The current weekday is "<< as::ftime("%A") << now << endl;

More fine-grained control of date-time formatting is also available:

  • as::time_default , as::time_short , as::time_medium , as::time_long , as::time_full – change time formatting.
  • as::date_default , as::date_short , as::date_medium , as::date_long , as::date_full – change date formatting.

These manipulators, when used together with the as::date, as::time, or as::datetime manipulators, change the date-time representation. The default format is medium.

By default, the date and time are shown in the local time zone. This behavior may be changed with the following manipulators:

  • as::gmt – display date and time in GMT.
  • as::local_time – display in local time zone (default).
  • as::time_zone – parameterized manipulator that sets the time-zone ID for date-time formatting and parsing. It takes a string parameter that represents the time zone ID.

For example:

double now=time(0);
cout << as::datetime << as::local_time << "Local time is: "<< now << endl;
cout << as::gmt << "GMT Time is: "<< now <<endl;
cout << as::time_zone("EST") << "Eastern Standard Time is: "<< now <<endl;

There is a list of supported strftime flags by ICU backend:

  • %a – Abbreviated weekday (Sun.)
  • %A – Full weekday (Sunday)
  • %b – Abbreviated month (Jan.)
  • %B – Full month (January)
  • %c – Locale date-time format. Note: prefer using as::datetime
  • %d – Day of Month [01,31]
  • %e – Day of Month [1,31]
  • %h – Same as %b
  • %H – 24 clock hour [00,23]
  • %I – 12 clock hour [01,12]
  • %j – Day of year [1,366]
  • %m – Month [01,12]
  • %M – Minute [00,59]
  • %n – New Line
  • %p – AM/PM in locale representation
  • %r – Time with AM/PM, same as %I:%M:%S %p
  • %R – Same as %H:%M
  • %S – Second [00,61]
  • %t – Tab character
  • %T – Same as %H:%M:%S
  • %x – Local date representation. Note: prefer using as::date
  • %X – Local time representation. Note: prefer using as::time
  • %y – Year [00,99]
  • %Y – 4 digits year. (2009)
  • %Z – Time Zone
  • %% – Percent symbol

Unsupported strftime flags are: %C , %u , %U , %V , %w , %W . Also, the O and E modifiers are not supported.

General recommendations

  • Prefer using generic date-time manipulators rather than specifying the full format using as::ftime.
  • Remember that current calendars may be not Gregorian.

Internals

Formatting information is stored in a stream class by using the xalloc, pword, and register_callback member functions of std::ios_base . All the information is stored and managed using a special object bound to iostream, and the manipulators just change its state.

When a number is written to or read from the stream, a custom Boost.Locale facet accesses the object and checks the required formatting information. Then it creates a special object that actually formats the number and caches it in the iostream. The next time a number is written to the stream, the same formatter would be used unless some flags had changed and formatter object is invalid.