w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

icuzdump.cpp
Go to the documentation of this file.
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *
6 * Copyright (C) 2007-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
8 *
9 *******************************************************************************
10 * file name: icuzdump.cpp
11 * encoding: UTF-8
12 * tab size: 8 (not used)
13 * indentation:4
14 *
15 * created on: 2007-04-02
16 * created by: Yoshito Umaoka
17 *
18 * This tool write out timezone transitions for ICU timezone. This tool
19 * is used as a part of tzdata update process to check if ICU timezone
20 * code works as well as the corresponding Olson stock localtime/zdump.
21 */
22 
23 #include <cstdlib>
24 #include <cstring>
25 #include <fstream>
26 #include <sstream>
27 #include <iostream>
28 
29 #include "unicode/utypes.h"
30 #include "unicode/ustring.h"
31 #include "unicode/timezone.h"
32 #include "unicode/simpletz.h"
33 #include "unicode/smpdtfmt.h"
34 #include "unicode/decimfmt.h"
35 #include "unicode/gregocal.h"
36 #include "unicode/ustream.h"
37 #include "unicode/putil.h"
38 
39 #include "cmemory.h"
40 #include "uoptions.h"
41 
42 using namespace std;
43 using namespace icu;
44 
46 public:
49  stz = new SimpleTimeZone(0, "");
50  sdf = new SimpleDateFormat((UnicodeString)"yyyy-MM-dd EEE HH:mm:ss", Locale::getEnglish(), status);
51  DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getEnglish(), status);
52  decf = new DecimalFormat("00", symbols, status);
53  }
55  }
56 
57  UnicodeString& format(UDate time, int32_t offset, UBool isDst, UnicodeString& appendTo) {
58  stz->setRawOffset(offset);
59  sdf->setTimeZone(*stz);
60  UnicodeString str = sdf->format(time, appendTo);
61  if (offset < 0) {
62  appendTo += "-";
63  offset = -offset;
64  } else {
65  appendTo += "+";
66  }
67 
68  int32_t hour, min, sec;
69 
70  offset /= 1000;
71  sec = offset % 60;
72  offset = (offset - sec) / 60;
73  min = offset % 60;
74  hour = offset / 60;
75 
76  decf->format(hour, appendTo);
77  decf->format(min, appendTo);
78  decf->format(sec, appendTo);
79  appendTo += "[DST=";
80  if (isDst) {
81  appendTo += "1";
82  } else {
83  appendTo += "0";
84  }
85  appendTo += "]";
86  return appendTo;
87  }
88 private:
89  SimpleTimeZone* stz;
90  SimpleDateFormat* sdf;
91  DecimalFormat* decf;
92 };
93 
94 class ICUZDump {
95 public:
97  formatter = new DumpFormatter();
98  loyear = 1902;
99  hiyear = 2050;
100  tick = 1000;
101  linesep = NULL;
102  }
103 
105  }
106 
107  void setLowYear(int32_t lo) {
108  loyear = lo;
109  }
110 
111  void setHighYear(int32_t hi) {
112  hiyear = hi;
113  }
114 
115  void setTick(int32_t t) {
116  tick = t;
117  }
118 
119  void setTimeZone(TimeZone* tz) {
120  timezone = tz;
121  }
122 
124  formatter = fmt;
125  }
126 
127  void setLineSeparator(const char* sep) {
128  linesep = sep;
129  }
130 
131  void dump(ostream& out) {
133  UDate SEARCH_INCREMENT = 12 * 60 * 60 * 1000; // half day
134  UDate t, cutlo, cuthi;
135  int32_t rawOffset, dstOffset;
136  UnicodeString str;
137 
138  getCutOverTimes(cutlo, cuthi);
139  t = cutlo;
140  timezone->getOffset(t, false, rawOffset, dstOffset, status);
141  while (t < cuthi) {
142  int32_t newRawOffset, newDstOffset;
143  UDate newt = t + SEARCH_INCREMENT;
144 
145  timezone->getOffset(newt, false, newRawOffset, newDstOffset, status);
146 
147  UBool bSameOffset = (rawOffset + dstOffset) == (newRawOffset + newDstOffset);
148  UBool bSameDst = ((dstOffset != 0) && (newDstOffset != 0)) || ((dstOffset == 0) && (newDstOffset == 0));
149 
150  if (!bSameOffset || !bSameDst) {
151  // find the boundary
152  UDate lot = t;
153  UDate hit = newt;
154  while (true) {
155  int32_t diff = (int32_t)(hit - lot);
156  if (diff <= tick) {
157  break;
158  }
159  UDate medt = lot + ((diff / 2) / tick) * tick;
160  int32_t medRawOffset, medDstOffset;
161  timezone->getOffset(medt, false, medRawOffset, medDstOffset, status);
162 
163  bSameOffset = (rawOffset + dstOffset) == (medRawOffset + medDstOffset);
164  bSameDst = ((dstOffset != 0) && (medDstOffset != 0)) || ((dstOffset == 0) && (medDstOffset == 0));
165 
166  if (!bSameOffset || !bSameDst) {
167  hit = medt;
168  } else {
169  lot = medt;
170  }
171  }
172  // write out the boundary
173  str.remove();
174  formatter->format(lot, rawOffset + dstOffset, (dstOffset == 0 ? false : true), str);
175  out << str << " > ";
176  str.remove();
177  formatter->format(hit, newRawOffset + newDstOffset, (newDstOffset == 0 ? false : true), str);
178  out << str;
179  if (linesep != NULL) {
180  out << linesep;
181  } else {
182  out << endl;
183  }
184 
185  rawOffset = newRawOffset;
186  dstOffset = newDstOffset;
187  }
188  t = newt;
189  }
190  }
191 
192 private:
193  void getCutOverTimes(UDate& lo, UDate& hi) {
195  GregorianCalendar* gcal = new GregorianCalendar(timezone, Locale::getEnglish(), status);
196  gcal->clear();
197  gcal->set(loyear, 0, 1, 0, 0, 0);
198  lo = gcal->getTime(status);
199  gcal->set(hiyear, 0, 1, 0, 0, 0);
200  hi = gcal->getTime(status);
201  }
202 
203  TimeZone* timezone;
207 
209  const char* linesep;
210 };
211 
213 public:
215  if (bAll) {
216  zenum = TimeZone::createEnumeration();
217  }
218  else {
219  zenum = NULL;
220  zids = NULL;
221  idx = 0;
222  numids = 1;
223  }
224  }
225 
226  ZoneIterator(const char** ids, int32_t num) {
227  zenum = NULL;
228  zids = ids;
229  idx = 0;
230  numids = num;
231  }
232 
234  if (zenum != NULL) {
235  delete zenum;
236  }
237  }
238 
239  TimeZone* next() {
240  TimeZone* tz = NULL;
241  if (zenum != NULL) {
243  const UnicodeString* zid = zenum->snext(status);
244  if (zid != NULL) {
245  tz = TimeZone::createTimeZone(*zid);
246  }
247  }
248  else {
249  if (idx < numids) {
250  if (zids != NULL) {
251  tz = TimeZone::createTimeZone((const UnicodeString&)zids[idx]);
252  }
253  else {
254  tz = TimeZone::createDefault();
255  }
256  idx++;
257  }
258  }
259  return tz;
260  }
261 
262 private:
263  const char** zids;
264  StringEnumeration* zenum;
267 };
268 
269 enum {
276 };
277 
278 static UOption options[]={
281  UOPTION_DEF("allzones", 'a', UOPT_NO_ARG),
282  UOPTION_DEF("cutover", 'c', UOPT_REQUIRES_ARG),
283  UOPTION_DEF("destdir", 'd', UOPT_REQUIRES_ARG),
284  UOPTION_DEF("linesep", 'l', UOPT_REQUIRES_ARG)
285 };
286 
287 extern int
288 main(int argc, char *argv[]) {
289  int32_t low = 1902;
290  int32_t high = 2038;
291  UBool bAll = false;
292  const char *dir = NULL;
293  const char *linesep = NULL;
294 
297 
298  if (argc < 0) {
299  cerr << "Illegal command line argument(s)" << endl << endl;
300  }
301 
302  if (argc < 0 || options[kOptHelpH].doesOccur || options[kOptHelpQuestionMark].doesOccur) {
303  cerr
304  << "Usage: icuzdump [-options] [zoneid1 zoneid2 ...]" << endl
305  << endl
306  << "\tDump all offset transitions for the specified zones." << endl
307  << endl
308  << "Options:" << endl
309  << "\t-a : Dump all available zones." << endl
310  << "\t-d <dir> : When specified, write transitions in a file under" << endl
311  << "\t the directory for each zone." << endl
312  << "\t-l <sep> : New line code type used in file outputs. CR or LF (default)"
313  << "\t or CRLF." << endl
314  << "\t-c [<low_year>,]<high_year>" << endl
315  << "\t : When specified, dump transitions starting <low_year>" << endl
316  << "\t (inclusive) up to <high_year> (exclusive). The default" << endl
317  << "\t values are 1902(low) and 2038(high)." << endl;
319  }
320 
321  bAll = options[kOptAllZones].doesOccur;
322 
323  if (options[kOptDestDir].doesOccur) {
325  }
326 
327  if (options[kOptLineSep].doesOccur) {
328  if (strcmp(options[kOptLineSep].value, "CR") == 0) {
329  linesep = "\r";
330  } else if (strcmp(options[kOptLineSep].value, "CRLF") == 0) {
331  linesep = "\r\n";
332  } else if (strcmp(options[kOptLineSep].value, "LF") == 0) {
333  linesep = "\n";
334  }
335  }
336 
337  if (options[kOptCutover].doesOccur) {
338  char* comma = (char*)strchr(options[kOptCutover].value, ',');
339  if (comma == NULL) {
341  } else {
342  *comma = 0;
344  high = atoi(comma + 1);
345  }
346  }
347 
348  ICUZDump dumper;
349  dumper.setLowYear(low);
350  dumper.setHighYear(high);
351  if (dir != NULL && linesep != NULL) {
352  // use the specified line separator only for file output
353  dumper.setLineSeparator((const char*)linesep);
354  }
355 
356  ZoneIterator* zit;
357  if (bAll) {
358  zit = new ZoneIterator(true);
359  } else {
360  if (argc <= 1) {
361  zit = new ZoneIterator();
362  } else {
363  zit = new ZoneIterator((const char**)&argv[1], argc - 1);
364  }
365  }
366 
367  UnicodeString id;
368  if (dir != NULL) {
369  // file output
370  ostringstream path;
371  ios::openmode mode = ios::out;
372  if (linesep != NULL) {
373  mode |= ios::binary;
374  }
375  for (;;) {
376  TimeZone* tz = zit->next();
377  if (tz == NULL) {
378  break;
379  }
380  dumper.setTimeZone(tz);
381  tz->getID(id);
382 
383  // target file path
384  path.str("");
385  path << dir << U_FILE_SEP_CHAR;
386  id = id.findAndReplace("/", "-");
387  path << id;
388 
389  ofstream* fout = new ofstream(path.str().c_str(), mode);
390  if (fout->fail()) {
391  cerr << "Cannot open file " << path.str() << endl;
392  delete fout;
393  delete tz;
394  break;
395  }
396 
397  dumper.dump(*fout);
398  fout->close();
399  delete fout;
400  delete tz;
401  }
402 
403  } else {
404  // stdout
405  UBool bFirst = true;
406  for (;;) {
407  TimeZone* tz = zit->next();
408  if (tz == NULL) {
409  break;
410  }
411  dumper.setTimeZone(tz);
412  tz->getID(id);
413  if (bFirst) {
414  bFirst = false;
415  } else {
416  cout << endl;
417  }
418  cout << "ZONE: " << id << endl;
419  dumper.dump(cout);
420  delete tz;
421  }
422  }
423  delete zit;
424 }
#define mode
Definition: aptex-macros.h:510
unsigned binary[4]
Definition: ascii85.c:46
double linesep
Definition: axohelp.c:115
SimpleTimeZone * stz
Definition: icuzdump.cpp:89
UnicodeString & format(UDate time, int32_t offset, UBool isDst, UnicodeString &appendTo)
Definition: icuzdump.cpp:57
DecimalFormat * decf
Definition: icuzdump.cpp:91
SimpleDateFormat * sdf
Definition: icuzdump.cpp:90
void setLineSeparator(const char *sep)
Definition: icuzdump.cpp:127
int32_t tick
Definition: icuzdump.cpp:206
void dump(ostream &out)
Definition: icuzdump.cpp:131
void getCutOverTimes(UDate &lo, UDate &hi)
Definition: icuzdump.cpp:193
void setLowYear(int32_t lo)
Definition: icuzdump.cpp:107
int32_t hiyear
Definition: icuzdump.cpp:205
DumpFormatter * formatter
Definition: icuzdump.cpp:208
void setDumpFormatter(DumpFormatter *fmt)
Definition: icuzdump.cpp:123
void setTick(int32_t t)
Definition: icuzdump.cpp:115
const char * linesep
Definition: icuzdump.cpp:209
void setHighYear(int32_t hi)
Definition: icuzdump.cpp:111
ICUZDump()
Definition: icuzdump.cpp:96
void setTimeZone(TimeZone *tz)
Definition: icuzdump.cpp:119
TimeZone * timezone
Definition: icuzdump.cpp:203
int32_t loyear
Definition: icuzdump.cpp:204
TimeZone * next()
Definition: icuzdump.cpp:239
const char ** zids
Definition: icuzdump.cpp:263
int32_t numids
Definition: icuzdump.cpp:266
int32_t idx
Definition: icuzdump.cpp:265
ZoneIterator(UBool bAll=0)
Definition: icuzdump.cpp:214
ZoneIterator(const char **ids, int32_t num)
Definition: icuzdump.cpp:226
StringEnumeration * zenum
Definition: icuzdump.cpp:264
#define UPRV_LENGTHOF(array)
Definition: cmemory.h:50
static int id
Definition: bifont.c:66
int strcmp()
Definition: coll.cpp:143
FILE * fout
#define t
Definition: afcover.h:96
#define comma
Definition: globals.h:57
#define strchr
Definition: gsftopk.c:59
FILE * out
Definition: hbf2gf.c:286
int main(int argc, char *argv[])
Definition: icuzdump.cpp:288
@ kOptDestDir
Definition: icuzdump.cpp:274
@ kOptHelpH
Definition: icuzdump.cpp:270
@ kOptAllZones
Definition: icuzdump.cpp:272
@ kOptLineSep
Definition: icuzdump.cpp:275
@ kOptHelpQuestionMark
Definition: icuzdump.cpp:271
@ kOptCutover
Definition: icuzdump.cpp:273
#define NULL
Definition: ftobjs.h:61
signed int int32_t
Definition: stdint.h:77
int atoi(const char *)
int num
Definition: disdvi.c:621
int low
Definition: combiners.h:904
int high
Definition: combiners.h:904
symbols
Definition: gen-def.py:18
STL namespace.
#define min(a, b)
Definition: pbmplus.h:223
static int bAll
Definition: pdfdde.c:44
static int offset
Definition: ppmtogif.c:642
time_t time()
#define dir
#define status
C API: Unicode string handling functions.
static char sep[2]
Definition: pdftoppm.cc:115
C API: Platform Utilities.
#define U_FILE_SEP_CHAR
Definition: putil.h:130
#define str(s)
Definition: sh6.c:399
#define int32_t
Definition: stdint.in.h:167
char * value
Definition: ppmtopjxl.c:57
Definition: dvips.h:235
pointer path
Definition: t1imager.h:36
char fmt[256]
Definition: tex4ht.c:3925
int diff
Definition: tex4ht.c:3815
int8_t UBool
Definition: umachine.h:269
Definition: obx.h:51
int u_parseArgs(int argc, char *argv[], int optionCount, UOption options[])
Definition: uoptions.cpp:26
#define UOPTION_HELP_QUESTION_MARK
Definition: uoptions.h:69
#define UOPTION_HELP_H
Definition: uoptions.h:68
#define U_MAIN_INIT_ARGS(argc, argv)
Definition: uoptions.h:37
#define UOPTION_DEF(longName, shortName, hasArg)
Definition: uoptions.h:64
@ UOPT_NO_ARG
Definition: uoptions.h:50
@ UOPT_REQUIRES_ARG
Definition: uoptions.h:50
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Definition: utypes.h:431
@ U_ILLEGAL_ARGUMENT_ERROR
Definition: utypes.h:467
@ U_ZERO_ERROR
Definition: utypes.h:465
double UDate
Definition: utypes.h:203
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269