BDE 4.14.0 Production release
Loading...
Searching...
No Matches
baltzo_defaultzoneinfocache

Detailed Description

Outline

Purpose

Provide facilities to manage a default Zoneinfo cache object.

Classes

See also
baltzo_zoneinfocache, baltzo_timezoneutil

Description

This component provides a namespace, baltzo::DefaultZoneinfoCache, for utility functions that install and access a default Zoneinfo cache object. In addition, this component provides a mechanism, baltzo::DefaultZoneinfoCacheScopedGuard, that facilities the temporary installation of the default Zoneinfo cache object (for the lifetime of the guard object).

Operations that convert a time value either from, or to, a local time representation, commonly require access to time-zone information provided from a baltzo::ZoneinfoCache object. Because a single set of time-zone data is generally applicable to an entire task, this component provides the installation and use of a process-wide default baltzo::ZoneinfoCache object (i.e., a Zoneinfo cache). See baltzo_timezoneutil for examples of how operations may take advantage of this default cache. Note that the behavior is undefined unless this facility is used before main exits.

The Automatically-Installed Default-Cache Instance

If a baltzo::ZoneinfoCache object is not explicitly configured via the setDefaultCache method, the first call to defaultCache automatically initializes and returns a new Zoneinfo cache object (i.e., a default default-cache object). Subsequent calls to the defaultCache method return that same object, unless the default Zoneinfo cache object is reset via the setDefaultCache method.

Clients are encouraged to use this automatically configured default cache object unless there is a particular need to configure it explicitly.

Default Time Zone Data Location

The mechanism for automatically configuring a default Zoneinfo cache object first assumes that the TZ Database files are rooted in a directory specified by the BDE_ZONEINFO_ROOT_PATH environment variable. If BDE_ZONEINFO_ROOT_PATH is unset, the baltzo::DefaultZoneinfoCache will attempt to use one of a (priority ordered) sequence of several (platform specific) standard locations. Finally, if no standard directory exists that contains TZ Database files, the baltzo::ZoneinfoCache will use the current working directory.

If a TZ Database file is not available in the "configured" directory, requests for that time-zone's data will fail. Additional information about TZ Database files can be found in baltzo_datafileloader .

Thread Safety

The baltzo::DefaultZoneinfoCache::defaultCache method is thread-safe unless it is called concurrently with either the setDefaultCache method or the putenv POSIX function. Note that the baltzo::ZoneinfoCache singleton is, itself, fully thread-safe (see baltzo_zoneinfocache ); it is only the installation of the default cache that is not thread-safe.

baltzo::DefaultZoneinfoCache::setDefaultCache is not thread-safe. The expected usage is that clients that choose to explicitly configure the default cache for their application (rather than using the automatically provided default cache) will set the default cache during the initialization of their application (while the application has a single thread).

The baltzo::DefaultTimeZoneCacheScopedGuard class is not, even minimally thread-safe meaning that its constructor cannot be invoked concurrently from multiple threads.

Usage

The following usage examples demonstrate configuring and accessing the default Zoneinfo cache object.

Example 1: Accessing the Default Zoneinfo Cache Object

A common application of the baltzo::DefaultZoneinfoCache is to determine the appropriate time-zone information to use for an operation that accepts a Zoneinfo cache as an optional argument (e.g., see baltzo_timezoneutil ). Note that this usage pattern is also seen for the default allocator (see bslma_default ).

First, we declare a function, getLocalTimeDescriptor, that returns the local-time descriptor for a given time in a particular time zone. This method takes an optional baltzo::ZoneinfoCache address argument, via the default zoneinfoCache parameter. If zoneinfoCache is unspecified or 0, the default Zoneinfo cache is used for the operation:

/// Load, into the specified `result`, the local time descriptor
/// indicated by the specified `utcTime` and the specified `timeZoneId`.
/// Return 0 on success, and a non-zero value otherwise. Optionally
/// specify a `zoneinfoCache` used to retrieve time-zone information.
/// If `zoneinfoCache` is 0, the currently installed default Zoneinfo
/// cache is used.
int getLocalTimeDescriptor(baltzo::LocalTimeDescriptor *result,
const bdlt::Datetime& utcTime,
const char *timeZoneId,
baltzo::ZoneinfoCache *zoneinfoCache = 0)
{
Definition baltzo_localtimedescriptor.h:189
Definition baltzo_zoneinfocache.h:232
Definition bdlt_datetime.h:331

We call the baltzo::DefaultZoneinfoCache::defaultCache method, which returns zoneinfoCache if zoneinfoCache is not 0, and the currently installed Zoneinfo cache otherwise.

BSLS_ASSERT(0 != cache);
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
static ZoneinfoCache * defaultCache(ZoneinfoCache *cache=0)
Definition baltzo_defaultzoneinfocache.h:383

Then, now that we have a of Zoneinfo cache object, we access the time-zone data for timeZoneId, and obtain the local-time descriptor for utcTime:

const baltzo::Zoneinfo *zoneinfo = cache->getZoneinfo(timeZoneId);
if (0 == zoneinfo) {
// Data for `timeZoneId` is not available in the cache, so return
// an error.
return 1; // RETURN
}
const Zoneinfo * getZoneinfo(const char *timeZoneId)
Definition baltzo_zoneinfocache.h:336
Definition baltzo_zoneinfo.h:429

Now we invoke the findTransitionForUtcTime method on zoneInfo to obtain the transition holding the local time descriptor for the specified utcTime:

zoneinfo->findTransitionForUtcTime(utcTime);
*result = it->descriptor();
return 0;
}
TransitionConstIterator findTransitionForUtcTime(const bdlt::Datetime &utcTime) const
TransitionSequence::const_iterator TransitionConstIterator
Definition baltzo_zoneinfo.h:488

Note that findTransitionForUtcTime has undefined behavior if the supplied search time is earlier than that of the first transition in the Zoneinfo object. However a baltzo::ZoneinfoCache (from which we obtained zoneinfo) is guaranteed to return a well-formed baltzo::Zoneinfo (see baltzo::ZoneinfoUtil::isWellFormed), meaning that it contains a transition at the first representable bdlt::Datetime value, so the following call to findTransitionForUtcTime is guaranteed to have defined behavior.

Finally, we call our getLocalDescriptor defined above:

int rc = getLocalTimeDescriptor(&result,
bdlt::Datetime(bdlt::Date(2011, 03, 21),
bdlt::Time(20, 57)),
"America/New_York");
assert(0 == rc);
assert("EDT" == result.description());
assert(true == result.dstInEffectFlag());
assert(-14400 == result.utcOffsetInSeconds());
const bsl::string & description() const
Definition baltzo_localtimedescriptor.h:542
bool dstInEffectFlag() const
Definition baltzo_localtimedescriptor.h:548
int utcOffsetInSeconds() const
Definition baltzo_localtimedescriptor.h:554
Definition bdlt_date.h:294
Definition bdlt_time.h:196

Notice that since we did not specify the optional baltzo::ZoneinfoCache object, data will automatically come from the configured default baltzo::ZoneinfoCache object.

Example 2: Installing a Default Zoneinfo Cache Object

In this example we demonstrate how to configure the default time-zone cache for a process. Note that many application may not need to explicitly configure the default cache object, but can instead use the automatically configured default object. Also note that the default time-zone cache is intended to be configured by the owner of main. The default object should be set during the initialization of an application (while the task has a single thread) and unset just prior to termination (when there is similarly a single thread):

int main(int argc, const char *argv[])
{
// ...

First, we create and configure a baltzo::DataFileLoader object:

loader.configureRootPath("./test");
Definition baltzo_datafileloader.h:277
void configureRootPath(const char *path)

Then, we use loader to initialize a baltzo::ZoneinfoCache object:

baltzo::ZoneinfoCache cache(&loader);

Next, we create a baltzo::DefaultZoneinfoCacheScopedGuard to set the default Zoneinfo cache for the lifetime of the guard, and then verify the the address returned by the defaultCache method is correct:

{
// ...
Definition baltzo_defaultzoneinfocache.h:348

Finally, at the end of this scope the guard is destroyed, and the default Zoneinfo cache is restored to its previous value:

}
// ...
}