Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component baltzo_defaultzoneinfocache
[Package baltzo]

Provide facilities to manage a default Zoneinfo cache object. More...

Namespaces

namespace  baltzo

Detailed Description

Outline
Purpose:
Provide facilities to manage a default Zoneinfo cache object.
Classes:
baltzo::DefaultZoneinfoCache default Zoneinfo cache utilities
baltzo::DefaultZoneinfoCacheScopedGuard guard for default Zoneinfo cache
See also:
Component baltzo_zoneinfocache, Component 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:
  int getLocalTimeDescriptor(baltzo::LocalTimeDescriptor *result,
                             const bdlt::Datetime&        utcTime,
                             const char                  *timeZoneId,
                             baltzo::ZoneinfoCache       *zoneinfoCache = 0)
      // 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.
  {
We call the baltzo::DefaultZoneinfoCache::defaultCache method, which returns zoneinfoCache if zoneinfoCache is not 0, and the currently installed Zoneinfo cache otherwise. 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
      }
Now we invoke the findTransitionForUtcTime method on zoneInfo to obtain the transition holding the local time descriptor for the specified utcTime:
      baltzo::Zoneinfo::TransitionConstIterator it =
                                 zoneinfo->findTransitionForUtcTime(utcTime);
      *result = it->descriptor();
      return 0;
  }
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:
  baltzo::LocalTimeDescriptor result;
  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());
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:
      baltzo::DataFileLoader loader;
      loader.configureRootPath("./test");
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: Finally, at the end of this scope the guard is destroyed, and the default Zoneinfo cache is restored to its previous value:
      }
      assert(&cache != baltzo::DefaultZoneinfoCache::defaultCache());

      // ...
  }