]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/tools/misc/src/com/ibm/icu/dev/tool/timezone/ICUZDump.java
Upgrade ICU4J.
[Dictionary.git] / jars / icu4j-52_1 / tools / misc / src / com / ibm / icu / dev / tool / timezone / ICUZDump.java
1 /*
2  ***********************************************************************
3  * Copyright (C) 2007, International Business Machines                 *
4  * Corporation and others. All Rights Reserved.                        *
5  ***********************************************************************
6  *
7  */
8
9 package com.ibm.icu.dev.tool.timezone;
10
11 import java.io.BufferedWriter;
12 import java.io.File;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.OutputStreamWriter;
16 import java.io.PrintWriter;
17 import java.io.Writer;
18 import java.lang.reflect.Method;
19 import java.util.ArrayList;
20 import java.util.Date;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.TreeSet;
24
25 import com.ibm.icu.text.DecimalFormat;
26 import com.ibm.icu.text.DecimalFormatSymbols;
27 import com.ibm.icu.text.SimpleDateFormat;
28 import com.ibm.icu.util.GregorianCalendar;
29 import com.ibm.icu.util.SimpleTimeZone;
30 import com.ibm.icu.util.ULocale;
31
32 /**
33  * TimeZone transition dump tool.
34  */
35 public class ICUZDump {
36     private static final String DEFAULT_LINE_SEP;
37
38     static {
39         String sep = System.getProperty("line.separator");
40         DEFAULT_LINE_SEP = (sep == null) ? "\n" : sep;
41     }
42
43     private TimeZoneImpl tz = null;
44
45     private int loyear = 1900;
46     private int hiyear = 2050;
47     private long tick = 1000;
48     private DumpFormatter formatter;
49     private String linesep = DEFAULT_LINE_SEP;
50
51     public ICUZDump() {
52     }
53     
54     public void setLowYear(int loyear) {
55         this.loyear = loyear;
56     }
57     
58     public void setHighYear(int hiyear) {
59         this.hiyear = hiyear;
60     }
61
62     public void setTick(int tick) {
63         if (tick <= 0) {
64             throw new IllegalArgumentException("tick must be positive");
65         }
66         this.tick = tick;
67     }
68     
69     public void setTimeZone(Object tzimpl) {
70         this.tz = new TimeZoneImpl(tzimpl);
71     }
72
73     public void setDumpFormatter(DumpFormatter formatter) {
74         this.formatter = formatter;
75     }
76     
77     public void setLineSeparator(String sep) {
78         this.linesep = sep;
79     }
80     
81     public void dump(Writer w) throws IOException {
82         if (tz == null) {
83             throw new IllegalStateException("timezone is not initialized");
84         }
85
86         if (formatter == null) {
87             formatter = new DumpFormatter();
88         }
89         
90         final long SEARCH_INCREMENT = 12 * 60 * 60 * 1000; // half day
91         long cutovers[] = getCutOverTimes();
92         long t = cutovers[0];
93         int offset = tz.getOffset(t);
94         boolean inDst = tz.inDaylightTime(t);
95         while (t < cutovers[1]) {
96             long newt = t + SEARCH_INCREMENT;
97             int newOffset = tz.getOffset(newt);
98             boolean newInDst = tz.inDaylightTime(newt);
99             if (offset != newOffset || inDst != newInDst) {
100                 // find the boundary
101                 long lot = t;
102                 long hit = newt;
103                 while (true) {
104                     long diff = hit - lot;
105                     if (diff <= tick) {
106                         break;
107                     }
108                     long medt = lot + ((diff / 2) / tick) * tick;
109                     int medOffset = tz.getOffset(medt);
110                     boolean medInDst = tz.inDaylightTime(medt);
111                     if (medOffset != offset || medInDst != inDst) {
112                         hit = medt;
113                     } else {
114                         lot = medt;
115                     }
116                 }
117                 w.write(formatter.format(lot, offset, tz.inDaylightTime(lot)));
118                 w.write(" > ");
119                 w.write(formatter.format(hit, newOffset, tz.inDaylightTime(hit)));
120                 w.write(linesep);
121                 offset = newOffset;
122                 inDst = newInDst;
123             }
124             t = newt;
125         }
126
127     }
128     
129     private long[] getCutOverTimes() {
130         long[] cutovers = new long[2];
131         cutovers[0] = tz.getTime(loyear, 0, 1, 0, 0, 0);
132         cutovers[1] = tz.getTime(hiyear, 0, 1, 0, 0, 0);
133         return cutovers;
134     }
135
136     private class TimeZoneImpl {
137         private Object tzobj;
138         
139         public TimeZoneImpl(Object tzobj) {
140             this.tzobj = tzobj;
141         }
142
143         public int getOffset(long time) {
144             try {
145                 Method method = tzobj.getClass().getMethod("getOffset", new Class[] {long.class});
146                 Object result = method.invoke(tzobj, new Object[] {new Long(time)});
147                 return ((Integer)result).intValue();
148             } catch (Exception e) {
149                 e.printStackTrace();
150             }
151             return 0;
152         }
153
154         public boolean inDaylightTime(long time) {
155             try {
156                 Method method = tzobj.getClass().getMethod("inDaylightTime", new Class[] {Date.class});
157                 Object result = method.invoke(tzobj, new Object[] {new Date(time)});
158                 return ((Boolean)result).booleanValue();
159             } catch (Exception e) {
160                 e.printStackTrace();
161             }
162             return false;
163         }
164
165         public long getTime(int year, int month, int dayOfMonth, int hour, int minute, int second) {
166             long time;
167             if (tzobj instanceof com.ibm.icu.util.TimeZone) {
168                 GregorianCalendar cal = new GregorianCalendar();
169                 cal.setTimeZone((com.ibm.icu.util.TimeZone)tzobj);
170                 cal.clear();
171                 cal.set(year, month, dayOfMonth, hour, minute, second);
172                 time = cal.getTimeInMillis();
173             } else if (tzobj instanceof java.util.TimeZone) {
174                 java.util.GregorianCalendar cal = new java.util.GregorianCalendar();
175                 cal.setTimeZone((java.util.TimeZone)tzobj);
176                 cal.clear();
177                 cal.set(year, month, dayOfMonth, hour, minute, second);
178                 time = cal.getTimeInMillis();
179             } else {
180                 throw new IllegalStateException("Unsupported TimeZone implementation");
181             }
182             return time;
183         }
184     }
185
186     public class DumpFormatter {
187         private SimpleTimeZone stz = new SimpleTimeZone(0, "");
188         private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd EEE HH:mm:ss", ULocale.US);
189         private DecimalFormat decf;
190
191         public DumpFormatter() {
192             DecimalFormatSymbols decfs = new DecimalFormatSymbols(ULocale.US);
193             decf = new DecimalFormat("00", decfs);
194         }
195
196         public String format(long time, int offset, boolean isDst) {
197             StringBuffer buf = new StringBuffer();
198             stz.setRawOffset(offset);
199             sdf.setTimeZone(stz);
200             buf.append(sdf.format(new Date(time)));
201             if (offset < 0) {
202                 buf.append("-");
203                 offset = -offset;
204             } else {
205                 buf.append("+");
206             }
207
208             int hour, min, sec;
209
210             offset /= 1000;
211             sec = offset % 60;
212             offset = (offset - sec) / 60;
213             min = offset % 60;
214             hour = offset / 60;
215
216             buf.append(decf.format(hour));
217             buf.append(decf.format(min));
218             buf.append(decf.format(sec));
219
220             buf.append("[DST=");
221             buf.append(isDst ? "1" : "0");
222             buf.append("]");
223             return buf.toString();
224         }
225     }
226
227     /*
228      * Usage:
229      * 
230      * java -cp icu4j.jar com.ibm.icu.dev.tool.timezone [-j] [-a] [-c[<low_year>,]<high_year>] [-d<dir>] [-l<sep>] [<zone_name> [<zone_name>]]
231      * 
232      * Options:
233      *      -j      : Use JDK TimeZone.  By default, ICU TimeZone is used.
234      *      -a      : Dump all available zones.
235      *      -c[<low_year>,]<high_year>
236      *              : When specified, dump transitions starting <low_year> (inclusive) up to
237      *                <high_year> (exclusive).  The default values are 1902(low) and 2038(high).
238      *      -d<dir> : When specified, write transitions in a file under the directory for each zone.
239      *      -l<sep> : New line code type CR/LF/CRLF.
240      */
241     public static void main(String[] args) {
242         boolean jdk = false;
243         int low = 1902;
244         int high = 2038;
245         List idlist = new ArrayList();
246         boolean all = false;
247         String dir = null;
248         String newLineMode = null;
249         for (int i = 0; i < args.length; i++) {
250             if (args[i].equals("-j")) {
251                 jdk = true;
252             } else if (args[i].startsWith("-c")) {
253                 String val = args[i].substring(2);
254                 String[] years = val.split(",");
255                 if (years.length == 1) {
256                     high = Integer.parseInt(years[0]);
257                 } else if (years.length == 2) {
258                     low = Integer.parseInt(years[0]);
259                     high = Integer.parseInt(years[1]);
260                 }
261             } else if (args[i].equals("-a")) {
262                 all = true;
263             } else if (args[i].startsWith("-d")) {
264                 dir = args[i].substring(2);
265             } else if (args[i].startsWith("-l")) {
266                 newLineMode = args[i].substring(2);
267             } else if (!args[i].startsWith("-")){
268                 idlist.add(args[i].trim());
269             }
270         }
271
272         String lineSep = System.getProperty("line.separator");
273         if (newLineMode != null && newLineMode.length() > 0) {
274             if (newLineMode.equalsIgnoreCase("CR")) {
275                 lineSep = "\r";
276             } else if (newLineMode.equalsIgnoreCase("LF")) {
277                 lineSep = "\n";
278             } else if (newLineMode.equalsIgnoreCase("CRLF")) {
279                 lineSep = "\r\n";            
280             }
281         }
282         
283         String[] tzids = null;
284
285         if (all) {
286             if (jdk) {
287                 tzids = java.util.TimeZone.getAvailableIDs();
288             } else {
289                 tzids = com.ibm.icu.util.TimeZone.getAvailableIDs();
290             }
291
292             // sort tzids
293             TreeSet set = new TreeSet();
294             for (int i = 0; i < tzids.length; i++) {
295                 set.add(tzids[i]);
296             }
297             Iterator it = set.iterator();
298             int i = 0;
299             while (it.hasNext()) {
300                 tzids[i++] = (String)it.next();
301             }
302         } else {
303             int len = idlist.size();
304             if (len == 0) {
305                 tzids = new String[1];
306                 tzids[0] = java.util.TimeZone.getDefault().getID();
307             } else {
308                 tzids = new String[idlist.size()];
309                 idlist.toArray(tzids);
310             }            
311         }
312
313         File dirfile = null;
314         if (dir == null || dir.length() == 0) {
315             PrintWriter pw = new PrintWriter(System.out);
316             try {
317                 for (int i = 0; i < tzids.length; i++) {
318                     if (i != 0) {
319                         pw.println();
320                     }
321                     pw.write("ZONE: ");
322                     pw.write(tzids[i]);
323                     pw.println();
324                     dumpZone(pw, lineSep, tzids[i], low, high, jdk);
325                 }
326                 pw.flush();
327             } catch (IOException ioe) {
328                 ioe.printStackTrace();
329             }
330         } else {
331             dirfile = new File(dir);
332             dirfile.mkdirs();
333
334             try {
335                 for (int i = 0; i < tzids.length; i++) {
336                     FileOutputStream fos = new FileOutputStream(new File(dirfile, tzids[i].replace('/', '-')));
337                     Writer w = new BufferedWriter(new OutputStreamWriter(fos));
338                     dumpZone(w, lineSep, tzids[i], low, high, jdk);
339                     w.close();
340                 }
341             } catch (IOException ioe) {
342                 ioe.printStackTrace();
343             }
344         }
345     }
346
347     private static void dumpZone(Writer w, String lineSep, String tzid, int low, int high, boolean isJdk) throws IOException {
348         ICUZDump dumper = new ICUZDump();
349         Object tzimpl;
350         if (isJdk) {
351             tzimpl = java.util.TimeZone.getTimeZone(tzid);
352         } else {
353             tzimpl = com.ibm.icu.util.TimeZone.getTimeZone(tzid);
354         }
355         dumper.setTimeZone(tzimpl);
356         dumper.setLowYear(low);
357         dumper.setHighYear(high);
358         dumper.setLineSeparator(lineSep);
359         dumper.dump(w);
360     }
361 }