BDE 4.39.x Production Release
Loading...
Searching...
No Matches
baltzo_zoneinfobinaryreader.h
Go to the documentation of this file.
1/// @file baltzo_zoneinfobinaryreader.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baltzo_zoneinfobinaryreader.h -*-C++-*-
8#ifndef INCLUDED_BALTZO_ZONEINFOBINARYREADER
9#define INCLUDED_BALTZO_ZONEINFOBINARYREADER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baltzo_zoneinfobinaryreader baltzo_zoneinfobinaryreader
15/// @brief Provide utilities for reading the Zoneinfo binary data format.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baltzo
19/// @{
20/// @addtogroup baltzo_zoneinfobinaryreader
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baltzo_zoneinfobinaryreader-purpose"> Purpose</a>
25/// * <a href="#baltzo_zoneinfobinaryreader-classes"> Classes </a>
26/// * <a href="#baltzo_zoneinfobinaryreader-description"> Description </a>
27/// * <a href="#baltzo_zoneinfobinaryreader-zoneinfo-files"> Zoneinfo (TZ Database) Files </a>
28/// * <a href="#baltzo_zoneinfobinaryreader-zoneinfo-binary-file-format"> Zoneinfo Binary File Format </a>
29/// * <a href="#baltzo_zoneinfobinaryreader-isgmt-and-isstd"> isGmt and isStd </a>
30/// * <a href="#baltzo_zoneinfobinaryreader-leap-corrections"> Leap Corrections </a>
31/// * <a href="#baltzo_zoneinfobinaryreader-version-2"> Version 2 </a>
32/// * <a href="#baltzo_zoneinfobinaryreader-version-3"> Version 3 </a>
33/// * <a href="#baltzo_zoneinfobinaryreader-version-4"> Version 4 </a>
34/// * <a href="#baltzo_zoneinfobinaryreader-additional-information"> Additional Information </a>
35/// * <a href="#baltzo_zoneinfobinaryreader-usage"> Usage </a>
36/// * <a href="#baltzo_zoneinfobinaryreader-example-1-reading-zoneinfo-binary-data"> Example 1: Reading Zoneinfo Binary Data </a>
37///
38/// # Purpose {#baltzo_zoneinfobinaryreader-purpose}
39/// Provide utilities for reading the Zoneinfo binary data format.
40///
41/// # Classes {#baltzo_zoneinfobinaryreader-classes}
42///
43/// - baltzo::ZoneinfoBinaryReader: utilities for reading Zoneinfo binary data
44///
45/// @see baltzo_zoneinfo
46///
47/// # Description {#baltzo_zoneinfobinaryreader-description}
48/// This component provides a `struct`,
49/// `baltzo::ZoneinfoBinaryReader`, containing utilities to read the binary data
50/// format of the Zoneinfo database from a `bsl::istream` and populate a
51/// `baltzo::Zoneinfo` object. The Zoneinfo database (also known as the Olson
52/// database or TZ database) records information about the world's time zones.
53/// It includes information such as the historic changes to the rules of local
54/// times, the time of transitions to daylight saving time, and corrections for
55/// leap seconds.
56///
57/// ## Zoneinfo (TZ Database) Files {#baltzo_zoneinfobinaryreader-zoneinfo-files}
58///
59///
60/// The Zoneinfo binary data is generated from a set of text-based rule file. A
61/// rule file may be compiled into multiple binary files, each describing one
62/// time zone. Information about the Zoneinfo database can be found online at
63/// `http://www.iana.org/time-zones`, including the time zone rules for the
64/// supported time zones, and source code for the `zic` compiler (for compiling
65/// those rules into the binary representation read by utility functions
66/// provided by this component).
67///
68/// ## Zoneinfo Binary File Format {#baltzo_zoneinfobinaryreader-zoneinfo-binary-file-format}
69///
70///
71/// A binary byte stream conforming to the Zoneinfo binary data format begins
72/// with a 44-byte header that describes the file. The structure of the header
73/// is shown below:
74/// @code
75/// Byte | Name | Description
76/// ---------+-------------------+----------------------------------------------
77/// 0 - 3 | 'T''Z''i''f' | magic characters to identify the file
78/// 4 | version | '\0', '2', '3' or '4' to identify the version
79/// 5 - 19 | reserved | unused
80/// 20 - 23 | numIsGmt | number of UTC/local-time indicators
81/// 24 - 27 | numIsStd | number of standard/local-time indicators
82/// 28 - 31 | numLeaps | number of leap seconds corrections
83/// 32 - 35 | numTransitions | number of transition times
84/// 36 - 39 | numLocalTimeTypes | number of local-time types
85/// 40 - 43 | numAbbrevChar | length of time-zone abbreviation string
86/// ---------+-------------------+----------------------------------------------
87/// @endcode
88/// NOTE: All the numbers are 4-byte signed integers stored in big-endian format
89/// (higher order byte first).
90///
91/// The binary file has the following layout:
92/// @code
93/// File Segment Number of bytes
94/// +--------------------------------+ ---------------
95/// | HEADER | 44
96/// +--------------------------------+
97/// | TRANSITION TIMES | 4 * header.numTransitions
98/// +--------------------------------+
99/// | TRANSITION-TIME INDEXES | 1 * header.numTransitions
100/// +--------------------------------+
101/// | LOCAL-TIME TYPES | (4+1+1) * header.numLocalTimeTypes
102/// +--------------------------------+
103/// | TIME-ZONE ABBREVIATION STRINGS | 1 * header.numAbbrevChar
104/// +--------------------------------+
105/// | LEAP SECONDS | (4+4) * header.numLeaps
106/// +--------------------------------+
107/// | IS_GMT(s) | 1 * header.numIsGmt
108/// +--------------------------------+
109/// | IS_STD(s) | 1 * header.numIsStd
110/// +--------------------------------+
111/// @endcode
112/// * HEADER -- The header is 44 bytes that describe the file.
113/// * TRANSITION TIMES -- `numTransitions` number of 4-byte big-endian signed
114/// integers representing the transition times in POSIX time format (number
115/// of seconds elapsed since midnight UTC, January 1, 1970) sorted in
116/// ascending order. Each transition time represents a time at which the
117/// rule for computing the local time in that time zone changes. (NOTE: See
118/// "Version `2`" section for additional information.)
119/// * TRANSITION-TIME INDEXES -- `numTransitions` number of unsigned bytes.
120/// The byte at a given offset N stores the index of the local-time type
121/// entry (in the array of local-time types appearing next in the file) that
122/// corresponds to the transition at index N in the preceding sequence of
123/// transitions.
124/// * LOCAL-TIME TYPES -- An array of `numLocalTimeTypes` local-time types,
125/// where each entry consist of:
126/// - gmtOffset -- 4-bytes big-endian signed integer indicating the number of
127/// seconds added to UTC to compute the local time in the time zone
128/// - isDst -- 1-byte boolean indicating whether the local-time type is
129/// considered daylight saving time
130/// - abbreviationIndex -- 1 unsigned byte indicating the index of the first
131/// byte of the null terminated string abbreviation of this local-time type
132/// in the array of bytes holding abbreviation strings later in the file.
133/// * TIME-ZONE ABBREVIATION STRINGS -- `numAbbrevChar` number of bytes
134/// containing the abbreviation strings of the local-time types of this time
135/// zone. Each abbreviation string ends with the '\0' character.
136/// * LEAP SECONDS -- `numLeaps` number of *pairs* of 4-byte signed big-endian
137/// integers (totaling 8 bytes). The first value of the pair is the POSIX
138/// time at which the leap seconds occur. The second value of the pair gives
139/// the number of leap seconds to be applied to times after the time defined
140/// by the first element of the pair. The pairs are stored in ascending
141/// order by time. (NOTE: See "Version `2`" section for additional
142/// information.)
143/// * IS_GMT(s) -- `numIsGmt` number of 1-byte booleans indicating whether the
144/// transition time for the local-time type with the corresponding index in
145/// the preceding array of local-time types was specified in UTC time or
146/// local time in the original rule file (from which the binary file was
147/// presumably compiled) (see next section for details).
148/// * IS_STD(s) -- `numIsStd` number of 1-byte booleans indicating whether the
149/// transition time for the local-time type with the corresponding index in
150/// the preceding array of local-time types was specified in standard time or
151/// local time in the original rule file (from which the binary file was
152/// presumably compiled). Standard time refers to the time without
153/// adjustment for daylight-saving time whether daylight saving is in effect
154/// or not. (see next section for details).
155///
156/// ### isGmt and isStd {#baltzo_zoneinfobinaryreader-isgmt-and-isstd}
157///
158///
159/// The `isGmt` and `isStd` boolean flags are not used by this component.
160///
161/// They indicate properties of the original rule file that were compiled into
162/// this binary representation. Each `isGmt` boolean flag indicates whether a
163/// transition time was originally specified as a UTC time or as a local time in
164/// the **rule file**. `isStd` indicates whether a transition time was
165/// originally specified as a standard time or local time. Note that all the
166/// transitions in the *binary* Zoneinfo representation are UTC times regardless
167/// of whether the original representation in the rule file was in local time.
168/// Also note that the value of `numIsGmt` and `numIsStd` should equal to
169/// `numLocalTimeTypes`, but for backward compatibility reasons, they may be set
170/// to zero.
171///
172/// ### Leap Corrections {#baltzo_zoneinfobinaryreader-leap-corrections}
173///
174///
175/// Leap corrections are currently not supported by this component (i.e. it does
176/// not provide tools to obtain leap corrections data from the stream).
177///
178/// There is a slight difference between the mean length of a day and 86400
179/// (24 * 60 * 60) seconds. Leap corrections are adjustments to the UTC time to
180/// account for this difference. In general, the time in a computer is updated
181/// through the network to account for leap seconds. Thus, it is not necessary
182/// to for this component to consider leap corrections for accurate time
183/// calculations.
184///
185/// ### Version 2 {#baltzo_zoneinfobinaryreader-version-2}
186///
187///
188/// Version `2` format of the Zoneinfo binary data can be divided into two
189/// parts. The first part contains the header and data described above. The
190/// second part contains header and data in the same format with the exception
191/// that eight bytes are used for transition time and leap correction time. The
192/// second header and data is followed by a formatted string used for handling
193/// time after the last transition time.
194///
195/// The version `2` format uses 8 bytes to store date-time values because the
196/// 4-byte values used in the version '\0' format provide a limited date range.
197/// The standard IANA data contains many transitions that are outside the range
198/// of representable values of a 4-byte offset (these transitions are ignored by
199/// the version '\0' format, which leads to inaccurate information for dates far
200/// in the past or future).
201///
202/// The version `2` format adds an additional optional POSIX TZ environment
203/// string, holding a text description of the local time transitions of the
204/// timezone, which can be used to compute transitions beyond the range
205/// represented in the binary compiled time zone data (see
206/// ftp://ftp.iana.org/tz/code/tzfile.h). It is similar (but not necessarily
207/// identical to) POSIX time zone description used for the `TZ` environment
208/// variable. String is found between two newline '\n' characters immediately
209/// following the data. If two consecutive newline characters are found, no
210/// string has been specified.
211///
212/// This component will always load version `2` data if it is present in the
213/// supplied binary data.
214///
215/// ### Version 3 {#baltzo_zoneinfobinaryreader-version-3}
216///
217///
218/// Version `3` format of the Zoneinfo binary data is identical to the version
219/// `2` data described above. The version number of some files was incremented
220/// because the rules for the allowable range of values for the POSIX TZ
221/// environment string (found at the end of the data) were changed (see
222/// ftp://ftp.iana.org/tz/code/tzfile.h for more information).
223///
224/// ### Version 4 {#baltzo_zoneinfobinaryreader-version-4}
225///
226///
227/// Version `4` format of the Zoneinfo binary data is identical to the versions
228/// `2` and `3` described above except for changes in leap second records. Note
229/// that leap corrections are currently not supported by this component
230/// (see @ref baltzo_zoneinfobinaryreader-leap-corrections ).
231///
232/// ### Additional Information {#baltzo_zoneinfobinaryreader-additional-information}
233///
234///
235/// Additional documentation for the Zoneinfo file format can be found at
236/// various places on the internet:
237///
238/// * http://www.iana.org/time-zones -- Central links for Zoneinfo time-zone DB
239/// information. Up-to-date documentation on the file specification can be
240/// found inside the code distribution, in a file named `tzfile.5.txt`. This
241/// file contains the most recent man-page text.
242/// * https://github.com/eggert/tz -- Unofficial GitHub repository for unstable
243/// changes not yet published into an official release on the IANA website.
244/// This repository is published and maintained by the official IANA
245/// maintainer, Paul Eggert.
246///
247/// ## Usage {#baltzo_zoneinfobinaryreader-usage}
248///
249///
250/// In this section, we illustrate how this component can be used.
251///
252/// ### Example 1: Reading Zoneinfo Binary Data {#baltzo_zoneinfobinaryreader-example-1-reading-zoneinfo-binary-data}
253///
254///
255/// The following demonstrates how to read a byte stream in the Zoneinfo binary
256/// data format into a `baltzo::Zoneinfo` object. We start by creating Zoneinfo
257/// data in memory for "Asia/Bangkok", which was chosen due to its small size.
258/// Note that this data was generated by the `zic` compiler, which is publicly
259/// obtainable as part of the standard Zoneinfo distribution (see
260/// `http://www.iana.org/time-zones`):
261/// @code
262/// const unsigned char ASIA_BANGKOK_DATA[] = {
263/// 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
265/// 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
266/// 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xa2, 0x6a, 0x67, 0xc4,
267/// 0x01, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x70, 0x00,
268/// 0x04, 0x42, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00,
269/// 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271/// 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272/// 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff,
273/// 0xff, 0x56, 0xb6, 0x85, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xa2, 0x6a, 0x67,
274/// 0xc4, 0x01, 0x02, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x5e,
275/// 0x3c, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70, 0x00, 0x08, 0x4c, 0x4d, 0x54,
276/// 0x00, 0x42, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00,
277/// 0x00, 0x00, 0x00, 0x0a, 0x49, 0x43, 0x54, 0x2d, 0x37, 0x0a
278/// };
279/// @endcode
280/// Then, we load this data into a stream buffer.
281/// @code
282/// bdlsb::FixedMemInStreamBuf inStreamBuf(
283/// reinterpret_cast<const char *>(ASIA_BANGKOK_DATA),
284/// sizeof(ASIA_BANGKOK_DATA));
285/// bsl::istream inputStream(&inStreamBuf);
286/// @endcode
287/// Now, we read the `inputStream` using `baltzo::ZoneinfoBinaryReader::read`.
288/// @code
289/// baltzo::Zoneinfo timeZone;
290/// if (0 != baltzo::ZoneinfoBinaryReader::read(&timeZone, inputStream)) {
291/// bsl::cerr << "baltzo::ZoneinfoBinaryReader::load failed"
292/// << bsl::endl;
293/// return 1; // RETURN
294/// }
295/// @endcode
296/// Finally, we write a description of the loaded Zoneinfo to the console.
297/// @code
298/// timeZone.print(bsl::cout, 1, 3);
299/// @endcode
300/// The output of the preceding statement should look like:
301/// @code
302/// [
303/// identifier = ""
304/// transitions = [
305/// [
306/// time = 01JAN0001_00:00:00.000
307/// descriptor = [
308/// utcOffsetInSeconds = 24124
309/// dstInEffectFlag = false
310/// description = "LMT"
311/// ]
312/// ]
313/// [
314/// time = 31DEC1879_17:17:56.000
315/// descriptor = [
316/// utcOffsetInSeconds = 24124
317/// dstInEffectFlag = false
318/// description = "BMT"
319/// ]
320/// ]
321/// [
322/// time = 31MAR1920_17:17:56.000
323/// descriptor = [
324/// utcOffsetInSeconds = 25200
325/// dstInEffectFlag = false
326/// description = "ICT"
327/// ]
328/// ]
329/// ]
330/// ]
331/// @endcode
332/// @}
333/** @} */
334/** @} */
335
336/** @addtogroup bal
337 * @{
338 */
339/** @addtogroup baltzo
340 * @{
341 */
342/** @addtogroup baltzo_zoneinfobinaryreader
343 * @{
344 */
345
346#include <balscm_version.h>
347
348#include <bsl_iosfwd.h>
349
350
351
352
353namespace baltzo {
354
355class Zoneinfo;
356class ZoneinfoBinaryHeader;
357
358 // ===========================
359 // struct ZoneinfoBinaryReader
360 // ===========================
361
362/// This struct provides a namespace for functions that read Zoneinfo time zone
363/// data from a binary input stream. The primary method, `read`, makes use of
364/// a stream containing a Zoneinfo time zone database to populate a `Zoneinfo`
365/// object.
366///
367/// See @ref baltzo_zoneinfobinaryreader
369
370 // CLASS METHODS
371
372 /// Read time zone information from the specified `stream`, and load the
373 /// description into the specified `zoneinfoResult`. The `zoneinfoResult`
374 /// will have a sentinel transition at 01-01-001, meeting the first two
375 /// requirements for a "well-formed" object (see
376 /// `baltzo::ZoneinfoUtil::isWellFormed` documentation). Return 0 on
377 /// success and a non-zero value if `stream` does not provide a sequence of
378 /// bytes consistent with the Zoneinfo binary format. If an error occurs
379 /// during the operation, `zoneinfoResult` is unspecified. Optionally
380 /// specify a `headerResult` that, on success, will be populated with a
381 /// summary of the `stream` contents.
382 static int read(Zoneinfo *zoneinfoResult,
383 bsl::istream& stream);
384 static int read(Zoneinfo *zoneinfoResult,
385 ZoneinfoBinaryHeader *headerResult,
386 bsl::istream& stream);
387
388 /// Read time zone information from the specified `stream`, and load the
389 /// description into the specified `zoneinfoResult` exactly in accordance
390 /// with the original data. The `zoneinfoResult` may not be a
391 /// "well-formed" object (see `baltzo::ZoneinfoUtil::isWellFormed`
392 /// documentation for details). Return 0 on success and a non-zero value
393 /// if `stream` does not provide a sequence of bytes consistent with the
394 /// Zoneinfo binary format. If an error occurs during the operation,
395 /// `zoneinfoResult` is unspecified. Optionally specify a `headerResult`
396 /// that, on success, will be populated with a summary of the `stream` contents.
397 ///
398 /// \note Note that time zone data files created by certain versions
399 /// of the `zic` time zone compiler will have a sentinel transition prior
400 /// to 01-01-0001 (the first representable `Datetime` value) and the
401 /// `zoneinfoResult` will therefore be non-well formed (use `read`
402 /// instead).
403 static int readRaw(Zoneinfo *zoneinfoResult,
404 bsl::istream& stream);
405 static int readRaw(Zoneinfo *zoneinfoResult,
406 ZoneinfoBinaryHeader *headerResult,
407 bsl::istream& stream);
408};
409
410} // close package namespace
411
412
413#endif
414
415// ----------------------------------------------------------------------------
416// Copyright 2015 Bloomberg Finance L.P.
417//
418// Licensed under the Apache License, Version 2.0 (the "License");
419// you may not use this file except in compliance with the License.
420// You may obtain a copy of the License at
421//
422// http://www.apache.org/licenses/LICENSE-2.0
423//
424// Unless required by applicable law or agreed to in writing, software
425// distributed under the License is distributed on an "AS IS" BASIS,
426// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
427// See the License for the specific language governing permissions and
428// limitations under the License.
429// ----------------------------- END-OF-FILE ----------------------------------
430
431/** @} */
432/** @} */
433/** @} */
Definition baltzo_zoneinfobinaryheader.h:226
Definition baltzo_zoneinfo.h:429
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baltzo_datafileloader.h:259
Definition baltzo_zoneinfobinaryreader.h:368
static int read(Zoneinfo *zoneinfoResult, bsl::istream &stream)
static int readRaw(Zoneinfo *zoneinfoResult, ZoneinfoBinaryHeader *headerResult, bsl::istream &stream)
static int readRaw(Zoneinfo *zoneinfoResult, bsl::istream &stream)
static int read(Zoneinfo *zoneinfoResult, ZoneinfoBinaryHeader *headerResult, bsl::istream &stream)