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