BDE 4.14.0 Production release
Loading...
Searching...
No Matches
baltzo_timezoneutil.h
Go to the documentation of this file.
1/// @file baltzo_timezoneutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baltzo_timezoneutil.h -*-C++-*-
8#ifndef INCLUDED_BALTZO_TIMEZONEUTIL
9#define INCLUDED_BALTZO_TIMEZONEUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baltzo_timezoneutil baltzo_timezoneutil
15/// @brief Provide utilities for converting times among different time zones.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baltzo
19/// @{
20/// @addtogroup baltzo_timezoneutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baltzo_timezoneutil-purpose"> Purpose</a>
25/// * <a href="#baltzo_timezoneutil-classes"> Classes </a>
26/// * <a href="#baltzo_timezoneutil-description"> Description </a>
27/// * <a href="#baltzo_timezoneutil-valid-ambiguous-and-invalid-local-time-values"> Valid, Ambiguous, and Invalid Local-Time Values </a>
28/// * <a href="#baltzo_timezoneutil-daylight-saving-time-policies-and-disambiguation"> Daylight-Saving Time (DST) Policies and Disambiguation </a>
29/// * <a href="#baltzo_timezoneutil-result-of-convertlocaltoutc-for-various-baltzo-dstpolicy-values"> Result of convertLocalToUtc for Various baltzo::DstPolicy Values </a>
30/// * <a href="#baltzo_timezoneutil-thread-safety"> Thread Safety </a>
31/// * <a href="#baltzo_timezoneutil-usage"> Usage </a>
32/// * <a href="#baltzo_timezoneutil-example-1-converting-a-utc-time-to-a-local-time"> Example 1: Converting a UTC time to a Local Time </a>
33/// * <a href="#baltzo_timezoneutil-example-2-converting-a-local-time-in-one-time-zone-to-another-time-zone"> Example 2: Converting a Local Time in One Time Zone to Another Time Zone </a>
34/// * <a href="#baltzo_timezoneutil-example-3-initializing-a-local-time"> Example 3: Initializing a Local Time </a>
35/// * <a href="#baltzo_timezoneutil-example-4-obtaining-information-about-a-time-value"> Example 4: Obtaining Information About a Time Value </a>
36///
37/// # Purpose {#baltzo_timezoneutil-purpose}
38/// Provide utilities for converting times among different time zones.
39///
40/// # Classes {#baltzo_timezoneutil-classes}
41///
42/// - baltzo::TimeZoneUtil: utilities for converting local time values
43///
44/// @see baltzo_localdatetime, baltzo_zoneinfo, baltzo_defaultzoneinfocache
45///
46/// # Description {#baltzo_timezoneutil-description}
47/// This component provides a namespace, `baltzo::TimeZoneUtil`,
48/// containing utility functions for converting time values to and from their
49/// corresponding local time representations in (possibly) different time zones.
50/// The primary methods provided include:
51/// * `convertLocalToLocalTime` and `convertUtcToLocalTime`, for converting a
52/// time to the corresponding local-time value in some time zone;
53/// * `convertLocalToUtc`, for converting a local-time value into the
54/// corresponding UTC time value;
55/// * `initLocalTime`, for initializing a local-time value.
56/// Additionally, the `loadLocalTimePeriod` and `loadLocalTimePeriodForUtc`
57/// methods enable clients to obtain information about a time value, such as
58/// whether the provided time is a daylight-saving time value. Finally note
59/// that, all of the functions in this utility component make use of a
60/// process-wide cache of time-zone information (see
61/// @ref baltzo_defaultzoneinfocache ).
62///
63/// ## Valid, Ambiguous, and Invalid Local-Time Values {#baltzo_timezoneutil-valid-ambiguous-and-invalid-local-time-values}
64///
65///
66/// There are intervals around each daylight-saving time transition where a
67/// `bdlt::Datetime` object holding a local time may not describe a valid or
68/// unique clock time in the local time zone (see @ref baltzo_localtimevalidity ).
69/// When interpreting a local-time value represented using a `bdlt::Datetime`
70/// object with respect to a given time zone, there are three possible
71/// scenarios:
72///
73/// 1. The local time is *valid* and *unique*: The local time representation is
74/// valid, and unique within the time zone (the most likely scenario). For
75/// example, in New York at "Aug 31, 2010 12:00AM", DST was in effect and the
76/// local-time offset from UTC was -4 hours.
77/// 2. The local time is *valid*, but *ambiguous*: The local time representation
78/// is valid, but could correctly be interpreted as either of two possible
79/// times, as may happen around a daylight-saving time transition where the
80/// local-time offset from UTC increases (e.g., in the United States local
81/// time "falls back" by an hour in the fall). Thus, a local time within
82/// such a transition period occurs twice, and is ambiguous without
83/// additional information. For example, in New York, daylight-saving time
84/// was in effect until "Nov 7, 2010 2:00AM" when clocks were set back by an
85/// hour; therefore, the time "Nov 7, 2010 1:30AM" occurred twice, and that
86/// description (as represented in a `bdlt::Datetime` object) could refer to
87/// either of those two times.
88/// 3. The local time is **invalid**: The local-time representation doesn't
89/// correspond to a valid time within the given time zone, as may happen
90/// around a daylight-saving time transition where the offset from UTC
91/// decreases (e.g., in the United States local time "springs forward" by an
92/// hour in the spring). Thus, local times that are skipped during such a
93/// transition are invalid. For example, in New York, DST was in effect
94/// starting "Mar 14, 2010 2:00AM" when clocks are set forward an hour;
95/// therefore, the local time "Mar 14, 2010 2:30AM" never occurs.
96///
97/// Note that the functions provided in this component guarantee a graceful
98/// handling of all three scenarios. Ambiguity and invalidity, when they arise,
99/// are resolved according to a user-supplied daylight-saving time policy that
100/// describes how to interpret the input time values (see @ref baltzo_dstpolicy ).
101///
102/// ### Daylight-Saving Time (DST) Policies and Disambiguation {#baltzo_timezoneutil-daylight-saving-time-policies-and-disambiguation}
103///
104///
105/// The `baltzo::TimeZoneUtil` methods that take, as input, a `bdlt::Datetime`
106/// object representing a local time (i.e., a local-time value without a UTC
107/// offset) also accept an optional `baltzo::DstPolicy::Enum`. This (optional)
108/// argument policy allows clients to specify how they would like the operation
109/// to interpret the input value (as such a value may be ambiguous or invalid
110/// within the indicated time zone -- see above). Clients are, however,
111/// encouraged to use the default policy, `e_UNSPECIFIED`, unless there is some
112/// specific reason they require a different option.
113///
114/// Three enumerated `baltzo::DstPolicy` values are supported:
115///
116/// 1. `e_UNSPECIFIED` (default)
117/// - The client does not explicitly indicate whether the associated input
118/// time represents a daylight-saving time value, and the operation will
119/// determine how to interpret the time solely based on the input itself.
120/// If the input value is *valid* and *unique*, the operation will use its
121/// (unique) corresponding UTC value. If the input is either *ambiguous*
122/// or *invalid*, the operation will use the later of two potential
123/// interpretations of the input (determined, e.g., by applying the
124/// standard and daylight-saving time UTC offsets to the input). For
125/// *invalid* times, this choice reflects the assumption that the user most
126/// likely forgot to adjust their clock. For *ambiguous* times, this
127/// choice is arbitrary (but is consistent with common implementations of
128/// the C standard library).
129/// 2. `e_STANDARD`
130/// - Indicates that the operation should treat the associated input time
131/// value as a standard time, using the UTC value computed by applying the
132/// standard-time UTC offset. Note that the standard-time UTC offset is
133/// used even when the input time value is (unambiguously) *not* a standard
134/// time, which would result in a UTC time that does not correspond to a
135/// standard time within the time zone.
136/// 3. `e_DST`
137/// - Indicates that the operation should treat the associated input time
138/// value as a daylight-saving time, using the UTC value computed by
139/// applying the daylight-saving time UTC offset. Note that the
140/// daylight-saving-time UTC offset is used even when the input time value
141/// is (unambiguously) *not* a daylight-saving time, which would result in
142/// a UTC time that does not correspond to a daylight-saving time within
143/// the time zone.
144///
145/// Note that these policies are intended to reflect the behavior of the C
146/// standard library function `mktime` and its interpretation of the `tm_isdst`
147/// value of the supplied `tm` structure. The behavior for the "unspecified"
148/// policy, however, is not strictly defined by either the ISO or POSIX
149/// standards, and varies among implementations.
150///
151/// ### Result of convertLocalToUtc for Various baltzo::DstPolicy Values {#baltzo_timezoneutil-result-of-convertlocaltoutc-for-various-baltzo-dstpolicy-values}
152///
153///
154/// The following table summarizes the effect that the different
155/// `baltzo::DstPolicy` values have on a call to `convertLocalToUtc` for several
156/// possible time values in New York. Note that standard local time in New York
157/// is UTC-5:00, and daylight-saving local time there is UTC-4:00.
158/// @code
159/// Result format: UTC 'bdlt::Time' & corresponding local 'bdlt::TimeTz'.
160/// ,--------------------------------------------------------------------------.
161/// | Input in New York | 'baltzo::DstPolicy::Enum' |
162/// | Local Time |-----------------------------------------------------|
163/// | (bdlt::Datetime) | *_UNSPECIFIED | *_STANDARD | *_DST |
164/// |==========================================================================|
165/// | Jan 1, 2010 01:30 | 06:30:00 UTC | 06:30:00 UTC | 05:30:00 UTC |
166/// | (standard time) | (01:30:00-5:00) | (01:30:00-5:00) | (00:30:00-5:00) |
167/// | | | [1] | [2] |
168/// |--------------------|-----------------------------------------------------|
169/// | Mar 14, 2010 02:30 | 07:30:00 UTC | 07:30:00 UTC | 06:30:00 UTC |
170/// | (invalid) | (03:30:00-4:00) | (03:30:00-4:00) | (01:30:00-5:00) |
171/// | | [3] | [4] | [5] |
172/// |--------------------|-----------------------------------------------------|
173/// | Apr 1, 2010 01:30 | 05:30:00 UTC | 06:30:00 UTC | 05:30:00 UTC |
174/// | (daylight-saving) | (01:30:00-4:00) | (02:30:00-4:00) | (01:30:00-4:00) |
175/// | | | [6] | [7] |
176/// |--------------------|-----------------------------------------------------|
177/// | Nov 7, 2010 01:30 | 06:30:00 UTC | 06:30:00 UTC | 05:30:00 UTC |
178/// | (ambiguous) | (01:30:00-5:00) | (01:30:00-5:00) | (01:30:00-4:00) |
179/// | | [8] | | |
180/// `--------------------------------------------------------------------------'
181/// @endcode
182///
183/// 1. "Jan 1, 2010 01:30" is unambiguously a standard time value. The result
184/// is simply the corresponding UTC time "Jan 1, 2010 06:30 UTC".
185/// 2. "Jan 1, 2010 01:30" is unambiguously a standard time value, so the
186/// supplied policy, `e_DST`, contradicts the actual occurrence of
187/// daylight-saving time in New York. The input time is adjusted by the UTC
188/// offset for daylight-saving time in New York (-4:00) resulting in a UTC
189/// time 05:30. Note that the result, "Jan 1, 2010 05:30 UTC", corresponds
190/// to the New York time "Jan 1, 2010 00:30:00-5:00" (a standard time).
191/// 3. "Mar 14, 2010 02:30" is not a valid local time in New York (a correctly
192/// administered clock would have been set ahead an hour at 2:00AM). The
193/// operation will use the later of two potential values, determined by
194/// applying the standard and daylight-saving time UTC offsets to the input
195/// (07:30 UTC and 06:30 UTC, respectively). Note that the selection of the
196/// later time reflects an assumption that the user forgot to adjust the
197/// clock.
198/// 4. The input time is adjusted by the UTC offset for standard time in New
199/// York (-5:00) resulting in the UTC time 07:30. Note that "Mar 14, 2010
200/// 07:30 UTC" corresponds to the New York time "Mar 14, 2010 03:30-4:00" (a
201/// daylight-saving time).
202///
203/// 5. The input time is adjusted by the UTC offset for daylight-saving time in
204/// New York (-4:00) resulting in the UTC time 06:30. Note that "Mar 14,
205/// 2010. 06:30 UTC" corresponds to the New York time "Mar 14, 2010
206/// 01:30-5:00" (a standard time).
207///
208/// 6. "Apr 1, 2010 01:30" is unambiguously a daylight-saving time value, so the
209/// supplied policy `e_STANDARD` contradicts the actual occurrence of
210/// daylight-saving time in New York. The input time is adjusted by the UTC
211/// offset for standard time in New York (-5:00) resulting in a UTC time
212/// 06:30. Note that "Apr 1, 2010 06:30 UTC" corresponds to the New York
213/// time "Apr 1, 2010 02:30:00-4:00" (a daylight-saving time).
214///
215/// 7. "Apr 1, 2010 01:30" is unambiguously a daylight-saving time value. The
216/// result is simply the corresponding UTC time "Apr 1, 2010 06:30 UTC".
217/// 8. "Nov 7, 2010 01:30" is a valid, but ambiguous, local time in New York
218/// (clocks are set back by an hour at 2:00AM, so 1:30AM occurs twice). The
219/// operation will use the later of two potential values determined by
220/// applying the standard and daylight-saving time UTC offsets to the input
221/// (06:30 UTC and 05:30 UTC, respectively). Note that the selection of the
222/// later time is arbitrary, but is consistent with common implementations of
223/// the C standard library.
224///
225/// ## Thread Safety {#baltzo_timezoneutil-thread-safety}
226///
227///
228/// The functions provided by `baltzo::TimeZoneUtil` are *thread-safe*, meaning
229/// they can be safely executed concurrently.
230///
231/// ## Usage {#baltzo_timezoneutil-usage}
232///
233///
234/// The following usage examples demonstrate how to use various functions
235/// provided by `baltzo::TimeZoneUtil` to perform conversions on various time
236/// representations.
237///
238/// ### Example 1: Converting a UTC time to a Local Time {#baltzo_timezoneutil-example-1-converting-a-utc-time-to-a-local-time}
239///
240///
241/// In this usage example, we illustrate how to convert a UTC time to its
242/// corresponding local time in a given time zone. We start by creating a
243/// `bdlt::Datetime` object holding the UTC time "July 31, 2010 15:00:00":
244/// @code
245/// bdlt::Datetime utcTime(2010, 7, 31, 15, 0, 0);
246/// @endcode
247/// Then, we create a `baltzo::LocalDatetime` object to hold the result of the
248/// conversion operation:
249/// @code
250/// baltzo::LocalDatetime newYorkTime;
251/// @endcode
252/// Now, we call the `convertUtcToLocalTime` function in `baltzo::TimeZoneUtil`:
253/// @code
254/// int status = baltzo::TimeZoneUtil::convertUtcToLocalTime(&newYorkTime,
255/// "America/New_York",
256/// utcTime);
257/// if (0 != status) {
258/// // A non-zero 'status' indicates there was an error in the conversion
259/// // (e.g., the time zone id was not valid or the environment has not
260/// // been correctly configured).
261///
262/// return 1; // RETURN
263/// }
264/// @endcode
265/// Finally, we observe that the result in `newYorkTime` is "July 31, 2010
266/// 11:00:00" and that the offset from UTC applied was -4 hours:
267/// @code
268/// const bdlt::Datetime test = newYorkTime.datetimeTz().localDatetime();
269/// assert(2010 == test.year()); assert(11 == test.hour());
270/// assert( 7 == test.month()); assert( 0 == test.minute());
271/// assert( 31 == test.day()); assert( 0 == test.second());
272///
273/// assert( -4 * 60 == newYorkTime.datetimeTz().offset());
274/// @endcode
275///
276/// ### Example 2: Converting a Local Time in One Time Zone to Another Time Zone {#baltzo_timezoneutil-example-2-converting-a-local-time-in-one-time-zone-to-another-time-zone}
277///
278///
279/// In this example we illustrate how to convert a local time in a given time
280/// zone directly to its corresponding local time in another time zone. In
281/// particular, we want to convert the time "July 31, 2010 15:00:00" in New York
282/// to its corresponding time in Rome, Italy.
283///
284/// First, we create a `bdlt::Datetime` object representing the time "July 31,
285/// 2010 15:00:00" in New York:
286/// @code
287/// bdlt::Datetime newYorkTime(2010, 7, 31, 15, 0, 0);
288/// @endcode
289/// Now, let's apply the conversion operation to obtain a
290/// `baltzo::LocalDatetime` object representing the corresponding local time in
291/// Italy:
292/// @code
293/// baltzo::LocalDatetime romeTime;
294/// int status = baltzo::TimeZoneUtil::convertLocalToLocalTime(
295/// &romeTime,
296/// "Europe/Rome",
297/// newYorkTime,
298/// "America/New_York");
299/// if (0 != status) {
300/// // A non-zero 'status' indicates there was an error in the conversion
301/// // (e.g., the time zone id was not valid or the environment has not
302/// // been correctly configured).
303///
304/// return 1; // RETURN
305/// }
306/// @endcode
307/// Notice that we did not specify the optional `dstPolicy` argument to
308/// `convertLocalToLocalTime`. The default value should be appropriate for most
309/// users.
310///
311/// Finally, we verify that the value of `romeTime` is "July 31, 2010 21:00:00",
312/// which is the time in Italy corresponding to "July 31, 2010 15:00:00" in New
313/// York:
314/// @code
315/// const bdlt::Datetime test = romeTime.datetimeTz().localDatetime();
316/// assert(2010 == test.year()); assert(21 == test.hour());
317/// assert( 7 == test.month()); assert( 0 == test.minute());
318/// assert( 31 == test.day()); assert( 0 == test.second());
319///
320/// assert( 2 * 60 == romeTime.datetimeTz().offset());
321/// @endcode
322///
323/// ### Example 3: Initializing a Local Time {#baltzo_timezoneutil-example-3-initializing-a-local-time}
324///
325///
326/// In this example we illustrate how to create a `baltzo::LocalDatetime` from a
327/// `bdlt::Datetime`, which may not represent a unique (or valid) clock time.
328///
329/// First, we create a `bdlt::Datetime` object for the New York local time "Jul
330/// 31, 2010 15:00:00". Note that this local date-time occurs during a DST
331/// transition and is an invalid date-time.
332/// @code
333/// bdlt::Datetime uniqueTime(2010, 7, 31, 15, 0, 0);
334/// @endcode
335/// Then, we call `initLocalTime`, which returns a `baltzo::LocalDatetime`
336/// object. `initLocalTime` also optionally returns
337/// `baltzo::LocalTimeValidity::Enum`, indicating whether the provided input was
338/// a valid and unique clock time. Note that invalid or ambiguous times are
339/// resolved using the optionally provided `baltzo::DstPolicy::Enum` (see the
340/// section {Daylight-Saving Time (DST) Policies and Disambiguation}):
341/// @code
342/// baltzo::LocalDatetime localTime;
343/// baltzo::LocalTimeValidity::Enum validity;
344/// int status = baltzo::TimeZoneUtil::initLocalTime(&localTime,
345/// &validity,
346/// uniqueTime,
347/// "America/New_York");
348/// if (0 != status) {
349/// return 1;
350/// }
351/// @endcode
352/// Now, we verify the value of `localTime` is "Jul 31, 2010 15:00:00" with an
353/// offset of -4:00 from UTC, in the time zone "America/New_York".
354/// @code
355/// const bdlt::Datetime invalidTest = localTime.datetimeTz().localDatetime();
356/// assert(2010 == invalidTest.year()); assert(15 == invalidTest.hour());
357/// assert( 7 == invalidTest.month()); assert( 0 == invalidTest.minute());
358/// assert( 31 == invalidTest.day()); assert( 0 == invalidTest.second());
359///
360/// assert( -4 * 60 == localTime.datetimeTz().offset());
361/// assert("America/New_York" == localTime.timeZoneId());
362/// @endcode
363/// In addition, the time provided represents a unique and valid clock time in
364/// New York (because it does not fall near a daylight-saving time transition):
365/// @code
366/// assert(baltzo::LocalTimeValidity::e_VALID_UNIQUE == validity);
367/// @endcode
368/// By contrast, if we call `initLocalTime` for a time value that falls during a
369/// during a daylight-saving time transition, the returned
370/// `baltzo::LocalTimeValidity::Enum` will indicate if the supplied time either
371/// does not represent a valid clock time in the time zone (as may occur when
372/// clocks are set forward), or does not represent a unique clock time (as may
373/// occur when clocks are set back).
374///
375/// For example, suppose we call `initLocalTime` for "Mar 14, 2010 02:30"; this
376/// clock time does not occurs in New York, as clocks are set forward by an hour
377/// at 2am local time:
378/// @code
379/// bdlt::Datetime invalidTime(2010, 3, 14, 2, 30, 0);
380/// status = baltzo::TimeZoneUtil::initLocalTime(&localTime,
381/// &validity,
382/// invalidTime,
383/// "America/New_York");
384/// if (0 != status) {
385/// return 1;
386/// }
387/// @endcode
388/// Now, we verify the value of `localTime` represents a valid and unique time
389/// of "Mar 14, 2010 03:30:00-04:00" in the "America/New_York" time zone.
390/// @code
391/// const bdlt::Datetime test = localTime.datetimeTz().localDatetime();
392/// assert(2010 == test.year()); assert( 3 == test.hour());
393/// assert( 3 == test.month()); assert(30 == test.minute());
394/// assert( 14 == test.day()); assert( 0 == test.second());
395///
396/// assert("America/New_York" == localTime.timeZoneId());
397/// assert( -4 * 60 == localTime.datetimeTz().offset());
398/// @endcode
399/// Finally, we verify that the validity status returned for `invalidTime` is
400/// `e_INVALID`:
401/// @code
402/// assert(baltzo::LocalTimeValidity::e_INVALID == validity);
403/// @endcode
404///
405/// ### Example 4: Obtaining Information About a Time Value {#baltzo_timezoneutil-example-4-obtaining-information-about-a-time-value}
406///
407///
408/// In this example we illustrate how to obtain additional information about a
409/// local time in a given time zone using the `loadLocalTimePeriod` method.
410/// Using `loadLocalTimePeriod` a client can determine, for a point in time, the
411/// attributes that characterize local time in a given time zone (e.g., the
412/// offset from UTC, whether it is daylight-saving time) as well as the interval
413/// over which those attributes apply (see @ref baltzo_localtimeperiod ).
414///
415/// First, we create a `baltzo::LocalDatetime` object for the New York local
416/// time "Jul 31, 2010 15:00:00-04:00". Note that this `baltzo::LocalDatetime`
417/// may also be created as in example 3.
418/// @code
419/// bdlt::DatetimeTz localTimeTz(bdlt::Datetime(2010, 7, 31, 15, 0, 0),
420/// -4 * 60);
421/// baltzo::LocalDatetime localTime(localTimeTz, "America/New_York");
422/// @endcode
423/// Then, we call `loadLocalTimePeriod`, which returns a
424/// `baltzo::LocalTimePeriod` object that is loaded with attributes
425/// characterizing local time in New York on "Mar 14, 2010 03:30:00", and the
426/// interval over which those attributes are in effect.
427/// @code
428/// baltzo::LocalTimePeriod period;
429/// int status = baltzo::TimeZoneUtil::loadLocalTimePeriod(&period, localTime);
430/// if (0 != status) {
431/// // A non-zero 'status' indicates there was an error in the conversion
432/// // (e.g., the time zone id was not valid or the environment has not
433/// // been correctly configured).
434///
435/// return 1; // RETURN
436/// }
437/// @endcode
438/// Now we examine the returned properties. "Mar 14, 2010 03:30:00" is during
439/// daylight-saving time, which is -4:00 UTC, and the type of local time is
440/// sometimes abbreviated "EDT" for "Eastern Daylight Time". "Eastern Daylight
441/// Time" is in effect from "Mar 14, 2010 7am UTC" to "Nov 7, 2010 6am UTC".
442/// Note that the abbreviation provided ("EDT") is not canonical or localized.
443/// In general the provided abbreviations should not be displayed to users (they
444/// are intended for development and debugging only):
445/// @code
446/// assert(true == period.descriptor().dstInEffectFlag());
447/// assert(-4 * 60 * 60 == period.descriptor().utcOffsetInSeconds());
448/// assert("EDT" == period.descriptor().description());
449/// assert(bdlt::Datetime(2010, 3, 14, 7, 0, 0) == period.utcStartTime());
450/// assert(bdlt::Datetime(2010, 11, 7, 6, 0, 0) == period.utcEndTime());
451/// @endcode
452/// @}
453/** @} */
454/** @} */
455
456/** @addtogroup bal
457 * @{
458 */
459/** @addtogroup baltzo
460 * @{
461 */
462/** @addtogroup baltzo_timezoneutil
463 * @{
464 */
465
466#include <balscm_version.h>
467
469#include <baltzo_dstpolicy.h>
472#include <baltzo_localdatetime.h>
473
474#include <bdlt_currenttime.h>
475#include <bdlt_datetime.h>
476#include <bdlt_datetimetz.h>
477
478#include <bsls_assert.h>
479#include <bsls_review.h>
480#include <bsls_timeinterval.h>
481
482#include <bsl_iosfwd.h>
483
484
485namespace baltzo {
486
487class LocalTimePeriod;
488class ZoneinfoCache;
489
490 // ===================
491 // struct TimeZoneUtil
492 // ===================
493
494/// This `struct` provides a namespace for utility functions that convert
495/// time values to, from, and between, their corresponding local time
496/// representations in (possibly) different time zones.
497///
498/// These utility functions are:
499/// * *alias-safe*
500/// * *exception-neutral* (agnostic)
501/// * *thread-safe*
502/// For terminology see @ref bsldoc_glossary .
504
505 // CLASS METHODS
506
507 /// Load, into the specified `result`, the local time value that is the
508 /// specified `interval` in the future of the specified `originalTime`
509 /// (in the time zone `originalTime.timeZoneId()`). Return 0 on
510 /// success, and a non-zero value with no effect otherwise. A return
511 /// value of `ErrorCode::k_UNSUPPORTED_ID` indicates that
512 /// `targetTimeZoneId` was not recognized, and a return value of
513 /// `ErrorCode::k_OUT_OF_RANGE` indicates that the result of the
514 /// operation would have been outside the range of values representable
515 /// by the `result` type. The resulting local-time is equivalent to
516 /// adding `interval` to `originalTime.datetimeTz().utcDatetime()` and
517 /// converting the result into the local time of
518 /// `originalTime.timeZoneId()`.
519 static int addInterval(LocalDatetime *result,
520 const LocalDatetime& originalTime,
521 const bsls::TimeInterval& interval);
522
524 const char *targetTimeZoneId,
525 const bdlt::Datetime& utcTime);
526 /// Load, into the specified `result`, the local date-time value (in the
527 /// time zone indicated by the specified `targetTimeZoneId`)
528 /// corresponding to the specified `utcTime`. The offset from UTC of
529 /// the time zone is rounded down to minute precision. Return 0 on
530 /// success, and a non-zero value with no effect otherwise. A return
531 /// value of `ErrorCode::k_UNSUPPORTED_ID` indicates that
532 /// `targetTimeZoneId` was not recognized, and a return value of
533 /// `ErrorCode::k_OUT_OF_RANGE` indicates that the result of the
534 /// operation would have been outside the range of values representable
535 /// by the `result` type.
536 static int convertUtcToLocalTime(bdlt::DatetimeTz *result,
537 const char *targetTimeZoneId,
538 const bdlt::Datetime& utcTime);
539
540 static int convertLocalToLocalTime(LocalDatetime *result,
541 const char *targetTimeZoneId,
542 const LocalDatetime& srcTime);
543 static int convertLocalToLocalTime(
544 LocalDatetime *result,
545 const char *targetTimeZoneId,
546 const bdlt::DatetimeTz& srcTime);
547 static int convertLocalToLocalTime(bdlt::DatetimeTz *result,
548 const char *targetTimeZoneId,
549 const LocalDatetime& srcTime);
550 /// Load, into the specified `result`, the local date-time value (in the
551 /// time zone indicated by the specified `targetTimeZoneId`)
552 /// corresponding to the local time indicated by the specified
553 /// `srcTime`. The offset from UTC of both time zones is rounded down
554 /// to minute precision. Return 0 on success, and a non-zero value with
555 /// no effect otherwise. A return value of
556 /// `ErrorCode::k_UNSUPPORTED_ID` indicates that `targetTimeZoneId` was
557 /// not recognized, and a return value of `ErrorCode::k_OUT_OF_RANGE`
558 /// indicates that the result of the operation would have been outside
559 /// the range of values representable by the `result` type.
560 static int convertLocalToLocalTime(
561 bdlt::DatetimeTz *result,
562 const char *targetTimeZoneId,
563 const bdlt::DatetimeTz& srcTime);
564
566 const char *targetTimeZoneId,
567 const bdlt::Datetime& srcTime,
568 const char *srcTimeZoneId,
569 DstPolicy::Enum dstPolicy =
571 /// Load, into the specified `result`, the local date-time value (in the
572 /// time zone indicated by the specified `targetTimeZoneId`)
573 /// corresponding to the local time indicated by the specified `srcTime`
574 /// (in the time zone indicated by the specified `srcTimeZoneId`).
575 /// Optionally specify a `dstPolicy` indicating whether or not `srcTime`
576 /// represents a daylight-saving time value. If `dstPolicy` is
577 /// unspecified and `srcTime` is a unique and valid time in the source
578 /// time zone, then perform the conversion using that uniquely described
579 /// time; if `dstPolicy` is unspecified and `srcTime` is either
580 /// ambiguous or invalid, then use the later of the two possible
581 /// interpretations of `srcTime`. The offset from UTC of both time
582 /// zones is rounded down to minute precision. Return 0 on success, and
583 /// a non-zero value with no effect otherwise. A return value of
584 /// `ErrorCode::k_UNSUPPORTED_ID` indicates that either
585 /// `targetTimeZoneId` or `srcTimeZoneId` was not recognized.
587 const char *targetTimeZoneId,
588 const bdlt::Datetime& srcTime,
589 const char *srcTimeZoneId,
590 DstPolicy::Enum dstPolicy =
592
593 static int initLocalTime(bdlt::DatetimeTz *result,
594 const bdlt::Datetime& localTime,
595 const char *timeZoneId,
596 DstPolicy::Enum dstPolicy =
598 static int initLocalTime(LocalDatetime *result,
599 const bdlt::Datetime& localTime,
600 const char *timeZoneId,
601 DstPolicy::Enum dstPolicy =
603 static int initLocalTime(bdlt::DatetimeTz *result,
604 LocalTimeValidity::Enum *resultValidity,
605 const bdlt::Datetime& localTime,
606 const char *timeZoneId,
607 DstPolicy::Enum dstPolicy =
609 /// Load, into the specified `result`, the local date-time value --
610 /// including the local date, time, and resolved UTC offset -- indicated
611 /// by the specified `localTime` in the time zone indicated by the
612 /// specified `timeZoneId`. Optionally specify `resultValidity` in
613 /// which to load the validity of `localTime` as being unique, ambiguous
614 /// but valid, or invalid. Optionally specify a `dstPolicy` indicating
615 /// whether or not `localTime` represents a daylight-saving time value.
616 /// If `dstPolicy` is unspecified and `localTime` is a unique and valid
617 /// time in the source time zone, then perform the conversion using that
618 /// uniquely described time; if `dstPolicy` is unspecified and
619 /// `localTime` is either ambiguous or invalid, then use the later of
620 /// the two possible interpretations of `localTime`. The offset from
621 /// UTC of the time zone is rounded down to minute precision. Return 0
622 /// on success, and a non-zero value with no effect otherwise. A return
623 /// value of `ErrorCode::k_UNSUPPORTED_ID` indicates that `timeZoneId`
624 /// was not recognized. The behavior is undefined unless the result of
625 /// the initialization falls within the supported epoch.
626 static int initLocalTime(LocalDatetime *result,
627 LocalTimeValidity::Enum *resultValidity,
628 const bdlt::Datetime& localTime,
629 const char *timeZoneId,
630 DstPolicy::Enum dstPolicy =
632
634 const bdlt::Datetime& localTime,
635 const char *timeZoneId,
636 DstPolicy::Enum dstPolicy =
638 /// Load, into the specified `result`, the UTC time value that
639 /// corresponds to the specified `localTime` in the time zone indicated
640 /// by the specified `timeZoneId`. Optionally specify a `dstPolicy`
641 /// indicating whether or not `localTime` represents a daylight-saving
642 /// time value. If `dstPolicy` is unspecified and `localTime` is a
643 /// unique and valid time in the source time zone, then perform the
644 /// conversion using that uniquely described time; if `dstPolicy` is
645 /// unspecified and `localTime` is either ambiguous or invalid, then use
646 /// the later of the two possible interpretations of `localTime`. The
647 /// offset from UTC of the time zone is rounded down to minute
648 /// precision. Return 0 on success, and a non-zero value with no effect
649 /// otherwise. A return value of `ErrorCode::k_UNSUPPORTED_ID`
650 /// indicates that `timeZoneId` was not recognized. The behavior is
651 /// undefined unless the result of the conversion falls within the
652 /// supported epoch.
654 const bdlt::Datetime& localTime,
655 const char *timeZoneId,
656 DstPolicy::Enum dstPolicy =
658
659 /// Load, into the specified `result`, attributes characterizing the
660 /// specified `localTime` (i.e., the offset from UTC, whether
661 /// daylight-saving time is in effect and the description of the time
662 /// zone), as well as the time interval over which those attributes
663 /// apply. Return 0 on success, and a non-zero value with no effect
664 /// otherwise. A return value of `ErrorCode::k_UNSUPPORTED_ID`
665 /// indicates that `localTime.timeZoneId()` was not recognized.
666 static int loadLocalTimePeriod(LocalTimePeriod *result,
667 const LocalDatetime& localTime);
668
669 /// Load, into the specified `result`, attributes characterizing the
670 /// specified `localTime` in the time zone indicated by the specified
671 /// `timeZoneId` (i.e., the offset from UTC, whether daylight-saving
672 /// time is in effect and the description of the time zone), as well as
673 /// the time interval over which those attributes apply. Return 0 on
674 /// success, and a non-zero value with no effect otherwise. A return
675 /// value of `ErrorCode::k_UNSUPPORTED_ID` indicates that `timeZoneId`
676 /// was not recognized.
677 static int loadLocalTimePeriod(LocalTimePeriod *result,
678 const bdlt::DatetimeTz& localTime,
679 const char *timeZoneId);
680
681 /// Load, into the specified `result`, attributes characterizing local
682 /// time at the specified `utcTime` in the time zone indicated by the
683 /// specified `timeZoneId` (i.e., the offset from UTC, whether
684 /// daylight-saving time is in effect and the description of the time
685 /// zone), as well as the time interval over which those attributes
686 /// apply. Return 0 on success, and a non-zero value with no effect
687 /// otherwise. A return value of `ErrorCode::k_UNSUPPORTED_ID`
688 /// indicates that `timeZoneId` was not recognized.
690 const char *timeZoneId,
691 const bdlt::Datetime& utcTime);
692
693 static int now(bdlt::DatetimeTz *result, const char *timeZoneId);
694 /// Load, into the specified `result`, the current local time value
695 /// in the time zone indicated by the specified `timeZoneId`. Return 0
696 /// on success, and a non-zero value with no effect otherwise. A
697 /// return value of `ErrorCode::k_UNSUPPORTED_ID` indicates
698 /// that `timeZoneid` is not recognized.
699 static int now(LocalDatetime *result, const char *timeZoneId);
700
701 /// Load, into the specified `result`, `true` if the offset from UTC of
702 /// the specified `localTime` (i.e., `localTime.offset()`) is consistent
703 /// with the actual local time offset, as indicated by time zone data,
704 /// at the UTC time `localTime.utcDatetime()` in the time zone indicated
705 /// by the specified `timeZoneId`, and `false` otherwise. Return 0 on
706 /// success, and a non-zero value with `false` loaded into `result`
707 /// otherwise. A return value of `ErrorCode::k_UNSUPPORTED_ID`
708 /// indicates that `timeZoneId` is not recognized. Note that this
709 /// operation verifies that the properties of the provided local time
710 /// are consistent with the time zone data.
711 static int validateLocalTime(bool *result,
712 const bdlt::DatetimeTz& localTime,
713 const char *timeZoneId);
714
715 /// Load, into the specified `result`, `true` if the time zone
716 /// identifier of the specified `localTime` (i.e.,
717 /// `localTime.timeZoneId()`) is a valid identifier, and the offset from
718 /// UTC of `localTime` (i.e., `localTime.datetimeTz().offset()`) is
719 /// consistent with the actual local time offset, as indicated by time
720 /// zone data, at the UTC time `localTime.datetimeTz().utcDatetime()` in
721 /// the time zone indicated by `localTime.timeZoneId()`, and `false`
722 /// otherwise. Return 0 on success, and a non-zero value with `false`
723 /// loaded into `result` otherwise. A return value of
724 /// `ErrorCode::k_UNSUPPORTED_ID` indicates that `timeZoneId` is not
725 /// recognized. Note that this operation verifies that the properties
726 /// of the provided local time are consistent with the time zone data.
727 static int validateLocalTime(bool *result, const LocalDatetime& localTime);
728};
729
730// ============================================================================
731// INLINE DEFINITIONS
732// ============================================================================
733
734 // -------------------
735 // struct TimeZoneUtil
736 // -------------------
737
738// CLASS METHODS
739inline
741 bdlt::DatetimeTz *result,
742 const char *targetTimeZoneId,
743 const bdlt::Datetime& utcTime)
744{
745 BSLS_ASSERT(result);
746 BSLS_ASSERT(targetTimeZoneId);
747
749 result,
750 targetTimeZoneId,
751 utcTime,
753}
754
755inline
757 LocalDatetime *result,
758 const char *targetTimeZoneId,
759 const LocalDatetime& srcTime)
760{
761 BSLS_ASSERT(result);
762 BSLS_ASSERT(targetTimeZoneId);
763
764 return convertUtcToLocalTime(result,
765 targetTimeZoneId,
766 srcTime.datetimeTz().utcDatetime());
767}
768
769inline
771 LocalDatetime *result,
772 const char *targetTimeZoneId,
773 const bdlt::DatetimeTz& srcTime)
774{
775 BSLS_ASSERT(result);
776 BSLS_ASSERT(targetTimeZoneId);
777
778 return convertUtcToLocalTime(result,
779 targetTimeZoneId,
780 srcTime.utcDatetime());
781}
782
783inline
785 bdlt::DatetimeTz *result,
786 const char *targetTimeZoneId,
787 const LocalDatetime& srcTime)
788{
789 BSLS_ASSERT(result);
790 BSLS_ASSERT(targetTimeZoneId);
791
792 return convertUtcToLocalTime(result,
793 targetTimeZoneId,
794 srcTime.datetimeTz().utcDatetime());
795}
796
797inline
799 bdlt::DatetimeTz *result,
800 const char *targetTimeZoneId,
801 const bdlt::DatetimeTz& srcTime)
802{
803 BSLS_ASSERT(result);
804 BSLS_ASSERT(targetTimeZoneId);
805
806 return convertUtcToLocalTime(result,
807 targetTimeZoneId,
808 srcTime.utcDatetime());
809}
810
811inline
813 LocalTimeValidity::Enum *resultValidity,
814 const bdlt::Datetime& localTime,
815 const char *timeZoneId,
816 DstPolicy::Enum dstPolicy)
817{
818 BSLS_ASSERT(result);
819 BSLS_ASSERT(resultValidity);
820 BSLS_ASSERT(timeZoneId);
821
823 result,
824 resultValidity,
825 localTime,
826 timeZoneId,
827 dstPolicy,
829}
830
831inline
833 const bdlt::Datetime& localTime,
834 const char *timeZoneId,
835 DstPolicy::Enum dstPolicy)
836{
837 BSLS_ASSERT(result);
838 BSLS_ASSERT(timeZoneId);
839
840 LocalTimeValidity::Enum validityStatus;
841 return initLocalTime(result,
842 &validityStatus,
843 localTime,
844 timeZoneId,
845 dstPolicy);
846}
847
848inline
850 const LocalDatetime& localTime)
851{
852 BSLS_ASSERT(result);
853
854 return loadLocalTimePeriod(result,
855 localTime.datetimeTz(),
856 localTime.timeZoneId().c_str());
857}
858
859inline
861 const bdlt::DatetimeTz& localTime,
862 const char *timeZoneId)
863{
864 BSLS_ASSERT(result);
865 BSLS_ASSERT(timeZoneId);
866
867 return loadLocalTimePeriodForUtc(result,
868 timeZoneId,
869 localTime.utcDatetime());
870}
871
872inline
873int TimeZoneUtil::now(bdlt::DatetimeTz *result, const char *timeZoneId)
874{
875 BSLS_ASSERT(result);
876 BSLS_ASSERT(timeZoneId);
877
879 return convertUtcToLocalTime(result, timeZoneId, utcNow);
880}
881
882inline
883int TimeZoneUtil::now(LocalDatetime *result, const char *timeZoneId)
884{
885 BSLS_ASSERT(result);
886 BSLS_ASSERT(timeZoneId);
887
889 return convertUtcToLocalTime(result, timeZoneId, utcNow);
890}
891
892inline
894 const LocalDatetime& localTime)
895{
896 BSLS_ASSERT(result);
897
898 return validateLocalTime(result,
899 localTime.datetimeTz(),
900 localTime.timeZoneId().c_str());
901}
902
903} // close package namespace
904
905
906#endif
907
908// ----------------------------------------------------------------------------
909// Copyright 2018 Bloomberg Finance L.P.
910//
911// Licensed under the Apache License, Version 2.0 (the "License");
912// you may not use this file except in compliance with the License.
913// You may obtain a copy of the License at
914//
915// http://www.apache.org/licenses/LICENSE-2.0
916//
917// Unless required by applicable law or agreed to in writing, software
918// distributed under the License is distributed on an "AS IS" BASIS,
919// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
920// See the License for the specific language governing permissions and
921// limitations under the License.
922// ----------------------------- END-OF-FILE ----------------------------------
923
924/** @} */
925/** @} */
926/** @} */
Definition baltzo_localdatetime.h:172
const bsl::string & timeZoneId() const
Definition baltzo_localdatetime.h:562
const bdlt::DatetimeTz & datetimeTz() const
Definition baltzo_localdatetime.h:556
Definition baltzo_localtimeperiod.h:211
Definition bdlt_datetimetz.h:308
Datetime utcDatetime() const
Definition bdlt_datetimetz.h:678
Definition bdlt_datetime.h:331
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6705
Definition bsls_timeinterval.h:301
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition baltzo_datafileloader.h:263
static ZoneinfoCache * defaultCache(ZoneinfoCache *cache=0)
Definition baltzo_defaultzoneinfocache.h:383
Enum
Definition baltzo_dstpolicy.h:131
@ e_UNSPECIFIED
Definition baltzo_dstpolicy.h:137
Enum
Definition baltzo_localtimevalidity.h:149
static int initLocalTime(bdlt::DatetimeTz *result, LocalTimeValidity::Enum *resultValidity, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy, ZoneinfoCache *cache)
static int convertUtcToLocalTime(bdlt::DatetimeTz *result, const char *resultTimeZoneId, const bdlt::Datetime &utcTime, ZoneinfoCache *cache)
Definition baltzo_timezoneutil.h:503
static int loadLocalTimePeriod(LocalTimePeriod *result, const LocalDatetime &localTime)
Definition baltzo_timezoneutil.h:849
static int addInterval(LocalDatetime *result, const LocalDatetime &originalTime, const bsls::TimeInterval &interval)
static int initLocalTime(bdlt::DatetimeTz *result, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
Definition baltzo_timezoneutil.h:832
static int now(bdlt::DatetimeTz *result, const char *timeZoneId)
Definition baltzo_timezoneutil.h:873
static int convertLocalToLocalTime(bdlt::DatetimeTz *result, const char *targetTimeZoneId, const bdlt::Datetime &srcTime, const char *srcTimeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static int initLocalTime(LocalDatetime *result, LocalTimeValidity::Enum *resultValidity, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static int convertUtcToLocalTime(LocalDatetime *result, const char *targetTimeZoneId, const bdlt::Datetime &utcTime)
static int loadLocalTimePeriodForUtc(LocalTimePeriod *result, const char *timeZoneId, const bdlt::Datetime &utcTime)
static int initLocalTime(LocalDatetime *result, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static int convertLocalToLocalTime(LocalDatetime *result, const char *targetTimeZoneId, const bdlt::Datetime &srcTime, const char *srcTimeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static int convertLocalToUtc(bdlt::Datetime *result, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static int validateLocalTime(bool *result, const bdlt::DatetimeTz &localTime, const char *timeZoneId)
static int convertLocalToLocalTime(LocalDatetime *result, const char *targetTimeZoneId, const LocalDatetime &srcTime)
Definition baltzo_timezoneutil.h:756
static int convertLocalToUtc(LocalDatetime *result, const bdlt::Datetime &localTime, const char *timeZoneId, DstPolicy::Enum dstPolicy=DstPolicy::e_UNSPECIFIED)
static Datetime utc()
Definition bdlt_currenttime.h:296