// baltzo_localtimeoffsetutil.t.cpp                                   -*-C++-*-
#include <baltzo_localtimeoffsetutil.h>

#include <baltzo_localtimedescriptor.h>
#include <baltzo_defaultzoneinfocache.h>  // for testing only
#include <baltzo_testloader.h>            // for testing only
#include <baltzo_zoneinfo.h>
#include <baltzo_zoneinfocache.h>         // for testing only
#include <baltzo_zoneinfoutil.h>          // for testing only

#include <bslmt_barrier.h>       // case -1
#include <bslmt_configuration.h> // case -1
#include <bslmt_threadutil.h>    // case -1
#include <bdlt_epochutil.h>
#include <bdlt_iso8601util.h>                // case 5
#include <bslma_default.h>
#include <bslma_defaultallocatorguard.h>  // case 5
#include <bslma_testallocator.h>          // case 5

#include <bslmf_assert.h>

#include <bsl_cstdio.h>
#include <bsl_cstdlib.h>
#include <bsl_cstring.h>         // 'strcmp'
#include <bsl_iostream.h>
#include <bsls_assert.h>
#include <bsls_asserttest.h>
#include <bsls_stopwatch.h>      // case -2, -3
#include <bsls_types.h>
#include <bsl_vector.h>          // case -1

#if defined(BSLS_PLATFORM_CMP_MSVC)
#define snprintf _snprintf
#endif

using namespace BloombergLP;
using namespace bsl;

// ============================================================================
//                              TEST PLAN
// ----------------------------------------------------------------------------
//                              Overview
//                              --------
// The component under test is a utility; however, as the functions provided
// all serve to set or report on local time offset information (consisting of
// value semantic types), the test strategy of this component more closely
// resembles that of a VST than of a typical utility.  In particular, we will
// informally categorize certain methods as "Primary Manipulators" and "Basic
// Accessors" validate them, and then use them in tests for other methods.
//
// Primary Manipulators:
//: o 'configure' (the overload with two parameters)
//
// Basic Accessors:
//: o 'loadTimezone'
//: o 'loadLocalTimePeriod'
//
// ----------------------------------------------------------------------------
// CLASS METHODS
                        // *** local time offset methods ***
// [ 6] int localTimeOffset(int *result, const bdlt::Datetime& utc);
// [ 4] bdlt::CurrentTime::LLTOC setLoadLocalTimeOffsetCallback();

                        // *** configure methods ***
// [ 3] int configure();
// [ 3] int configure(const char *timezone);
// [ 2] int configure(const char *timezone, const bdlt::Datetime& utc);

                        // *** accessor methods ***
// [ 2] void loadLocalTimePeriod(LocalTimePeriod *localTimePeriod);
// [ 2] bsl::string loadTimezone(bsl::string *timezone);
// [ 6] int updateCount();
// ----------------------------------------------------------------------------
// [ 1] BREATHING TEST
// [ 7] USAGE EXAMPLE
// [ 2] BOOTSTRAP1: int updateCount();
// [ 3] BOOTSTRAP2: int updateCount();
// [ 5] CONCERN: This component uses the default global allocator.
// [ 5] CONCERN: The static members have the expected initial values.
// [-1] CONCERN: The public methods of this component are *thread-safe*.
// [-2] CONCERN: Performance on cache hits.
// [-3] CONCERN: Performance on cache misses.

// ============================================================================
//                      STANDARD BDE ASSERT TEST MACRO
// ----------------------------------------------------------------------------

static int testStatus = 0;
static void aSsErT(int c, const char *s, int i)
{
    if (c) {
        cout << "Error " << __FILE__ << "(" << i << "): " << s
             << "    (failed)" << endl;
        if (testStatus >= 0 && testStatus <= 100) ++testStatus;
    }
}
#define ASSERT(X) { aSsErT(!(X), #X, __LINE__); }

// ============================================================================
//                   STANDARD BDE LOOP-ASSERT TEST MACROS
// ----------------------------------------------------------------------------

#define LOOP_ASSERT(I,X) { \
   if (!(X)) { cout << #I << ": " << I << "\n"; aSsErT(1, #X, __LINE__); }}

#define LOOP2_ASSERT(I,J,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " \
              << J << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP3_ASSERT(I,J,K,X) { \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " \
                    << J << "\t" \
                    << #K << ": " << K <<  "\n"; aSsErT(1, #X, __LINE__); } }

// ============================================================================
//                     SEMI-STANDARD TEST OUTPUT MACROS
// ----------------------------------------------------------------------------

#define P(X) cout << #X " = " << (X) << endl; // Print identifier and value.
#define Q(X) cout << "<| " #X " |>" << endl;  // Quote identifier literally.
#define P_(X) cout << #X " = " << (X) << ", "<< flush; // P(X) without '\n'
#define T_  cout << "\t" << flush;          // Print a tab (w/o newline)
#define L_ __LINE__                           // current Line number

bool             g_verbose;
bool         g_veryVerbose;
bool     g_veryVeryVerbose;
bool g_veryVeryVeryVerbose;

// ============================================================================
//                     NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT_SAFE_PASS(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_PASS(EXPR)
#define ASSERT_SAFE_FAIL(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_FAIL(EXPR)
#define ASSERT_PASS(EXPR)      BSLS_ASSERTTEST_ASSERT_PASS(EXPR)
#define ASSERT_FAIL(EXPR)      BSLS_ASSERTTEST_ASSERT_FAIL(EXPR)
#define ASSERT_OPT_PASS(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_PASS(EXPR)
#define ASSERT_OPT_FAIL(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_FAIL(EXPR)

// ============================================================================
//                   GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------

typedef baltzo::LocalTimeOffsetUtil Util;

const char *NY  = "America/New_York";
const char *BE  = "Europe/Berlin";
const char *RY  = "Asia/Riyadh";
const char *SA  = "Asia/Saigon";
const char *GMT = "Etc/GMT";
const char *GP1 = "Etc/GMT+1";
const char *GM1 = "Etc/GMT-1";

// ============================================================================
//                             GLOBAL TEST DATA
// ----------------------------------------------------------------------------

const char *DEFAULT_TZ_ARRAY[]   = { NY, BE, RY, SA, GMT, GP1, GM1 };
const int   DEFAULT_NUM_TZ_ARRAY = sizeof  DEFAULT_TZ_ARRAY
                                 / sizeof *DEFAULT_TZ_ARRAY;

const bdlt::Datetime DEFAULT_DT_ARRAY[] = { bdlt::Datetime(2012,  1,  1),
                                           bdlt::Datetime(2013,  6, 20),
                                           bdlt::Datetime(2014, 12, 31)
                                          };
const int DEFAULT_NUM_DT_ARRAY = sizeof  DEFAULT_DT_ARRAY
                               / sizeof *DEFAULT_DT_ARRAY;

#ifdef BSLS_PLATFORM_CPU_32_BIT
#define SUFFICIENTLY_LONG_STRING "123456789012345678901234567890123"
#else  // 64_BIT
#define SUFFICIENTLY_LONG_STRING "12345678901234567890123456789012" \
                                 "123456789012345678901234567890123"
#endif
BSLMF_ASSERT(sizeof SUFFICIENTLY_LONG_STRING > sizeof(bsl::string));

const char *const LONG_STRING    = "a_"   SUFFICIENTLY_LONG_STRING;
const char *const LONGER_STRING  = "ab_"  SUFFICIENTLY_LONG_STRING;
const char *const LONGEST_STRING = "abc_" SUFFICIENTLY_LONG_STRING;

// ============================================================================
//                            TEST TIME ZONE DATA
// ----------------------------------------------------------------------------

// America/New_York
static const unsigned char AMERICA_NEW_YORK_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x9e, 0xa6, 0x1e, 0x70,
    0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, 0xa1, 0x9a, 0xcd, 0x60,
    0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, 0xa4, 0x6a, 0xae, 0x70,
    0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, 0xa7, 0x15, 0x89, 0x60,
    0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, 0xaa, 0x13, 0x8e, 0xf0,
    0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, 0xac, 0xbe, 0x69, 0xe0,
    0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, 0xaf, 0xb3, 0x34, 0xf0,
    0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, 0xb2, 0x67, 0x4a, 0x60,
    0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, 0xb5, 0x5c, 0x15, 0x70,
    0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, 0xb8, 0x06, 0xf0, 0x60,
    0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, 0xbb, 0x04, 0xf5, 0xf0,
    0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, 0xbd, 0xaf, 0xd0, 0xe0,
    0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, 0xc0, 0xa4, 0x9b, 0xf0,
    0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, 0xc3, 0x4f, 0x76, 0xe0,
    0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, 0xc6, 0x4d, 0x7c, 0x70,
    0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, 0xc8, 0xf8, 0x57, 0x60,
    0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, 0xcb, 0x88, 0xf0, 0x70,
    0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, 0xd3, 0x75, 0xe4, 0xf0,
    0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, 0xd6, 0x20, 0xbf, 0xe0,
    0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, 0xd9, 0x15, 0x8a, 0xf0,
    0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, 0xdb, 0xc0, 0x65, 0xe0,
    0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, 0xde, 0xbe, 0x6b, 0x70,
    0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, 0xe1, 0x69, 0x46, 0x60,
    0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, 0xe4, 0x5e, 0x11, 0x70,
    0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, 0xe7, 0x37, 0x10, 0xe0,
    0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, 0xea, 0x06, 0xf1, 0xf0,
    0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, 0xec, 0xd6, 0xb6, 0xe0,
    0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, 0xef, 0xaf, 0xd2, 0x70,
    0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, 0xf2, 0x7f, 0x97, 0x60,
    0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, 0xf5, 0x4f, 0x78, 0x70,
    0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, 0xf8, 0x28, 0x77, 0xe0,
    0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, 0xfa, 0xf8, 0x58, 0xf0,
    0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, 0xfd, 0xc8, 0x1d, 0xe0,
    0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, 0x00, 0x97, 0xfe, 0xf0,
    0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, 0x03, 0x70, 0xfe, 0x60,
    0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, 0x06, 0x40, 0xdf, 0x70,
    0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, 0x09, 0x10, 0xa4, 0x60,
    0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, 0x0b, 0xe0, 0x85, 0x70,
    0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, 0x0e, 0xb9, 0x84, 0xe0,
    0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, 0x11, 0x89, 0x65, 0xf0,
    0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, 0x14, 0x59, 0x2a, 0xe0,
    0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, 0x17, 0x29, 0x0b, 0xf0,
    0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, 0x1a, 0x02, 0x0b, 0x60,
    0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, 0x1c, 0xd1, 0xec, 0x70,
    0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, 0x1f, 0xa1, 0xb1, 0x60,
    0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, 0x22, 0x55, 0xe2, 0xf0,
    0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, 0x25, 0x4a, 0x91, 0xe0,
    0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, 0x27, 0xfe, 0xc3, 0x70,
    0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, 0x2a, 0xea, 0x37, 0xe0,
    0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, 0x2d, 0x9e, 0x69, 0x70,
    0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, 0x30, 0x93, 0x18, 0x60,
    0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, 0x33, 0x47, 0x49, 0xf0,
    0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, 0x36, 0x32, 0xbe, 0x60,
    0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, 0x38, 0xe6, 0xef, 0xf0,
    0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, 0x3b, 0xdb, 0x9e, 0xe0,
    0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, 0x3e, 0x8f, 0xd0, 0x70,
    0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, 0x41, 0x84, 0x7f, 0x60,
    0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, 0x44, 0x2f, 0x76, 0x70,
    0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, 0x47, 0x2d, 0x5f, 0xe0,
    0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, 0x49, 0xb3, 0x6c, 0xf0,
    0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, 0x4c, 0xd6, 0x40, 0x60,
    0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, 0x4f, 0x5c, 0x4d, 0x70,
    0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, 0x52, 0x75, 0xe6, 0x60,
    0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, 0x54, 0xfb, 0xf3, 0x70,
    0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, 0x58, 0x1e, 0xc6, 0xe0,
    0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, 0x5a, 0xa4, 0xd3, 0xf0,
    0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, 0x5d, 0xbe, 0x6c, 0xe0,
    0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, 0x60, 0x4d, 0xb4, 0x70,
    0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, 0x63, 0x67, 0x4d, 0x60,
    0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, 0x65, 0xed, 0x5a, 0x70,
    0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, 0x69, 0x06, 0xf3, 0x60,
    0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, 0x6b, 0x96, 0x3a, 0xf0,
    0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, 0x6e, 0xaf, 0xd3, 0xe0,
    0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, 0x71, 0x35, 0xe0, 0xf0,
    0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, 0x74, 0x4f, 0x79, 0xe0,
    0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, 0x76, 0xde, 0xc1, 0x70,
    0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, 0x79, 0xf8, 0x5a, 0x60,
    0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, 0x7c, 0x7e, 0x67, 0x70,
    0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, 0x7f, 0x98, 0x00, 0x60,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x00, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x04, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0x45, 0x44, 0x54, 0x00, 0x45,
    0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa5,
    0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa8,
    0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xaa,
    0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xad,
    0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xb0,
    0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb3,
    0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb6,
    0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb9,
    0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbb,
    0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xbe,
    0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc1,
    0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc4,
    0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xc7,
    0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, 0xca,
    0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2,
    0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd7,
    0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd9,
    0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xdc,
    0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdf,
    0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe2,
    0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe5,
    0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe8,
    0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xea,
    0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xed,
    0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf3,
    0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf6,
    0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xfb,
    0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07,
    0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x09,
    0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0c,
    0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f,
    0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x12,
    0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x18,
    0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x29,
    0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x37,
    0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x74,
    0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54,
    0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54,
    0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x2c,
    0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31,
    0x2e, 0x30, 0x0a
};

// GMT
static const unsigned char GMT_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4d,
    0x54, 0x00, 0x00, 0x00, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0a,
};

// Europe/Rome
static const unsigned char EUROPE_ROME_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x9b, 0x37, 0xa6, 0xf0,
    0x9b, 0xd5, 0xda, 0xf0, 0x9c, 0xc5, 0xcb, 0xf0, 0x9d, 0xb5, 0xbc, 0xf0,
    0x9e, 0x89, 0xfe, 0x70, 0x9f, 0x9e, 0xd9, 0x70, 0xa0, 0x60, 0xa5, 0xf0,
    0xa1, 0x7e, 0xbb, 0x70, 0xa2, 0x5c, 0x37, 0x70, 0xa3, 0x4c, 0x28, 0x70,
    0xc8, 0x6c, 0x35, 0xf0, 0xcc, 0xe7, 0x4b, 0x10, 0xcd, 0xa9, 0x17, 0x90,
    0xce, 0xa2, 0x43, 0x10, 0xcf, 0x92, 0x34, 0x10, 0xd0, 0x07, 0x5f, 0x60,
    0xd0, 0x6e, 0x42, 0x70, 0xd1, 0x72, 0x16, 0x10, 0xd2, 0x4c, 0xd2, 0xf0,
    0xd3, 0x3e, 0x31, 0x90, 0xd4, 0x49, 0xd2, 0x10, 0xd5, 0x1d, 0xf7, 0x70,
    0xd6, 0x29, 0x97, 0xf0, 0xd6, 0xeb, 0x80, 0x90, 0xd8, 0x09, 0x96, 0x10,
    0xf9, 0x33, 0xb5, 0xf0, 0xf9, 0xd9, 0xc4, 0xe0, 0xfb, 0x1c, 0xd2, 0x70,
    0xfb, 0xb9, 0xa6, 0xe0, 0xfc, 0xfc, 0xb4, 0x70, 0xfd, 0x99, 0x88, 0xe0,
    0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0x82, 0xa5, 0x60, 0x00, 0xc5, 0xb2, 0xf0,
    0x01, 0x62, 0x87, 0x60, 0x02, 0x9c, 0x5a, 0x70, 0x03, 0x42, 0x77, 0x70,
    0x04, 0x85, 0x76, 0xf0, 0x05, 0x2b, 0x85, 0xe0, 0x06, 0x6e, 0x93, 0x70,
    0x07, 0x0b, 0x67, 0xe0, 0x08, 0x45, 0x3a, 0xf0, 0x08, 0xeb, 0x49, 0xe0,
    0x0a, 0x2e, 0x57, 0x70, 0x0a, 0xcb, 0x39, 0xf0, 0x0c, 0x0e, 0x39, 0x70,
    0x0c, 0xab, 0x1b, 0xf0, 0x0d, 0xe4, 0xe0, 0xf0, 0x0e, 0x8a, 0xfd, 0xf0,
    0x0f, 0xcd, 0xfd, 0x70, 0x10, 0x74, 0x1a, 0x70, 0x11, 0xad, 0xdf, 0x70,
    0x12, 0x53, 0xfc, 0x70, 0x12, 0xce, 0x97, 0xf0, 0x13, 0x4d, 0x44, 0x10,
    0x14, 0x33, 0xfa, 0x90, 0x15, 0x23, 0xeb, 0x90, 0x16, 0x13, 0xdc, 0x90,
    0x17, 0x03, 0xcd, 0x90, 0x17, 0xf3, 0xbe, 0x90, 0x18, 0xe3, 0xaf, 0x90,
    0x19, 0xd3, 0xa0, 0x90, 0x1a, 0xc3, 0x91, 0x90, 0x1b, 0xbc, 0xbd, 0x10,
    0x1c, 0xac, 0xae, 0x10, 0x1d, 0x9c, 0x9f, 0x10, 0x1e, 0x8c, 0x90, 0x10,
    0x1f, 0x7c, 0x81, 0x10, 0x20, 0x6c, 0x72, 0x10, 0x21, 0x5c, 0x63, 0x10,
    0x22, 0x4c, 0x54, 0x10, 0x23, 0x3c, 0x45, 0x10, 0x24, 0x2c, 0x36, 0x10,
    0x25, 0x1c, 0x27, 0x10, 0x26, 0x0c, 0x18, 0x10, 0x27, 0x05, 0x43, 0x90,
    0x27, 0xf5, 0x34, 0x90, 0x28, 0xe5, 0x25, 0x90, 0x29, 0xd5, 0x16, 0x90,
    0x2a, 0xc5, 0x07, 0x90, 0x2b, 0xb4, 0xf8, 0x90, 0x2c, 0xa4, 0xe9, 0x90,
    0x2d, 0x94, 0xda, 0x90, 0x2e, 0x84, 0xcb, 0x90, 0x2f, 0x74, 0xbc, 0x90,
    0x30, 0x64, 0xad, 0x90, 0x31, 0x5d, 0xd9, 0x10, 0x32, 0x72, 0xb4, 0x10,
    0x33, 0x3d, 0xbb, 0x10, 0x34, 0x52, 0x96, 0x10, 0x35, 0x1d, 0x9d, 0x10,
    0x36, 0x32, 0x78, 0x10, 0x36, 0xfd, 0x7f, 0x10, 0x38, 0x1b, 0x94, 0x90,
    0x38, 0xdd, 0x61, 0x10, 0x39, 0xfb, 0x76, 0x90, 0x3a, 0xbd, 0x43, 0x10,
    0x3b, 0xdb, 0x58, 0x90, 0x3c, 0xa6, 0x5f, 0x90, 0x3d, 0xbb, 0x3a, 0x90,
    0x3e, 0x86, 0x41, 0x90, 0x3f, 0x9b, 0x1c, 0x90, 0x40, 0x66, 0x23, 0x90,
    0x41, 0x84, 0x39, 0x10, 0x42, 0x46, 0x05, 0x90, 0x43, 0x64, 0x1b, 0x10,
    0x44, 0x25, 0xe7, 0x90, 0x45, 0x43, 0xfd, 0x10, 0x46, 0x05, 0xc9, 0x90,
    0x47, 0x23, 0xdf, 0x10, 0x47, 0xee, 0xe6, 0x10, 0x49, 0x03, 0xc1, 0x10,
    0x49, 0xce, 0xc8, 0x10, 0x4a, 0xe3, 0xa3, 0x10, 0x4b, 0xae, 0xaa, 0x10,
    0x4c, 0xcc, 0xbf, 0x90, 0x4d, 0x8e, 0x8c, 0x10, 0x4e, 0xac, 0xa1, 0x90,
    0x4f, 0x6e, 0x6e, 0x10, 0x50, 0x8c, 0x83, 0x90, 0x51, 0x57, 0x8a, 0x90,
    0x52, 0x6c, 0x65, 0x90, 0x53, 0x37, 0x6c, 0x90, 0x54, 0x4c, 0x47, 0x90,
    0x55, 0x17, 0x4e, 0x90, 0x56, 0x2c, 0x29, 0x90, 0x56, 0xf7, 0x30, 0x90,
    0x58, 0x15, 0x46, 0x10, 0x58, 0xd7, 0x12, 0x90, 0x59, 0xf5, 0x28, 0x10,
    0x5a, 0xb6, 0xf4, 0x90, 0x5b, 0xd5, 0x0a, 0x10, 0x5c, 0xa0, 0x11, 0x10,
    0x5d, 0xb4, 0xec, 0x10, 0x5e, 0x7f, 0xf3, 0x10, 0x5f, 0x94, 0xce, 0x10,
    0x60, 0x5f, 0xd5, 0x10, 0x61, 0x7d, 0xea, 0x90, 0x62, 0x3f, 0xb7, 0x10,
    0x63, 0x5d, 0xcc, 0x90, 0x64, 0x1f, 0x99, 0x10, 0x65, 0x3d, 0xae, 0x90,
    0x66, 0x08, 0xb5, 0x90, 0x67, 0x1d, 0x90, 0x90, 0x67, 0xe8, 0x97, 0x90,
    0x68, 0xfd, 0x72, 0x90, 0x69, 0xc8, 0x79, 0x90, 0x6a, 0xdd, 0x54, 0x90,
    0x6b, 0xa8, 0x5b, 0x90, 0x6c, 0xc6, 0x71, 0x10, 0x6d, 0x88, 0x3d, 0x90,
    0x6e, 0xa6, 0x53, 0x10, 0x6f, 0x68, 0x1f, 0x90, 0x70, 0x86, 0x35, 0x10,
    0x71, 0x51, 0x3c, 0x10, 0x72, 0x66, 0x17, 0x10, 0x73, 0x31, 0x1e, 0x10,
    0x74, 0x45, 0xf9, 0x10, 0x75, 0x11, 0x00, 0x10, 0x76, 0x2f, 0x15, 0x90,
    0x76, 0xf0, 0xe2, 0x10, 0x78, 0x0e, 0xf7, 0x90, 0x78, 0xd0, 0xc4, 0x10,
    0x79, 0xee, 0xd9, 0x90, 0x7a, 0xb0, 0xa6, 0x10, 0x7b, 0xce, 0xbb, 0x90,
    0x7c, 0x99, 0xc2, 0x90, 0x7d, 0xae, 0x9d, 0x90, 0x7e, 0x79, 0xa4, 0x90,
    0x7f, 0x8e, 0x7f, 0x90, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x43, 0x45, 0x53, 0x54, 0x00, 0x43,
    0x45, 0x54, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0xff,
    0xff, 0xff, 0xff, 0x3d, 0xbe, 0x1e, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x70,
    0xbc, 0x83, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x37, 0xa6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9b, 0xd5, 0xda, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9c,
    0xc5, 0xcb, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xb5, 0xbc, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0x89, 0xfe, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0x9e, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x60, 0xa5, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x7e, 0xbb, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x5c, 0x37, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x4c, 0x28, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0x6c, 0x35, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xcc,
    0xe7, 0x4b, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcd, 0xa9, 0x17, 0x90, 0xff,
    0xff, 0xff, 0xff, 0xce, 0xa2, 0x43, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcf,
    0x92, 0x34, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x07, 0x5f, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xd0, 0x6e, 0x42, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd1,
    0x72, 0x16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x4c, 0xd2, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x3e, 0x31, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x49, 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x1d, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x29, 0x97, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd6,
    0xeb, 0x80, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x09, 0x96, 0x10, 0xff,
    0xff, 0xff, 0xff, 0xf9, 0x33, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0xd9, 0xc4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x1c, 0xd2, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xfb, 0xb9, 0xa6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc,
    0xfc, 0xb4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x99, 0x88, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x82, 0xa5, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xb2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x62, 0x87, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x9c, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0x77, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x04, 0x85, 0x76, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x05,
    0x2b, 0x85, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x6e, 0x93, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x07, 0x0b, 0x67, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x08,
    0x45, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xeb, 0x49, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x0a, 0x2e, 0x57, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0a,
    0xcb, 0x39, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0e, 0x39, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0c, 0xab, 0x1b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0d,
    0xe4, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x8a, 0xfd, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x0f, 0xcd, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x74, 0x1a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x11, 0xad, 0xdf, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x12, 0x53, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x12,
    0xce, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4d, 0x44, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x33, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x23, 0xeb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x16, 0x13, 0xdc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x03, 0xcd, 0x90, 0x00, 0x00, 0x00, 0x00, 0x17,
    0xf3, 0xbe, 0x90, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xaf, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x19, 0xd3, 0xa0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xc3, 0x91, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xbc, 0xbd, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xac, 0xae, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0x9c, 0x9f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x90, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x7c, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x6c, 0x72, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5c, 0x63, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x4c, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x3c, 0x45, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2c, 0x36, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x1c, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x43, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xf5, 0x34, 0x90, 0x00, 0x00, 0x00, 0x00, 0x28,
    0xe5, 0x25, 0x90, 0x00, 0x00, 0x00, 0x00, 0x29, 0xd5, 0x16, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xc5, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xb4, 0xf8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa4, 0xe9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x94, 0xda, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0x84, 0xcb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0xbc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x64, 0xad, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x5d, 0xd9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xb4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x3d, 0xbb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0x96, 0x10, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x9d, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x36,
    0xfd, 0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x94, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xdd, 0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0x76, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbd, 0x43, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x58, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xa6, 0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x3a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x86, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x1c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x23, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x46, 0x05, 0x90, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x1b, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x25, 0xe7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x43, 0xfd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xc9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x23, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xee, 0xe6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0xc1, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xce, 0xc8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xe3, 0xa3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xae, 0xaa, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xcc, 0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x8e, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xac, 0xa1, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x6e, 0x6e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x8c, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x8a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x6c, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x37, 0x6c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4c, 0x47, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x55, 0x17, 0x4e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x2c, 0x29, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf7, 0x30, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x15, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xd7, 0x12, 0x90, 0x00, 0x00, 0x00, 0x00, 0x59, 0xf5, 0x28, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xb6, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xd5, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x11, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xb4, 0xec, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x7f, 0xf3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x94, 0xce, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x5f, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x7d, 0xea, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3f, 0xb7, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x5d, 0xcc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x1f, 0x99, 0x10, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3d, 0xae, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x08, 0xb5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x1d, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xe8, 0x97, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x68, 0xfd, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xc8, 0x79, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xdd, 0x54, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0xa8, 0x5b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xc6, 0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x88, 0x3d, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xa6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x68, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x51, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x66, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1e, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x45, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75,
    0x11, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2f, 0x15, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xf0, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x0e, 0xf7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd0, 0xc4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xee, 0xd9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0xb0, 0xa6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xce, 0xbb, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x99, 0xc2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xae, 0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x79, 0xa4, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x8e, 0x7f, 0x90, 0x01, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x04, 0x03, 0x04, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03,
    0x02, 0x03, 0x05, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x00,
    0x00, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xb4, 0x00, 0x04, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x4c,
    0x4d, 0x54, 0x00, 0x52, 0x4d, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00,
    0x43, 0x45, 0x54, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0a, 0x43, 0x45, 0x54,
    0x2d, 0x31, 0x43, 0x45, 0x53, 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x35, 0x2e,
    0x30, 0x2c, 0x4d, 0x31, 0x30, 0x2e, 0x35, 0x2e, 0x30, 0x2f, 0x33, 0x0a,
};

// Etc/GMT
static const unsigned char ETC_GMT_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4d,
    0x54, 0x00, 0x00, 0x00, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0a,
};

// Etc/GMT+1
static const unsigned char ETC_GMTP1_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf1, 0xf0,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf1, 0xf0, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2b, 0x31, 0x3e, 0x31, 0x0a,
};

// Etc/GMT+2
static const unsigned char ETC_GMTP2_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xd5, 0xd0,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xd5, 0xd0, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2b, 0x33, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2b, 0x33, 0x3e, 0x33, 0x0a,
};

// Etc/GMT-1
static const unsigned char ETC_GMTM1_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x10,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x00, 0x00, 0x00, 0x54, 0x5a,
    0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00,
    0x47, 0x4d, 0x54, 0x2d, 0x31, 0x00, 0x00, 0x00, 0x0a, 0x3c, 0x47, 0x4d,
    0x54, 0x2d, 0x31, 0x3e, 0x2d, 0x31, 0x0a,
};

// Asia/Riyadh
static const unsigned char ASIA_RIYADH_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xda, 0x61, 0x36, 0xb4,
    0x01, 0x00, 0x00, 0x2b, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x30, 0x00,
    0x04, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff,
    0xff, 0xda, 0x61, 0x36, 0xb4, 0x01, 0x00, 0x00, 0x2b, 0xcc, 0x00, 0x00,
    0x00, 0x00, 0x2a, 0x30, 0x00, 0x04, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x53,
    0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x53, 0x54, 0x2d, 0x33,
    0x0a,
};

// Asia/Saigon
static const unsigned char ASIA_SAIGON_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x88, 0x6f, 0x42, 0x80,
    0x91, 0x5f, 0xee, 0xd0, 0x93, 0x85, 0xb1, 0x90, 0xb7, 0x41, 0xbc, 0x00,
    0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70, 0x00, 0x08, 0x00, 0x00,
    0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00, 0x53, 0x4d, 0x54, 0x00,
    0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff,
    0x88, 0x6f, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x91, 0x5f, 0xee, 0xd0,
    0xff, 0xff, 0xff, 0xff, 0x93, 0x85, 0xb1, 0x90, 0xff, 0xff, 0xff, 0xff,
    0xb7, 0x41, 0xbc, 0x00, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70,
    0x00, 0x08, 0x00, 0x00, 0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00,
    0x53, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x43, 0x54, 0x2d, 0x37, 0x0a,
};

static const unsigned char EUROPE_BERLIN_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90,
    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x9b, 0x0c, 0x17, 0x60,
    0x9b, 0xd5, 0xda, 0xf0, 0x9c, 0xd9, 0xae, 0x90, 0x9d, 0xa4, 0xb5, 0x90,
    0x9e, 0xb9, 0x90, 0x90, 0x9f, 0x84, 0x97, 0x90, 0xc8, 0x09, 0x71, 0x90,
    0xcc, 0xe7, 0x4b, 0x10, 0xcd, 0xa9, 0x17, 0x90, 0xce, 0xa2, 0x43, 0x10,
    0xcf, 0x92, 0x34, 0x10, 0xd0, 0x82, 0x25, 0x10, 0xd1, 0x72, 0x16, 0x10,
    0xd1, 0xb6, 0x96, 0x00, 0xd2, 0x58, 0xbe, 0x80, 0xd2, 0xa1, 0x4f, 0x10,
    0xd2, 0xdb, 0x34, 0xf0, 0xd3, 0x63, 0x1b, 0x90, 0xd4, 0x4b, 0x23, 0x90,
    0xd5, 0x39, 0xd1, 0x20, 0xd5, 0x67, 0xe7, 0x90, 0xd5, 0xa8, 0x73, 0x00,
    0xd6, 0x29, 0xb4, 0x10, 0xd7, 0x2c, 0x1a, 0x10, 0xd8, 0x09, 0x96, 0x10,
    0xd9, 0x02, 0xc1, 0x90, 0xd9, 0xe9, 0x78, 0x10, 0x12, 0xce, 0x97, 0xf0,
    0x13, 0x4d, 0x44, 0x10, 0x14, 0x33, 0xfa, 0x90, 0x15, 0x23, 0xeb, 0x90,
    0x16, 0x13, 0xdc, 0x90, 0x17, 0x03, 0xcd, 0x90, 0x17, 0xf3, 0xbe, 0x90,
    0x18, 0xe3, 0xaf, 0x90, 0x19, 0xd3, 0xa0, 0x90, 0x1a, 0xc3, 0x91, 0x90,
    0x1b, 0xbc, 0xbd, 0x10, 0x1c, 0xac, 0xae, 0x10, 0x1d, 0x9c, 0x9f, 0x10,
    0x1e, 0x8c, 0x90, 0x10, 0x1f, 0x7c, 0x81, 0x10, 0x20, 0x6c, 0x72, 0x10,
    0x21, 0x5c, 0x63, 0x10, 0x22, 0x4c, 0x54, 0x10, 0x23, 0x3c, 0x45, 0x10,
    0x24, 0x2c, 0x36, 0x10, 0x25, 0x1c, 0x27, 0x10, 0x26, 0x0c, 0x18, 0x10,
    0x27, 0x05, 0x43, 0x90, 0x27, 0xf5, 0x34, 0x90, 0x28, 0xe5, 0x25, 0x90,
    0x29, 0xd5, 0x16, 0x90, 0x2a, 0xc5, 0x07, 0x90, 0x2b, 0xb4, 0xf8, 0x90,
    0x2c, 0xa4, 0xe9, 0x90, 0x2d, 0x94, 0xda, 0x90, 0x2e, 0x84, 0xcb, 0x90,
    0x2f, 0x74, 0xbc, 0x90, 0x30, 0x64, 0xad, 0x90, 0x31, 0x5d, 0xd9, 0x10,
    0x32, 0x72, 0xb4, 0x10, 0x33, 0x3d, 0xbb, 0x10, 0x34, 0x52, 0x96, 0x10,
    0x35, 0x1d, 0x9d, 0x10, 0x36, 0x32, 0x78, 0x10, 0x36, 0xfd, 0x7f, 0x10,
    0x38, 0x1b, 0x94, 0x90, 0x38, 0xdd, 0x61, 0x10, 0x39, 0xfb, 0x76, 0x90,
    0x3a, 0xbd, 0x43, 0x10, 0x3b, 0xdb, 0x58, 0x90, 0x3c, 0xa6, 0x5f, 0x90,
    0x3d, 0xbb, 0x3a, 0x90, 0x3e, 0x86, 0x41, 0x90, 0x3f, 0x9b, 0x1c, 0x90,
    0x40, 0x66, 0x23, 0x90, 0x41, 0x84, 0x39, 0x10, 0x42, 0x46, 0x05, 0x90,
    0x43, 0x64, 0x1b, 0x10, 0x44, 0x25, 0xe7, 0x90, 0x45, 0x43, 0xfd, 0x10,
    0x46, 0x05, 0xc9, 0x90, 0x47, 0x23, 0xdf, 0x10, 0x47, 0xee, 0xe6, 0x10,
    0x49, 0x03, 0xc1, 0x10, 0x49, 0xce, 0xc8, 0x10, 0x4a, 0xe3, 0xa3, 0x10,
    0x4b, 0xae, 0xaa, 0x10, 0x4c, 0xcc, 0xbf, 0x90, 0x4d, 0x8e, 0x8c, 0x10,
    0x4e, 0xac, 0xa1, 0x90, 0x4f, 0x6e, 0x6e, 0x10, 0x50, 0x8c, 0x83, 0x90,
    0x51, 0x57, 0x8a, 0x90, 0x52, 0x6c, 0x65, 0x90, 0x53, 0x37, 0x6c, 0x90,
    0x54, 0x4c, 0x47, 0x90, 0x55, 0x17, 0x4e, 0x90, 0x56, 0x2c, 0x29, 0x90,
    0x56, 0xf7, 0x30, 0x90, 0x58, 0x15, 0x46, 0x10, 0x58, 0xd7, 0x12, 0x90,
    0x59, 0xf5, 0x28, 0x10, 0x5a, 0xb6, 0xf4, 0x90, 0x5b, 0xd5, 0x0a, 0x10,
    0x5c, 0xa0, 0x11, 0x10, 0x5d, 0xb4, 0xec, 0x10, 0x5e, 0x7f, 0xf3, 0x10,
    0x5f, 0x94, 0xce, 0x10, 0x60, 0x5f, 0xd5, 0x10, 0x61, 0x7d, 0xea, 0x90,
    0x62, 0x3f, 0xb7, 0x10, 0x63, 0x5d, 0xcc, 0x90, 0x64, 0x1f, 0x99, 0x10,
    0x65, 0x3d, 0xae, 0x90, 0x66, 0x08, 0xb5, 0x90, 0x67, 0x1d, 0x90, 0x90,
    0x67, 0xe8, 0x97, 0x90, 0x68, 0xfd, 0x72, 0x90, 0x69, 0xc8, 0x79, 0x90,
    0x6a, 0xdd, 0x54, 0x90, 0x6b, 0xa8, 0x5b, 0x90, 0x6c, 0xc6, 0x71, 0x10,
    0x6d, 0x88, 0x3d, 0x90, 0x6e, 0xa6, 0x53, 0x10, 0x6f, 0x68, 0x1f, 0x90,
    0x70, 0x86, 0x35, 0x10, 0x71, 0x51, 0x3c, 0x10, 0x72, 0x66, 0x17, 0x10,
    0x73, 0x31, 0x1e, 0x10, 0x74, 0x45, 0xf9, 0x10, 0x75, 0x11, 0x00, 0x10,
    0x76, 0x2f, 0x15, 0x90, 0x76, 0xf0, 0xe2, 0x10, 0x78, 0x0e, 0xf7, 0x90,
    0x78, 0xd0, 0xc4, 0x10, 0x79, 0xee, 0xd9, 0x90, 0x7a, 0xb0, 0xa6, 0x10,
    0x7b, 0xce, 0xbb, 0x90, 0x7c, 0x99, 0xc2, 0x90, 0x7d, 0xae, 0x9d, 0x90,
    0x7e, 0x79, 0xa4, 0x90, 0x7f, 0x8e, 0x7f, 0x90, 0x00, 0x01, 0x02, 0x03,
    0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x00, 0x03,
    0x01, 0x02, 0x03, 0x02, 0x05, 0x00, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07,
    0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x2a, 0x30,
    0x01, 0x09, 0x00, 0x00, 0x2a, 0x30, 0x01, 0x09, 0x00, 0x00, 0x1c, 0x20,
    0x01, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x43, 0x45, 0x53, 0x54,
    0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x4d, 0x54, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x91, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0xff, 0xff,
    0xff, 0xff, 0x6f, 0xa2, 0x61, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x0c,
    0x17, 0x60, 0xff, 0xff, 0xff, 0xff, 0x9b, 0xd5, 0xda, 0xf0, 0xff, 0xff,
    0xff, 0xff, 0x9c, 0xd9, 0xae, 0x90, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xa4,
    0xb5, 0x90, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xb9, 0x90, 0x90, 0xff, 0xff,
    0xff, 0xff, 0x9f, 0x84, 0x97, 0x90, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x09,
    0x71, 0x90, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xe7, 0x4b, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xcd, 0xa9, 0x17, 0x90, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa2,
    0x43, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x92, 0x34, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xd0, 0x82, 0x25, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd1, 0x72,
    0x16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd1, 0xb6, 0x96, 0x00, 0xff, 0xff,
    0xff, 0xff, 0xd2, 0x58, 0xbe, 0x80, 0xff, 0xff, 0xff, 0xff, 0xd2, 0xa1,
    0x4f, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd2, 0xdb, 0x34, 0xf0, 0xff, 0xff,
    0xff, 0xff, 0xd3, 0x63, 0x1b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x4b,
    0x23, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x39, 0xd1, 0x20, 0xff, 0xff,
    0xff, 0xff, 0xd5, 0x67, 0xe7, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xa8,
    0x73, 0x00, 0xff, 0xff, 0xff, 0xff, 0xd6, 0x29, 0xb4, 0x10, 0xff, 0xff,
    0xff, 0xff, 0xd7, 0x2c, 0x1a, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x09,
    0x96, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd9, 0x02, 0xc1, 0x90, 0xff, 0xff,
    0xff, 0xff, 0xd9, 0xe9, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x12, 0xce,
    0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4d, 0x44, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x14, 0x33, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x15, 0x23,
    0xeb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x16, 0x13, 0xdc, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x17, 0x03, 0xcd, 0x90, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf3,
    0xbe, 0x90, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xaf, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x19, 0xd3, 0xa0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc3,
    0x91, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xbc, 0xbd, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x1c, 0xac, 0xae, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x9c,
    0x9f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x90, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x1f, 0x7c, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6c,
    0x72, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5c, 0x63, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x22, 0x4c, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x23, 0x3c,
    0x45, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2c, 0x36, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x25, 0x1c, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0c,
    0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x43, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x27, 0xf5, 0x34, 0x90, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe5,
    0x25, 0x90, 0x00, 0x00, 0x00, 0x00, 0x29, 0xd5, 0x16, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x2a, 0xc5, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xb4,
    0xf8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa4, 0xe9, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x2d, 0x94, 0xda, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x84,
    0xcb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0xbc, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x64, 0xad, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d,
    0xd9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xb4, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x33, 0x3d, 0xbb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52,
    0x96, 0x10, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x9d, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x36, 0x32, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd,
    0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x94, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x38, 0xdd, 0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb,
    0x76, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbd, 0x43, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x3b, 0xdb, 0x58, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa6,
    0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x3a, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x3e, 0x86, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b,
    0x1c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x23, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x41, 0x84, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x42, 0x46,
    0x05, 0x90, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x1b, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x44, 0x25, 0xe7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43,
    0xfd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xc9, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x23, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xee,
    0xe6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0xc1, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x49, 0xce, 0xc8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xe3,
    0xa3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xae, 0xaa, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x4c, 0xcc, 0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x8e,
    0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xac, 0xa1, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x4f, 0x6e, 0x6e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x50, 0x8c,
    0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x8a, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x52, 0x6c, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37,
    0x6c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4c, 0x47, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x55, 0x17, 0x4e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0x2c,
    0x29, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf7, 0x30, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x58, 0x15, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xd7,
    0x12, 0x90, 0x00, 0x00, 0x00, 0x00, 0x59, 0xf5, 0x28, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x5a, 0xb6, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xd5,
    0x0a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x11, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x5d, 0xb4, 0xec, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x7f,
    0xf3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x94, 0xce, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x60, 0x5f, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x61, 0x7d,
    0xea, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3f, 0xb7, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x63, 0x5d, 0xcc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1f,
    0x99, 0x10, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3d, 0xae, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x66, 0x08, 0xb5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0x1d,
    0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xe8, 0x97, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x68, 0xfd, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xc8,
    0x79, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xdd, 0x54, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x6b, 0xa8, 0x5b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6,
    0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x88, 0x3d, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x6e, 0xa6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x68,
    0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x71, 0x51, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66,
    0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1e, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x74, 0x45, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11,
    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2f, 0x15, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x76, 0xf0, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0e,
    0xf7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd0, 0xc4, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x79, 0xee, 0xd9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb0,
    0xa6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xce, 0xbb, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x7c, 0x99, 0xc2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xae,
    0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x79, 0xa4, 0x90, 0x00, 0x00,
    0x00, 0x00, 0x7f, 0x8e, 0x7f, 0x90, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03,
    0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x01, 0x04, 0x02,
    0x03, 0x04, 0x03, 0x06, 0x01, 0x04, 0x03, 0x04, 0x03, 0x04, 0x02, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
    0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x0c, 0x88, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x00, 0x00, 0x2a, 0x30, 0x01, 0x0d, 0x00, 0x00, 0x2a, 0x30, 0x01,
    0x0d, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00,
    0x09, 0x4c, 0x4d, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x43, 0x45,
    0x54, 0x00, 0x43, 0x45, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x01, 0x0a, 0x43, 0x45, 0x54, 0x2d, 0x31, 0x43, 0x45, 0x53, 0x54, 0x2c,
    0x4d, 0x33, 0x2e, 0x35, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x30, 0x2e, 0x35,
    0x2e, 0x30, 0x2f, 0x33, 0x0a
};

// ============================================================================
//                        GLOBAL CLASSES FOR TESTING
// ----------------------------------------------------------------------------

struct LogVerbosityGuard {
    // The Logger verbosity guard disables logging on construction, and
    // re-enables logging, based on the prior default pass-through level, when
    // it goes out of scope and is destroyed.  It is intended to suppress
    // logged output for intentional errors when the test driver is run in
    // non-verbose mode.

    bool                    d_verbose;             // verbose mode does not
                                                   // disable logging

    bsls::LogSeverity::Enum d_defaultPassthrough;  // default passthrough 
                                                   // log level

    explicit LogVerbosityGuard(bool verbose = false)
        // If the optionally specified 'verbose' is 'false' disable logging
        // until this guard is destroyed.
    {
        d_verbose            = verbose;
        d_defaultPassthrough = bsls::Log::severityThreshold();

        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(bsls::LogSeverity::e_FATAL);
        }
    }

    ~LogVerbosityGuard()
        // Set the logging verbosity back to its default state.
    {
        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(d_defaultPassthrough);
        }
    }
};

// ============================================================================
//                             HELPER FUNCTIONS
// ----------------------------------------------------------------------------

struct ThreadArg {
    int            d_offset;
    bdlt::Datetime  d_utcDatetime;
    bslmt::Barrier *d_barrier_p;
};

typedef bsl::vector<struct ThreadArg> ThreadArgs;

extern "C" void *workerThread(void *arg)
{
    ThreadArg *p = static_cast<ThreadArg *>(arg);

    p->d_barrier_p->wait();

    p->d_offset = baltzo::LocalTimeOffsetUtil::localTimeOffset(
                                              p->d_utcDatetime).totalSeconds();
    return 0;
}

typedef bsl::vector<bslmt::ThreadUtil::Handle> Handles;

bdlt::EpochUtil::TimeT64 toTimeT(const bdlt::Datetime& value)
    // Return the interval in seconds from UNIX epoch time of the specified
    // 'value'.  Note that this method is shorthand for
    // 'bdlt::EpochUtil::convertToTimeT64'.
{
    return bdlt::EpochUtil::convertToTimeT64(value);
}

bdlt::Datetime toDatetime(const char *iso8601TimeString)
    // Return the datetime value indicated by the specified
    // 'iso8601TimeString'.  The behavior is undefined unless
    // 'iso8601TimeString' is a null-terminated C-string containing a time
    // description matching the iso8601 specification (see 'bdlt_iso8601util').
{
    bdlt::Datetime time;
    int rc = bdlt::Iso8601Util::parse(&time,
                                  iso8601TimeString,
                                  bsl::strlen(iso8601TimeString));
    BSLS_ASSERT(0 == rc);
    return time;
}

struct TransitionDescription {
    // A 'struct' describing a transitions.  Note that this type is meant to
    // be used to create data tables for use with 'addTransitions'.

    int         d_line;
    const char *d_transitionTime;
    int         d_offsetMins;
    const char *d_abbrev;
    bool        d_isDst;
};

void addTransitions(baltzo::Zoneinfo            *result,
                    const TransitionDescription *descriptions,
                    int                          numDescriptions)
    // Insert to the specified 'result' the contiguous sequence of specified
    // 'descriptions', of length 'numDescriptions'.
{
    BSLS_ASSERT(result);

    for (int i = 0; i < numDescriptions; ++i) {
        const char *TRANS = descriptions[i].d_transitionTime;
        baltzo::LocalTimeDescriptor desc(descriptions[i].d_offsetMins * 60,
                                        descriptions[i].d_isDst,
                                        descriptions[i].d_abbrev);
        result->addTransition(toTimeT(toDatetime(TRANS)), desc);
    }
}

// ============================================================================
//                               USAGE EXAMPLE
// ----------------------------------------------------------------------------

namespace UsageExample1 {
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Using 'localTimeOffset' as the Local Time Offset Callback
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Suppose we must quickly generate time stamp values in local time (e.g., on
// records for a high frequency logger) and the default performance of the
// relevant methods of 'bdlt::CurrentTime' is inadequate.  Further suppose that
// we must do so arbitrary time values and time zones.  Those requirements can
// be met by installing the 'localTimeOffset' method of
// 'baltzo::LocalTimeOffsetUtil' as the local time callback used by
// 'bdlt::CurrentTime'.
//
// First, specify the time zone to be used by the callback and a UTC date time
// for the initial offset information in the cache.
//..
void main1()
{
    ASSERT(0 == baltzo::LocalTimeOffsetUtil::updateCount());

    int status = baltzo::LocalTimeOffsetUtil::configure("America/New_York",
                                                        bdlt::Datetime(2013,
                                                                         2,
                                                                        26));
    ASSERT(0 == status);
    ASSERT(1 == baltzo::LocalTimeOffsetUtil::updateCount());

    bsl::string timezone;

    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(0 == strcmp("America/New_York", timezone.c_str()));
//..
// Notice that the value returned by the 'updateCount' method is increased by
// one after then time zone information has been set.
//
// Then, use the 'setLoadLocalTimeOffsetCallback' method to set the
// 'localTimeOffset' of 'baltzo::LocalTimeOffsetUtil' as the local time
// offset callback used in 'bdlt::CurrentTime'.
//..
    bdlt::LocalTimeOffset::LocalTimeOffsetCallback previousCallback =
                 baltzo::LocalTimeOffsetUtil::setLoadLocalTimeOffsetCallback();

    ASSERT(&baltzo::LocalTimeOffsetUtil::localTimeOffset
        == bdlt::LocalTimeOffset::localTimeOffsetCallback());
//..
// Notice that previously installed callback was saved so we can restore it, if
// needed.
//
// Now, calls to 'bdlt::CurrentTime' methods will use the method we installed.
// For example, we can check the time offset in New York for three dates of
// interest:
//..
    int offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 2, 26))
                                                               .totalSeconds();
    ASSERT(        0 == status);
    ASSERT(-5 * 3600 == offsetInSeconds);
    ASSERT(        1 == baltzo::LocalTimeOffsetUtil::updateCount());

    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));

    offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 7, 4))
                                                               .totalSeconds();
    ASSERT(-4 * 3600 == offsetInSeconds);
    ASSERT(        2 == baltzo::LocalTimeOffsetUtil::updateCount());
    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));

    offsetInSeconds =
        bdlt::LocalTimeOffset::localTimeOffset(bdlt::Datetime(2013, 12, 21))
                                                               .totalSeconds();
    ASSERT(-5 * 3600 == offsetInSeconds);
    ASSERT(        3 == baltzo::LocalTimeOffsetUtil::updateCount());
    baltzo::LocalTimeOffsetUtil::loadTimezone(&timezone);
    ASSERT(        0 == strcmp("America/New_York", timezone.c_str()));
//..
// Notice that the value returned by 'updateCount()' is unchanged by our first
// request, but incremented by the second and third request, which transitions
// into and then out of daylight saving time.  Also notice that the updates
// change the offset information but do not change the timezone.
//
// Finally, we restore the original local time callback.
//..
    previousCallback = bdlt::LocalTimeOffset::setLocalTimeOffsetCallback(
                                                             previousCallback);
    ASSERT(previousCallback == &baltzo::LocalTimeOffsetUtil::localTimeOffset);
//..
}
}  // close namespace UsageExample1

// ============================================================================
//                               MAIN PROGRAM
// ----------------------------------------------------------------------------

int main(int argc, char *argv[])
{
    int                 test = argc > 1 ? atoi(argv[1]) : 0;
    bool             verbose = argc > 2;
    bool         veryVerbose = argc > 3;
    bool     veryVeryVerbose = argc > 4;
    bool veryVeryVeryVerbose = argc > 5;

                g_verbose =             verbose;
            g_veryVerbose =         veryVerbose;
        g_veryVeryVerbose =     veryVeryVerbose;
    g_veryVeryVeryVerbose = veryVeryVeryVerbose;

    cout << "TEST " << __FILE__ << " CASE " << test << endl;

    bslma::TestAllocator allocator("Test", veryVeryVeryVerbose);
    bslma::TestAllocator defaultAllocator("Default", veryVeryVeryVerbose);
    bslma::DefaultAllocatorGuard guard(&defaultAllocator);
    bslma::TestAllocator *Z = &allocator;

    baltzo::TestLoader     testLoader(Z);
    baltzo::ZoneinfoCache  testCache(&testLoader, Z);
    ASSERT(0 == testLoader.setTimeZone("GMT",
                         reinterpret_cast<const char *>(GMT_DATA),
                         sizeof(GMT_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT",
                         reinterpret_cast<const char *>(ETC_GMT_DATA),
                         sizeof(ETC_GMT_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT+1",
                         reinterpret_cast<const char *>(ETC_GMTP1_DATA),
                         sizeof(ETC_GMTP1_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT+2",
                         reinterpret_cast<const char *>(ETC_GMTP2_DATA),
                         sizeof(ETC_GMTP2_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Etc/GMT-1",
                         reinterpret_cast<const char *>(ETC_GMTM1_DATA),
                         sizeof(ETC_GMTM1_DATA)));
    ASSERT(0 == testLoader.setTimeZone("America/New_York",
                         reinterpret_cast<const char *>(AMERICA_NEW_YORK_DATA),
                         sizeof(AMERICA_NEW_YORK_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Asia/Riyadh",
                         reinterpret_cast<const char *>(ASIA_RIYADH_DATA),
                         sizeof(ASIA_RIYADH_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Asia/Saigon",
                         reinterpret_cast<const char *>(ASIA_SAIGON_DATA),
                         sizeof(ASIA_SAIGON_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Europe/Rome",
                         reinterpret_cast<const char *>(EUROPE_ROME_DATA),
                         sizeof(EUROPE_ROME_DATA)));
    ASSERT(0 == testLoader.setTimeZone("Europe/Berlin",
                         reinterpret_cast<const char *>(EUROPE_BERLIN_DATA),
                         sizeof(EUROPE_BERLIN_DATA)));

    baltzo::DefaultZoneinfoCache::setDefaultCache(&testCache);

    switch (test) { case 0:
      case 7: {
        // --------------------------------------------------------------------
        // USAGE EXAMPLE
        //   Extracted from component header file.
        //
        // Concerns:
        //: 1 The usage example provided in the component header file compiles,
        //:   links, and runs as shown.
        //
        // Plan:
        //: 1 Incorporate usage example from header into test driver, remove
        //:   leading comment characters, and replace 'assert' with 'ASSERT'.
        //:   (C-1)
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "USAGE EXAMPLE" << endl
                          << "=============" << endl;

        UsageExample1::main1();

      } break;
      case 6: {
        // --------------------------------------------------------------------
        // CALLBACK FUNCTION
        //
        // Concerns:
        //: 1 The callback function loads the correct offset and returns 0 for
        //:   arbitrary Zoneinfo timezones for arbitrary UTC datetimes.
        //:
        //: 2 For a given timezone, the callback function updates the cached
        //:   local time offset information on transitions into and out of
        //:   daylight saving time.
        //:
        //: 3 The value returned by the 'updateCall' method increases by one
        //:   for each transition into and out of daylight saving time, and for
        //:   no other invocations of the callback.
        //
        // Plan:
        //: 1 Using the array-driven approach, compare the results of calling
        //:   to those obtained from an independent source.  (C-1)
        //:
        //: 2 Using the array-driven approach, for a fixed timezone, invoke the
        //:   call back method on both sides of the boundaries of daylight
        //:   saving time for a year.  Confirm that the expected values are
        //:   returned throughout, and that the static members are updated when
        //:   times transition into and out of daylight saving time.  Also
        //:   confirm the same behavior when the series of datetimes are used
        //:   in reverse order.  (C-2..3)
        //
        // Testing:
        //  int localTimeOffset(int *result, const bdlt::Datetime& utc);
        //  int updateCount();
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "CALLBACK FUNCTION" << endl
                          << "=================" << endl;

        if (verbose) cout << "\nCheck arbitrary timezones and UTCs" << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                for (int j = 0; j < DEFAULT_NUM_DT_ARRAY; ++j) {
                    const bdlt::Datetime& UTC = DEFAULT_DT_ARRAY[j];
                    int                  status;

                    if (veryVerbose) { T_ P(UTC) }

                    baltzo::LocalTimePeriod expected;
                    status = baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc(
                                                                    &expected,
                                                                    TIMEZONE,
                                                                    UTC);
                    ASSERT(0 == status);

                    status = Util::configure(TIMEZONE, UTC);
                    ASSERT(0 == status);

                    int reportedOffset =
                                     Util::localTimeOffset(UTC).totalSeconds();
                    ASSERT(expected.descriptor().utcOffsetInSeconds()
                        == reportedOffset);
                }
            }
        }

        if (verbose) cout << "\nCheck daylight saving transitions" << endl;
        {
            bdlt::Datetime newYearsDay(2013,  1,  1, 0);
            int status = Util::configure("America/New_York", newYearsDay);
            ASSERT(0 == status);

            bdlt::Datetime  startOfDst(2013,  3, 10, 7);
            bdlt::Datetime resumeOfStd(2013, 11,  3, 6);

            bdlt::Datetime startOfDstMinus(startOfDst);
                          startOfDstMinus.addMilliseconds(-1);

            bdlt::Datetime startOfDstPlus(startOfDst);
                          startOfDstPlus.addMilliseconds(1);

            bdlt::Datetime resumeOfStdMinus(resumeOfStd);
                          resumeOfStdMinus.addMilliseconds(-1);

            bdlt::Datetime resumeOfStdPlus(resumeOfStd);
                          resumeOfStdPlus.addMilliseconds(1);

            baltzo::LocalTimePeriod priorLocalTimePeriod;
            Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            int                    priorUpdateCount     = Util::updateCount();
            bsl::string            priorTimezone;
            Util::loadTimezone(&priorTimezone);

            const struct {
                int           d_line;
                bdlt::Datetime d_utcDatetime;
                int           d_expectedOffset;
            } DATA[] = {

                //LINE UTC_DATETIME      EXP. OFFSET
                //---- ----------------  -----------
                { L_,  startOfDstMinus,    -5 * 3600 },
                { L_,  startOfDst,         -4 * 3600 },
                { L_,  startOfDstPlus,     -4 * 3600 },

                { L_,  resumeOfStdMinus,   -4 * 3600 },
                { L_,  resumeOfStd,        -5 * 3600 },
                { L_,  resumeOfStdPlus,    -5 * 3600 },
            };
            const int NUM_DATA = sizeof DATA / sizeof *DATA;

            for (int ti = 0; ti < NUM_DATA; ++ti) {
                const int            LINE         = DATA[ti].d_line;
                const bdlt::Datetime& UTC_DATETIME = DATA[ti].d_utcDatetime;
                const int            EXP_OFFSET   = DATA[ti].d_expectedOffset;

                if (veryVeryVerbose) { T_ P(ti) }
                if (veryVerbose) { T_ P_(LINE) P_(UTC_DATETIME) P(EXP_OFFSET) }

                int reportedOffset =
                            Util::localTimeOffset(UTC_DATETIME).totalSeconds();
                ASSERT(EXP_OFFSET == reportedOffset);

                bsl::string timezone; Util::loadTimezone(&timezone);
                LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant

                if (ti > 0 && DATA[ti - 1].d_expectedOffset != EXP_OFFSET) {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod != localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount + 1 ==
                                                          Util::updateCount());

                } else {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod == localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount     ==
                                                          Util::updateCount());
                }

                priorUpdateCount = Util::updateCount();
                Util::loadTimezone(&priorTimezone);
                Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            }

            ASSERT(0 <= NUM_DATA - 1);

            for (int ti = NUM_DATA - 1; 0 <= ti; --ti) {
                const int            LINE         = DATA[ti].d_line;
                const bdlt::Datetime& UTC_DATETIME = DATA[ti].d_utcDatetime;
                const int            EXP_OFFSET   = DATA[ti].d_expectedOffset;

                if (veryVeryVerbose) { T_ P(ti) }
                if (veryVerbose) { T_ P_(LINE) P_(UTC_DATETIME) P(EXP_OFFSET) }

                int reportedOffset =
                            Util::localTimeOffset(UTC_DATETIME).totalSeconds();
                ASSERT(EXP_OFFSET == reportedOffset);

                bsl::string timezone; Util::loadTimezone(&timezone);
                LOOP_ASSERT(LINE, priorTimezone == timezone); // invariant

                if (ti < NUM_DATA - 1
                 && DATA[ti + 1].d_expectedOffset != EXP_OFFSET) {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod != localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount + 1 ==
                                                          Util::updateCount());

                } else {
                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);
                    LOOP_ASSERT(LINE, priorLocalTimePeriod == localTimePeriod);
                    LOOP_ASSERT(LINE, priorUpdateCount     ==
                                                          Util::updateCount());
                }

                priorUpdateCount = Util::updateCount();
                Util::loadTimezone(&priorTimezone);
                Util::loadLocalTimePeriod(&priorLocalTimePeriod);
            }
        }
      } break;
      case 5: {
        // --------------------------------------------------------------------
        // STATIC INITIALIZATION
        //
        // Concerns:
        //: 1 The 'updateCount' method returns 0 before configuration.
        //:
        //: 2 The static members of 'baltzo::LocalTimeOffsetUtil' that take
        //:   allocators use the default global allocator.
        //:
        // Plan:
        //: 1 Before any other use of 'baltzo::LocalTimeOffsetUtil', check the
        //:   value returned by the 'updateCount' method.
        //:
        //: 2 Install the test allocators as the default and global allocators.
        //:   Since the memory for the static members will be deleted after the
        //:   return of 'main', we use a statically initialized allocator for
        //:   the global allocator which will outlive the static members.
        //:
        //: 3 Using 'baltzo::TestLoader' and several helper functions, define a
        //:   time zone with a description and a timezone name sufficiently
        //:   long as to require memory allocation from 'bsl::string' (which
        //:   has a short string optimization).  Construct a
        //:   'baltzo::ZoneinfoCache' using the configured test loader and
        //:   install that cache as the default timezone cache.
        //:
        //: 4 Configure our mechanism to use the custom-made timezone.  Check
        //:   the block count of each allocator before and after configuration
        //:   and compare to the expected values.
        //
        // Testing:
        //  CONCERN: This component uses the global allocator.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "STATIC INITIALIZATION" << endl
                          << "=====================" << endl;

        if (verbose) cout << "\nCheck Initial Values" << endl;
        {
            ASSERT(0 == Util::updateCount());
        }

        if (verbose) cout << "\nCheck For Global Allocators" << endl;
        {
            const char LONG_DESCRIPTION[] = "Description: "
                                                      SUFFICIENTLY_LONG_STRING;
            const char LONG_TIMEZONE[]    = "Timezone: "
                                                      SUFFICIENTLY_LONG_STRING;

            const TransitionDescription TZ_DATA[] = {
              { L_, "0001-01-01T00:00:00.000",     0, "A",              false},
              { L_, "2013-01-01T12:00:00.000",  1439, LONG_DESCRIPTION, false},
              { L_, "9999-12-31T23:59:59.000",     0, "B",              false}
             };
            const int NUM_TZ_DATA = sizeof TZ_DATA / sizeof *TZ_DATA;

            baltzo::Zoneinfo testZoneInfo;
            addTransitions(&testZoneInfo, TZ_DATA, NUM_TZ_DATA);
            testZoneInfo.setIdentifier(LONG_TIMEZONE);
            ASSERT(baltzo::ZoneinfoUtil::isWellFormed(testZoneInfo));

            baltzo::TestLoader testLoader;
            testLoader.setTimeZone(testZoneInfo);

            baltzo::ZoneinfoCache testCache(&testLoader);
            baltzo::DefaultZoneinfoCache::setDefaultCache(&testCache);

            static bslma::TestAllocator staticGlobalAllocator(
                                                          "global",
                                                          veryVeryVeryVerbose);

            bslma::Default::setGlobalAllocator(&staticGlobalAllocator);

            bslma::TestAllocator da("default", veryVeryVeryVerbose);
            bslma::Default::setDefaultAllocator(&da);

            ASSERT(0 == staticGlobalAllocator.numBlocksInUse());
            ASSERT(0 == da.numBlocksInUse());

            int status = Util::configure(LONG_TIMEZONE,
                                         bdlt::Datetime(2013, 1, 1, 12));

            ASSERT(2 == staticGlobalAllocator.numBlocksInUse());
            ASSERT(0 == da.numBlocksInUse());
        }

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // SETTING THE LOCAL TIME OFFSET CALLBACK
        //
        // Concerns:
        //: 1 The 'setLoadLocalTimeOffsetCallback' method sets the
        //:   'localTimeOffset' method as the current local time offset
        //:   callback used by 'bdlt::CurrentTime'.
        //:
        //: 2 The 'setLoadLocalTimeOffsetCallback' method returns the installed
        //:   previously callback.
        //
        // Plan:
        //: 1 Use the 'bdlt::CurrentTime::currentLocalTimeOffsetCallback'
        //:   method to check the current local time offset callback before and
        //:   after calls to 'setLoadLocalTimeOffsetCallback'.  (C-1)
        //:
        //: 2 Compare the value returned by the initial call to the
        //:   'bdlt::CurrentTime::currentLocalTimeOffsetCallback' method with
        //:   that returned by the 'setLoadLocalTimeOffsetCallback' method.
        //:   (C-2)
        //
        // Testing:
        //   bdlt::CurrentTime::LLTOC setLoadLocalTimeOffsetCallback();
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "SETTING THE LOCAL TIME OFFSET CALLBACK" << endl
                          << "======================================" << endl;

        const bdlt::LocalTimeOffset::LocalTimeOffsetCallback initialCallback =
                              bdlt::LocalTimeOffset::localTimeOffsetCallback();
        ASSERT(&Util::localTimeOffset != initialCallback);


        const bdlt::LocalTimeOffset::LocalTimeOffsetCallback previousCallback =
                                        Util::setLoadLocalTimeOffsetCallback();
        ASSERT(initialCallback == previousCallback);
        ASSERT(&Util::localTimeOffset
            == bdlt::LocalTimeOffset::localTimeOffsetCallback());

      } break;
      case 3: {
        // --------------------------------------------------------------------
        // OTHER MANIPULATORS
        //
        // Concerns:
        //: 1 The other (non-primary) manipulators apply their expected default
        //:   values.
        //:
        //: 2 The manipulators return a non-zero value when an invalid timezone
        //:   is specified, and (QoI) there is no change in the static members.
        //:
        //: 3 The value returned by the 'updateCall' method increases by one
        //:   for each successful call of a 'configure' method, and remains the
        //:   same after unsuccessful calls.
        //:
        //: 4 The value returned by the 'updateCall' method increases by one
        //:   for each successful call of a 'configure' method, and remains the
        //:   same after unsuccessful calls.
        //
        // Plan:
        //: 1 Invoke the non-primary manipulators and compare the results with
        //:   obtained from the primary manipulator using the expected default
        //:   values.  (C-1)
        //:
        //:   o One default value is the current UTC time which, of course,
        //:     changes between the invocation of the two manipulators;
        //:     however, this is only a problem in the unlikely event that the
        //:     local time zone information changes in that short interval.
        //:
        //: 2 Save the values of the static members and call each 'configure'
        //:   method with an unknown timezone.  After each 'configure' call,
        //:   check the return value, and compare the current values of the
        //:   static members to the saved values.  (C-2..4)
        //
        // Testing:
        //   int configure();
        //   int configure(const char *timezone);
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "OTHER MANIPULATORS" << endl
                          << "==================" << endl;

        int      updateCount = Util::updateCount();
        int priorUpdateCount = Util::updateCount();
        ASSERT(0 ==      updateCount);
        ASSERT(0 == priorUpdateCount);

        if (verbose) cout << "\nTesting 'configure(const char *timezone)'"
                          << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                int status = Util::configure(TIMEZONE);
                ASSERT(0 == status);
                bsl::string timezone; Util::loadTimezone(&timezone);
                ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;

                // Race: utcDatetime is changing.

                baltzo::LocalTimePeriod observedLocalTimePeriod;
                Util::loadLocalTimePeriod(&observedLocalTimePeriod);

                bdlt::Datetime now = bdlt::CurrentTime::utc();
                status = Util::configure(TIMEZONE, now);
                ASSERT(0 == status);
                baltzo::LocalTimePeriod localTimePeriod;
                Util::loadLocalTimePeriod(&localTimePeriod);
                ASSERT(localTimePeriod == observedLocalTimePeriod);

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;
            }
        }

        if (verbose) cout << "\nTesting 'configure()' for valid timezones"
                          << endl;
        {
            static char tzEquals[] = "TZ=";

            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                char buffer[80];
                ASSERT(sizeof(buffer) >
                                  sizeof(tzEquals) -1 + strlen(TIMEZONE) + 1);
                snprintf(buffer, sizeof(buffer), "%s%s", tzEquals, TIMEZONE);

                if (veryVeryVerbose) { T_ P(buffer) }

                int status = putenv(buffer);
                ASSERT(0 == status);
                ASSERT(0 == strcmp(TIMEZONE, getenv("TZ")));

                status = Util::configure();

                ASSERT(0 == status);
                bsl::string timezone; Util::loadTimezone(&timezone);
                ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;

                // Race: The UTC datetime  is changing.

                baltzo::LocalTimePeriod observedLocalTimePeriod;
                Util::loadLocalTimePeriod(&observedLocalTimePeriod);

                bdlt::Datetime now = bdlt::CurrentTime::utc();
                status = Util::configure(TIMEZONE, now);
                ASSERT(0 == status);
                baltzo::LocalTimePeriod localTimePeriod;
                Util::loadLocalTimePeriod(&localTimePeriod);
                ASSERT(localTimePeriod == observedLocalTimePeriod);

                updateCount = Util::updateCount();
                ASSERT(priorUpdateCount + 1 == updateCount);
                priorUpdateCount = updateCount;
            }
        }

        if (verbose) cout << "\nTesting Manipulators with invalid timezone"
                          << endl;
        {
            int         status;
            const char *invalidTimezone =    "FOO";
            char buffer[]               = "TZ=FOO";

            bsl::string timezone0;
            Util::loadTimezone(&timezone0);
            baltzo::LocalTimePeriod localTimePeriod0;
            Util::loadLocalTimePeriod(&localTimePeriod0);

            if (veryVeryVerbose) { T_ P(invalidTimezone) }

            {
                LogVerbosityGuard guard;
                status = Util::configure(invalidTimezone);
            }

            ASSERT(0                != status);
            bsl::string timezone; Util::loadTimezone(&timezone);
            ASSERT(timezone0        == timezone);
            baltzo::LocalTimePeriod localTimePeriod;
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);

            if (veryVeryVerbose) { T_ P(buffer) }

            status = putenv(buffer);
            ASSERT(0 == status);
            ASSERT(0 == strcmp(invalidTimezone, getenv("TZ")));

            {
                LogVerbosityGuard guard;
                status = Util::configure();
            }

            ASSERT(0                != status);
            Util::loadTimezone(&timezone);
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);
        }

      } break;
      case 2: {
        // --------------------------------------------------------------------
        // PRIMARY MANIPULATOR and BASIC ACCESSORS
        //
        // Concerns:
        //: 1 The primary manipulator can set the cached local time offset
        //:   information for any entry in the Zoneinfo database for arbitrary
        //:   UTC datetime.
        //:
        //: 2 The basic accessors report the currently cached local time offset
        //:   information.
        //:
        //: 3 The primary manipulator returns a non-zero value when an invalid
        //:   timezone is specified, and (QoI) there is no change in the static
        //:   members.
        //:
        //: 4 QoI: Asserted precondition violations are detected when enabled.
        //
        // Plan:
        //: 1 Using the array-driven approach, generate test cases for several
        //:   entries representing several categories of Zoneinfo entries
        //:   (i.e., timezone before and after "Etc/GMT" and "Etc/GMT" itself)
        //:   and for several categories of UTC datetimes (i.e., before,
        //:   during, and after daylight saving time, if defined in a
        //:   timezone).  For each entry confirm that 'configure' returns
        //:   successfully, and use the accessors to confirm that the cached
        //:   information matches the expected results.  The expected results
        //:   for the local time period is obtained using the
        //:   'baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc' method.
        //:   (C-1..2)
        //:
        //: 2 Save the values of the static members, call 'configure' with an
        //:   unknown timezone, check the return value, and compare the current
        //:   values of the static members to the saved values.
        //:
        //: 3 Verify that, in appropriate build modes, defensive checks are
        //:   triggered for invalid attribute values, but not triggered for
        //:   adjacent valid ones (using the 'BSLS_ASSERTTEST_*' macros).
        //:   (C-4)
        //
        // Testing:
        //   int configure(const char *timezone, const bdlt::Datetime& utc);
        //   void loadLocalTimePeriod(LocalTimePeriod *localTimePeriod);
        //   bsl::string loadTimezone(bsl::string *timezone);
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PRIMARY MANIPULATOR and BASIC ACCESSORS" << endl
                          << "=======================================" << endl;

        int      updateCount = Util::updateCount();
        int priorUpdateCount = Util::updateCount();
        ASSERT(0 ==      updateCount);
        ASSERT(0 == priorUpdateCount);

        if (verbose) cout << "\nCheck valid timezones" << endl;
        {
            for (int i = 0; i < DEFAULT_NUM_TZ_ARRAY; ++i) {
                const char *TIMEZONE = DEFAULT_TZ_ARRAY[i];

                if (veryVerbose) { P(TIMEZONE) }

                for (int j = 0; j < DEFAULT_NUM_DT_ARRAY; ++j) {
                    const bdlt::Datetime& UTC = DEFAULT_DT_ARRAY[j];

                    if (veryVerbose) { T_ P(UTC) }

                    int status = Util::configure(TIMEZONE, UTC);
                    ASSERT(0 == status);

                    bsl::string timezone; Util::loadTimezone(&timezone);
                    ASSERT(0 == strcmp(TIMEZONE, timezone.c_str()));

                    updateCount = Util::updateCount();
                    ASSERT(priorUpdateCount + 1 == updateCount);
                    priorUpdateCount = updateCount;

                    baltzo::LocalTimePeriod expectedLocalTimePeriod;

                    status = baltzo::TimeZoneUtil::loadLocalTimePeriodForUtc(
                                                      &expectedLocalTimePeriod,
                                                      TIMEZONE,
                                                      UTC);
                    ASSERT(0 == status);

                    baltzo::LocalTimePeriod localTimePeriod;
                    Util::loadLocalTimePeriod(&localTimePeriod);

                    ASSERT(expectedLocalTimePeriod == localTimePeriod);
                }
            }
        }

        if (verbose) cout << "\nCheck invalid timezone" << endl;
        {
            bsl::string timezone0; Util::loadTimezone(&timezone0);
            baltzo::LocalTimePeriod localTimePeriod0;
            Util::loadLocalTimePeriod(&localTimePeriod0);

            int status;

            {
                LogVerbosityGuard guard;
                status = Util::configure("hello, world", bdlt::Datetime(2013,
                                                                          2,
                                                                         28));
            }
            bsl::string timezone; Util::loadTimezone(&timezone);
            ASSERT(0                != status);
            ASSERT(timezone0        == timezone);
            baltzo::LocalTimePeriod localTimePeriod;
            Util::loadLocalTimePeriod(&localTimePeriod);
            ASSERT(localTimePeriod0 == localTimePeriod);

            updateCount = Util::updateCount();
            ASSERT(priorUpdateCount == updateCount);
        }

        if (verbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertFailureHandlerGuard
                                          hG(bsls::AssertTest::failTestDriver);

            if (veryVerbose) cout << "\t'loadLocalTimePeriod'" << endl;
            {
                baltzo::LocalTimePeriod ltp;
                ASSERT_SAFE_PASS(Util::loadLocalTimePeriod(&ltp));
                ASSERT_SAFE_FAIL(Util::loadLocalTimePeriod(0));
            }

            if (veryVerbose) cout << "\t'loadTimezone'" << endl;
            {
                bsl::string s;
                ASSERT_SAFE_PASS(Util::loadTimezone(&s));
                ASSERT_SAFE_FAIL(Util::loadTimezone( 0));
            }
        }
      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST
        //   This case exercises (but does not fully test) basic functionality.
        //
        // Concerns:
        //: 1 The class is sufficiently functional to enable comprehensive
        //:   testing in subsequent test cases.
        //
        // Plan:
        //: 1 Set the time zone to "America/New_York" for several dates in
        //:   succession, and examine the local time period information at each
        //:   stage.
        //
        // Testing:
        //   BREATHING TEST
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "BREATHING TEST" << endl
                          << "==============" << endl;

        baltzo::LocalTimePeriod localTimePeriod;

        int status1 = Util::configure(NY);
        ASSERT(0 == status1);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

        bdlt::Datetime startOfDst(2013, 3, 10, 7);
        int status2 = Util::configure(NY, startOfDst);
        ASSERT(0 == status2);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

        bdlt::Datetime resumeOfStd(2013, 11, 3, 6);
        int status3 = Util::configure(NY, resumeOfStd);
        ASSERT(0 == status3);

        if (verbose) {
            Util::loadLocalTimePeriod(&localTimePeriod);
            cout << localTimePeriod << endl;
        }

      } break;
      case -1: {
        // --------------------------------------------------------------------
        // THREAD SAFETY
        //   The primary concern is the thread-safety of the
        //   'localTimeOffset' method.  The other public methods will
        //   typically be called once near the start of a process, and before
        //   multiple threads are launched.  Since the limit on thread creation
        //   vary significantly with platform, this test is designed to be run
        //   interactively (i.e., the test has a negative test number).
        //
        // Concerns:
        //: 1 Concurrent threads calling the 'localTimeOffset' method each
        //:   receive the correct result and return value indicating success.
        //:
        //: 2 When needed, the cached local time zone information is updated
        //:   exactly once.
        //
        // Plan:
        //: 1 Set the timezone and UTC time to some day in 2013 before the
        //:   start of daylight saving time in New York).
        //:
        //: 2 Launch multiple threads (where the number is determined by a
        //:   command-line argument) that each wait at a common barrier until
        //:   all the threads have been created, and then invoke the
        //:   'localTimeOffset' method requesting the offset for the start
        //:   of daylight saving time.
        //:
        //: 3 Compare the values obtained by each thread with the expected
        //:   offset for the start of daylight saving time.
        //:
        //: 4 Confirm that the value returned by 'updateCount' increased by
        //:   exactly one.
        //:
        //: 5 Repeat the test a number of times specified by a command-line
        //:   argument.
        //
        // Testing:
        //   CONCERN: The public methods of this component are *thread-safe*.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "THREAD SAFETY" << endl
                          << "=============" << endl;

        const int numThreads    = argc > 2 ? atoi(argv[2]) : 1;
        const int numIterations = argc > 3 ? atoi(argv[3]) : 1;

        P(numThreads)
        P(numIterations)

        bslmt::Configuration::setDefaultThreadStackSize(
                    bslmt::Configuration::recommendedDefaultThreadStackSize());

        const bdlt::Datetime newYearsDay(2013, 1,  1);
        const bdlt::Datetime  startOfDst(2013, 3, 10, 7);
        const char          *timezone             = "America/New_York";
        int                  previousUpdateCount = Util::updateCount();

        ASSERT(0 == previousUpdateCount);

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations; ++i) {

            int status = Util::configure(timezone, newYearsDay);
            ASSERT(0 == status);

            int updateCount = Util::updateCount();
            ASSERT(previousUpdateCount + 1 == updateCount);
            previousUpdateCount = updateCount;

            Handles       handles(numThreads);
            ThreadArgs threadArgs(numThreads);

            bslmt::Barrier   barrier(numThreads);

            // Setup and launch threads.

            for (int j = 0; j < numThreads; ++j) {
                threadArgs[j].d_offset      = 0x0BADCAFE;
                threadArgs[j].d_utcDatetime = startOfDst;
                threadArgs[j].d_barrier_p   = &barrier;

                int status = bslmt::ThreadUtil::create(&handles[j],
                                                      workerThread,
                                                      &threadArgs[j]);
                ASSERT(0 == status);
            }

            // Wait for all threads to complete.


            for (Handles::iterator itr  = handles.begin(),
                                   end  = handles.end();
                                   end != itr; ++itr) {
                bslmt::ThreadUtil::join(*itr);
            }


            // Examine results.

            updateCount = Util::updateCount();
            ASSERT(previousUpdateCount + 1 == updateCount);
            previousUpdateCount = updateCount;

            for (ThreadArgs::iterator itr  = threadArgs.begin(),
                                      end  = threadArgs.end();
                                      end != itr; ++itr) {
                ASSERT(-4 * 3600 == itr->d_offset);
            }

        }

        stopwatch.stop();

        double systemTime;
        double   userTime;
        double   wallTime;

        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);
        P_(systemTime) P_(userTime) P(wallTime)

      } break;
      case -2: {
        // --------------------------------------------------------------------
        // PERFORMANCE: CACHE-HITS
        //
        // Concerns:
        //: 1 The time needed to deliver an offset value from the cached
        //:   information should be known.
        //
        // Plan:
        //: 1 Set the timezone and UTC time to some day in 2013 before the
        //:   start of daylight saving time in New York).
        //:
        //: 2 Use a stopwatch mechanism to measure the time needed to
        //:   iteratively request the local time offset at the UTC datetime set
        //:   in P-1.  The number of iterations is determined by a command-line
        //:   parameter.  (C-1)
        //
        // Testing:
        //   CONCERN: Performance on cache hits.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PERFORMANCE: CACHE-HITS" << endl
                          << "=======================" << endl;

        const int numIterations = argc > 2 ? atoi(argv[2]) : 0;

        P(numIterations);

        const bdlt::Datetime newYearsDay(2013, 1,  1);
        const char          *timezone             = "America/New_York";

        int status = Util::configure(timezone, newYearsDay);
        ASSERT(0 == status);

        // Confirm that the callback is working

        int offset = Util::localTimeOffset(newYearsDay).totalSeconds();

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations; ++i) {
            offset = Util::localTimeOffset(newYearsDay).totalSeconds();
        }

        double systemTime;
        double   userTime;
        double   wallTime;
        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);

        P_(systemTime) P_(userTime) P(wallTime);

      } break;
      case -3: {
        // --------------------------------------------------------------------
        // PERFORMANCE: CACHE MISSES
        //
        // Concerns:
        //: 1 The time needed to deliver an offset value when the information
        //:   is not in the cache information should be known.
        //
        // Plan:
        //: 1 Set the timezone and UTC time to some day in 2013 before the
        //:   start of daylight saving time in New York).
        //:
        //: 2 Use a stopwatch mechanism to measure the time needed to
        //:   iteratively request the local time offset at the UTC datetime
        //:   corresponding to the start of daylight saving time in New York,
        //:   a cache-miss, which resets the cache.  Then, request the result
        //:   for the UTC time set in P-1, another cache-miss.  The number of
        // requests is determined by a command-line parameter.
        //:   parameter.  (C-1)
        //
        // Testing:
        //   CONCERN: Performance on cache misses.
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "PERFORMANCE: CACHE-MISSES" << endl
                          << "=========================" << endl;

        const int numIterations = argc > 2 ? atoi(argv[2]) : 0;

        P(numIterations);

        const bdlt::Datetime  newYearsDay(2013,  1,  1);
        const bdlt::Datetime   startOfDst(2013,  3, 10, 7);
        const char          *timezone = "America/New_York";

        int status = Util::configure(timezone, newYearsDay);
        ASSERT(0 == status);

        // Confirm that the callback is working

        int offset = Util::localTimeOffset(newYearsDay).totalSeconds();

        const int numIterations2 = numIterations/2;

        bsls::Stopwatch stopwatch;
        stopwatch.start(true);

        for (int i = 0;  i < numIterations2; ++i) {
            offset = Util::localTimeOffset(startOfDst).totalSeconds();
            offset = Util::localTimeOffset(newYearsDay).totalSeconds();
        }

        stopwatch.stop();

        double systemTime;
        double   userTime;
        double   wallTime;
        stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);

        P_(systemTime) P_(userTime) P(wallTime);

      } break;
      default: {
        cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    if (testStatus > 0) {
        cerr << "Error, non-zero test status = " << testStatus << "." << endl;
    }
    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
