• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.util;
2 
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.util.Arrays;
6 import java.util.Date;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Locale;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Set;
15 import java.util.TreeMap;
16 import java.util.TreeSet;
17 import java.util.regex.Matcher;
18 
19 import org.unicode.cldr.draft.FileUtilities;
20 import org.unicode.cldr.tool.Option;
21 import org.unicode.cldr.tool.Option.Options;
22 import org.unicode.cldr.tool.TablePrinter;
23 import org.unicode.cldr.util.SupplementalDataInfo.DateRange;
24 import org.unicode.cldr.util.SupplementalDataInfo.MetaZoneRange;
25 import org.unicode.cldr.util.TimezoneFormatter.Format;
26 
27 import com.ibm.icu.impl.Row.R5;
28 import com.ibm.icu.text.MessageFormat;
29 import com.ibm.icu.text.SimpleDateFormat;
30 import com.ibm.icu.util.TimeZone;
31 import com.ibm.icu.util.ULocale;
32 
33 public class VerifyZones {
34     private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance();
35 
36     private static final String DIR = CLDRPaths.CHART_DIRECTORY + "verify/zones/";
37 
38     private static final boolean DEBUG = false;
39 
40     final static Options myOptions = new Options();
41 
42     enum MyOptions {
43         organization(".*", "CLDR", "organization"), filter(".*", ".*", "locale filter (regex)"), timezoneFilter(".*", null, "timezone filter (regex)"),;
44         // boilerplate
45         final Option option;
46 
MyOptions(String argumentPattern, String defaultArgument, String helpText)47         MyOptions(String argumentPattern, String defaultArgument, String helpText) {
48             option = myOptions.add(this, argumentPattern, defaultArgument, helpText);
49         }
50     }
51 
52     static long date = new Date(new Date().getYear(), 0, 15, 0, 0, 0).getTime();
53     static long date6 = date + 182L * 24 * 60 * 60 * 1000;
54 
55     static class MetazoneRow extends R5<Long, String, String, Integer, String> {
MetazoneRow(Integer order, Integer rawOffset, String container, int orderInMetazone, String metazone, String zone)56         public MetazoneRow(Integer order, Integer rawOffset, String container, int orderInMetazone, String metazone, String zone) {
57             super(((long) order << 32) + rawOffset, container, metazone, orderInMetazone, zone);
58         }
59 
getContainer()60         public String getContainer() {
61             return get1();
62         }
63 
getMetazone()64         public String getMetazone() {
65             return get2();
66         }
67 
getZone()68         public String getZone() {
69             return get4();
70         }
71     }
72 
73     public static class ZoneFormats {
74         private String gmtFormat;
75         private String hourFormat;
76         private String[] hourFormatPlusMinus;
77         private ICUServiceBuilder icuServiceBuilder = new ICUServiceBuilder();
78         private CLDRFile cldrFile;
79 
80         public enum Length {
81             LONG, SHORT;
toString()82             public String toString() {
83                 return name().toLowerCase(Locale.ENGLISH);
84             }
85         }
86 
87         public enum Type {
88             generic, standard, daylight, genericOrStandard
89         }
90 
set(CLDRFile cldrFile)91         public ZoneFormats set(CLDRFile cldrFile) {
92             this.cldrFile = cldrFile;
93 
94             gmtFormat = cldrFile.getWinningValue("//ldml/dates/timeZoneNames/gmtFormat");
95             hourFormat = cldrFile.getWinningValue("//ldml/dates/timeZoneNames/hourFormat");
96             hourFormatPlusMinus = hourFormat.split(";");
97             icuServiceBuilder.setCldrFile(cldrFile);
98             return this;
99         }
100 
formatGMT(TimeZone currentZone)101         public String formatGMT(TimeZone currentZone) {
102             int tzOffset = currentZone.getRawOffset();
103             SimpleDateFormat dateFormat = icuServiceBuilder.getDateFormat("gregorian",
104                 hourFormatPlusMinus[tzOffset >= 0 ? 0 : 1]);
105             String hoursMinutes = dateFormat.format(tzOffset >= 0 ? tzOffset : -tzOffset);
106             return MessageFormat.format(gmtFormat, hoursMinutes);
107         }
108 
getExemplarCity(String timezoneString)109         public String getExemplarCity(String timezoneString) {
110             String exemplarCity = cldrFile.getWinningValue("//ldml/dates/timeZoneNames/zone[@type=\"" + timezoneString
111                 + "\"]/exemplarCity");
112             if (exemplarCity == null) {
113                 exemplarCity = timezoneString.substring(timezoneString.lastIndexOf('/') + 1).replace('_', ' ');
114             }
115             return exemplarCity;
116         }
117 
getMetazoneName(String metazone, Length length, Type typeIn)118         public String getMetazoneName(String metazone, Length length, Type typeIn) {
119             Type type = typeIn == Type.genericOrStandard ? Type.generic : typeIn;
120             String name = cldrFile.getWinningValue("//ldml/dates/timeZoneNames/metazone[@type=\""
121                 + metazone + "\"]/" + length + "/" + type);
122 
123             return name != null ? name : typeIn != Type.genericOrStandard ? "n/a" : getMetazoneName(metazone, length,
124                 Type.standard);
125         }
126     }
127 
128     private final static SupplementalDataInfo sdi = SupplementalDataInfo.getInstance();
129     private final static Map<String, Map<String, String>> metazoneToRegionToZone = sdi.getMetazoneToRegionToZone();
130     private final static Set<MetazoneRow> rows = new TreeSet<MetazoneRow>();
131     private final static Set<String> goldenZones = new HashSet<String>();
132     private final static Map<String, Integer> countryToOrder = new HashMap<String, Integer>();
133 
134     private final static List<Format> FORMAT_LIST = Arrays.asList(Format.VVVV, Format.vvvv, Format.v, Format.zzzz,
135         Format.z, Format.zzzz, Format.z);
136     static {
137 
138         // find out which canonical zones are not in a metazone
139         Map<String, String> nameToCountry = new TreeMap<String, String>();
140         String[] zones = TimeZone.getAvailableIDs();
141         Set<String> zoneSet = new LinkedHashSet<String>();
142         Set<String> noncanonical = new LinkedHashSet<String>();
143         for (String zone : zones) {
144             String countryCode = TimeZone.getRegion(zone);
145             String englishTerritory = ULocale.getDisplayCountry("und-" + countryCode, ULocale.ENGLISH);
nameToCountry.put(englishTerritory, countryCode)146             nameToCountry.put(englishTerritory, countryCode);
147             String canon = TimeZone.getCanonicalID(zone);
148             if (canon.equals(zone)) {
149                 zoneSet.add(canon);
150             } else {
151                 noncanonical.add(zone);
152             }
153         }
154 
155         // get mapping of country names to ints
156         int i = 0;
157         for (Entry<String, String> entry : nameToCountry.entrySet()) {
entry.getValue()158             countryToOrder.put(entry.getValue(), i++);
159         }
160 
161         //System.out.println("Canonical zones:\t" + zoneSet.size() + "\t" + zoneSet);
162         //System.out.println("Non-canonical zones:\t" + noncanonical.size() + "\t" + noncanonical);
163 
164         Set<String> metazones = sdi.getAllMetazones();
165         if (DEBUG && !metazones.equals(metazoneToRegionToZone.keySet())) {
166             System.out.println("Mismatch between metazones");
showVennSets(metazones, metazoneToRegionToZone.keySet())167             showVennSets(metazones, metazoneToRegionToZone.keySet());
168         }
169 
170         Set<String> zonesInMetazones = new LinkedHashSet<String>();
171         for (String metazone : metazones) {
172             //String container = PathHeader.getMetazonePageTerritory(metazone);
173             Map<String, String> regionToZone = metazoneToRegionToZone.get(metazone);
174             String zone = regionToZone.get("001");
175             goldenZones.add(zone);
176             zonesInMetazones.add(zone);
177             //            TimeZone currentZone = TimeZone.getTimeZone(tz_string);
178             //            int order = Containment.getOrder(container);
179             //            int offsetOrder = currentZone.getRawOffset();
180             //            MetazoneRow row = new MetazoneRow(order, offsetOrder, container, 0, metazone, tz_string);
181             //            rows.add(row);
addRow(metazone, zone, 0)182             addRow(metazone, zone, 0);
183         }
184         //System.out.println("Zones. A = canonical zones, B = zones in metazonesToRegionToZone");
185         //showVennSets(zoneSet, zonesInMetazones);
vennSets(zoneSet, zonesInMetazones)186         vennSets(zoneSet, zonesInMetazones);
187         Set<String> found = new LinkedHashSet<String>();
188         for (String zone : zoneSet) {
189             Set<MetaZoneRange> metaZoneRanges = sdi.getMetaZoneRanges(zone);
190             if (metaZoneRanges == null) {
191                 continue;
192             }
193             for (MetaZoneRange metaZoneRange : metaZoneRanges) {
194                 if (metaZoneRange.dateRange.getTo() == DateRange.END_OF_TIME) {
195                     found.add(zone);
addRow(metaZoneRange.metazone, zone, 1)196                     addRow(metaZoneRange.metazone, zone, 1);
197                     break;
198                 }
199             }
200         }
201         //        zoneSet.removeAll(found);
202         //        for (String zone : zoneSet) {
203         //            found.add(zone);
204         //            //            TimeZone currentZone = TimeZone.getTimeZone(tz_string);
205         //            //            int offsetOrder = currentZone.getRawOffset();
206         //            //            MetazoneRow row = new MetazoneRow(Integer.MAX_VALUE, offsetOrder, "001", 1, "None", tz_string);
207         //            //            rows.add(row);
208         //            addRow("None", zone, 1);
209         //        }
210         if (DEBUG) System.out.println("\nSorted");
211         for (MetazoneRow row : rows) {
212             if (row.getMetazone().equals("Europe_Central")) {
213                 if (DEBUG) System.out.println(row);
214             }
215         }
216     }
217 
addRow(String metaZone, String tz_string, int orderInMetazone)218     private static void addRow(String metaZone, String tz_string, int orderInMetazone) {
219         TimeZone currentZone = TimeZone.getTimeZone(tz_string);
220         String container = PathHeader.getMetazonePageTerritory(metaZone);
221         if (container == null) {
222             return; // skip
223         }
224         int order = Containment.getOrder(container);
225         int offsetOrder = currentZone.getRawOffset();
226         orderInMetazone = (orderInMetazone << 16)
227             | (hasDaylight(currentZone) ? 0 : 1)
228             | countryToOrder.get(TimeZone.getRegion(tz_string));
229         MetazoneRow row = new MetazoneRow(order, offsetOrder, container,
230             orderInMetazone, metaZone, tz_string);
231         if (metaZone.equals("Europe_Central")) {
232             if (DEBUG) System.out.println(row);
233         }
234         rows.add(row);
235     }
236 
showVennSets(Set<String> zoneSet, Set<String> zonesInMetazones)237     private static void showVennSets(Set<String> zoneSet, Set<String> zonesInMetazones) {
238         Set<String> common = new LinkedHashSet<String>();
239         Set<String> firstMinusSecond = new LinkedHashSet<String>();
240         Set<String> secondMinusFirst = new LinkedHashSet<String>();
241         vennSets(zoneSet, zonesInMetazones, common, firstMinusSecond, secondMinusFirst);
242         if (!common.isEmpty()) System.out.println("A & B:\t" + common.size() + "\t" + common);
243         if (!firstMinusSecond.isEmpty()) System.out.println("A - B:\t" + firstMinusSecond.size() + "\t" + firstMinusSecond);
244         if (!secondMinusFirst.isEmpty()) System.out.println("B - A:\t" + secondMinusFirst.size() + "\t" + secondMinusFirst);
245     }
246 
vennSets(Set<T> first, Set<T> second, Set<T> common, Set<T> firstMinusSecond, Set<T> secondMinusFirst)247     private static <T> void vennSets(Set<T> first, Set<T> second,
248         Set<T> common, Set<T> firstMinusSecond, Set<T> secondMinusFirst) {
249         common.clear();
250         common.addAll(first);
251         common.retainAll(second);
252         firstMinusSecond.clear();
253         firstMinusSecond.addAll(first);
254         firstMinusSecond.removeAll(common);
255         secondMinusFirst.clear();
256         secondMinusFirst.addAll(second);
257         secondMinusFirst.removeAll(common);
258     }
259 
260     @SuppressWarnings("unused")
vennSets(Set<T> first, Set<T> second, Set<T> common)261     private static <T> void vennSets(Set<T> first, Set<T> second, Set<T> common) {
262         common.clear();
263         common.addAll(first);
264         common.retainAll(second);
265         first.removeAll(common);
266         second.removeAll(common);
267     }
268 
vennSets(Set<T> first, Set<T> second)269     private static <T> void vennSets(Set<T> first, Set<T> second) {
270         first.removeAll(second);
271         second.removeAll(first);
272     }
273 
274     /**
275      * Produce a set of static tables from the vxml data. Only a stopgap until the above is integrated into ST.
276      *
277      * @param args
278      * @throws IOException
279      */
main(String[] args)280     public static void main(String[] args) throws IOException {
281         myOptions.parse(MyOptions.organization, args, true);
282 
283         String organization = MyOptions.organization.option.getValue();
284         String filter = MyOptions.filter.option.getValue();
285         String timezoneFilterString = MyOptions.timezoneFilter.option.getValue();
286         Matcher timezoneFilter = timezoneFilterString == null ? null : PatternCache.get(timezoneFilterString)
287             .matcher("");
288 
289         Factory factory2 = Factory.make(CLDRPaths.MAIN_DIRECTORY, filter);
290         CLDRFile englishCldrFile = factory2.make("en", true);
291         DateTimeFormats.writeCss(DIR);
292         final CLDRFile english = CLDR_CONFIG.getEnglish();
293 
294         Map<String, String> indexMap = new TreeMap<>(CLDR_CONFIG.getCollator());
295 
296         for (String localeID : factory2.getAvailableLanguages()) {
297             Level level = StandardCodes.make().getLocaleCoverageLevel(organization, localeID);
298             if (Level.MODERN.compareTo(level) > 0) {
299                 continue;
300             }
301             CLDRFile cldrFile = factory2.make(localeID, true);
302             PrintWriter out = FileUtilities.openUTF8Writer(DIR, localeID + ".html");
303             String title = "Verify Time Zones: " + englishCldrFile.getName(localeID);
304             out.println("<!doctype HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'><html><head>\n" +
305                 "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n" +
306                 "<title>" + title + "</title>\n" +
307                 "<link rel='stylesheet' type='text/css' href='index.css'>\n" +
308                 "</head><body><h1>" + title + "</h1>\n"
309                 + "<p><a href='index.html'>Index</a></p>\n");
310 
311             showZones(timezoneFilter, englishCldrFile, cldrFile, out);
312 
313             out.println("</body></html>");
314             out.close();
315 
316             indexMap.put(english.getName(localeID), localeID + ".html");
317         }
318         try (PrintWriter index = DateTimeFormats.openIndex(DIR, "Time Zones")) {
319             DateTimeFormats.writeIndexMap(indexMap, index);
320         }
321 
322         // Look at DateTimeFormats.java
323 
324         if (true) return;
325 
326         // Set<String> defaultContentLocales = sdi.getDefaultContentLocales();
327         // NumberFormat enf = NumberFormat.getIntegerInstance(ULocale.ENGLISH);
328         // enf.setGroupingUsed(false);
329         // Set<String> debugCreationErrors = new LinkedHashSet<String>();
330         // Set<String> errors = new LinkedHashSet<String>();
331         //
332         // for (String locale : factory2.getAvailableLanguages()) {
333         // if (defaultContentLocales.contains(locale)) {
334         // continue;
335         // }
336         // Level level = StandardCodes.make().getLocaleCoverageLevel(organization, locale);
337         // if (Level.MODERN.compareTo(level) > 0) {
338         // continue;
339         // }
340         //
341         // // one path for group-3, one for group-4
342         // int factor = USES_GROUPS_OF_4.contains(locale) ? 10000 : 1000;
343         //
344         // ULocale locale2 = new ULocale(locale);
345         // NumberFormat nf = NumberFormat.getIntegerInstance(locale2);
346         // nf.setMaximumFractionDigits(0);
347         // CLDRFile cldrFile = factory2.make(locale, true, DraftStatus.contributed);
348         // PluralInfo pluralInfo = sdi.getPlurals(locale);
349         // Set<Double> samples = new TreeSet<Double>();
350         // for (Entry<Count, List<Double>> entry : pluralInfo.getCountToExamplesMap().entrySet()) {
351         // samples.add(entry.getValue().get(0));
352         // }
353         // String[] debugOriginals = null;
354         // CompactDecimalFormat cdf = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors, debugOriginals,
355         // Style.SHORT, locale2);
356         // captureErrors(debugCreationErrors, errors, locale, "short");
357         // CompactDecimalFormat cdfs = BuildIcuCompactDecimalFormat.build(cldrFile, debugCreationErrors, debugOriginals,
358         // Style.LONG, locale2);
359         // captureErrors(debugCreationErrors, errors, locale, "long");
360         //
361         // Set<Double> samples2 = new TreeSet<Double>();
362         // for (int i = 10; i < factor; i *= 10) {
363         // for (Double sample : samples) {
364         // samples2.add(sample*i);
365         // }
366         // }
367         // samples.addAll(samples2);
368         // samples.add(1.5d);
369         // System.out.println("———\t" + englishCldrFile.getName(locale) + "\t———");
370         //
371         // String column12 = (locale + "\t" + englishCldrFile.getName(locale));
372         // System.out.print(column12 +
373         // "\tNumeric\tCompact-Short\tCompact-Long\tFixed Numeric\tFixed Compact-Short\tFixed Compact-Long\n");
374         //
375         // try {
376         // // we print the __ so that it can be imported into a spreadsheet without problems.
377         // for (long i = factor; i <= 100000000000000L; i *= factor) {
378         // for (Double sample : samples) {
379         // double source = i * sample;
380         // if (false && source == 22000000 && locale.equals("cs")) {
381         // System.out.println("**");
382         // }
383         // System.out.print(locale + "\t__" + enf.format(source));
384         // System.out.print("\t__" + nf.format(source));
385         // String formatted = cdf.format(source);
386         // System.out.print("\t__" + formatted);
387         // formatted = cdfs.format(source);
388         // System.out.println("\t__" + formatted);
389         // }
390         // System.out.println();
391         // }
392         // } catch (Exception e) {
393         // e.printStackTrace();
394         // }
395         // }
396         // for (String s : errors) {
397         // System.out.println(s);
398         // }
399     }
400 
showZones(Matcher timezoneFilter, CLDRFile englishCldrFile, CLDRFile nativeCdrFile, Appendable out)401     public static void showZones(Matcher timezoneFilter,
402         CLDRFile englishCldrFile, CLDRFile nativeCdrFile,
403         Appendable out) throws IOException {
404         TablePrinter tablePrinter = new TablePrinter() // .setCaption("Timezone Formats")
405             .setTableAttributes("class='dtf-table'")
406             .addColumn("Metazone").setHeaderCell(true).setSpanRows(true)
407             .setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'")
408             .addColumn("Region: TZID").setHeaderCell(true).setSpanRows(true)
409             .setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'")
410         //.setCellPattern(CldrUtility.getDoubleLinkMsg())
411         // HACK because anchors don't work any more
412         // .addColumn("Region: City").setHeaderCell(true).setSpanRows(true)
413         // .addColumn("Region/City").setSpanRows(true)
414         ;
415         //         .addColumn("Code", "class='source'", CldrUtility.getDoubleLinkMsg(), "class='source'", true).setSpanRows(true)
416 
417         boolean daylight = false;
418         for (Format s : FORMAT_LIST) {
419             tablePrinter.addColumn(s.toString()
420                 + "<br>" + s.type.toString(daylight)
421                 + "<br>" + s.location
422                 + "<br>" + s.length).setSpanRows(true).setHeaderAttributes("class='dtf-th'")
423                 .setCellAttributes("class='dtf-s'");
424             if (s == Format.z) {
425                 daylight = true; // reset for final 2 items
426             }
427         }
428         tablePrinter.addColumn("View").setHeaderCell(true).setHeaderAttributes("class='dtf-th'").setCellAttributes("class='dtf-s'");
429         ZoneFormats englishZoneFormats = new ZoneFormats().set(englishCldrFile);
430         addZones(englishZoneFormats, nativeCdrFile, timezoneFilter, tablePrinter);
431 
432         out.append(tablePrinter.toString() + "\n");
433     }
434 
addZones(ZoneFormats englishZoneFormats, CLDRFile cldrFile, Matcher timezoneFilter, TablePrinter output)435     private static void addZones(ZoneFormats englishZoneFormats, CLDRFile cldrFile, Matcher timezoneFilter,
436         TablePrinter output) throws IOException {
437         CLDRFile englishCldrFile = englishZoneFormats.cldrFile;
438         //ZoneFormats nativeZoneFormats = new ZoneFormats().set(cldrFile);
439         TimezoneFormatter tzformatter = new TimezoneFormatter(cldrFile);
440 
441         for (MetazoneRow row : rows) {
442             String grouping = row.getContainer();
443             String metazone = row.getMetazone();
444             String tzid = row.getZone();
445             TimeZone currentZone = TimeZone.getTimeZone(tzid);
446             TimeZone tz = currentZone;
447 
448             String englishGrouping = englishCldrFile.getName(CLDRFile.TERRITORY_NAME, grouping);
449 
450             String metazoneInfo = englishGrouping
451                 + "<br>" + englishZoneFormats.formatGMT(currentZone)
452                 + "<br>" + "MZ: " + metazone;
453 
454             boolean isGolden = goldenZones.contains(tzid);
455             String countryCode2 = TimeZone.getRegion(tzid);
456             if (countryCode2.equals("001")) {
457                 continue;
458             }
459             String englishTerritory = englishCldrFile.getName(CLDRFile.TERRITORY_NAME, countryCode2);
460             output.addRow()
461                 .addCell(metazoneInfo)
462                 .addCell(englishTerritory + ": " + tzid.replace("/", "/\u200B"));
463             long date2 = getStandardDate(tz);
464             for (Format pattern : FORMAT_LIST) {
465                 String formattedZone = tzformatter.getFormattedZone(tzid, pattern.toString(), date2);
466                 if (isGolden) {
467                     formattedZone = "<b>" + formattedZone + "</b>";
468                 }
469                 output.addCell(formattedZone);
470                 if (pattern == Format.z) {
471                     if (!hasDaylight(tz)) {
472                         output.addCell("<i>n/a</i>");
473                         output.addCell("<i>n/a</i>");
474                         break;
475                     }
476                     date2 = date2 == date ? date6 : date; // reverse for final 2 items
477                 }
478             }
479             String view = PathHeader.getLinkedView(surveyUrl, cldrFile, METAZONE_PREFIX + metazone + METAZONE_SUFFIX);
480             if (view == null) {
481                 view = PathHeader.getLinkedView(surveyUrl, cldrFile, METAZONE_PREFIX + metazone + METAZONE_SUFFIX2);
482             }
483 
484             output.addCell(view == null
485                 ? ""
486                 : view);
487             output.finishRow();
488         }
489     }
490 
491     private static String surveyUrl = CLDR_CONFIG.getProperty("CLDR_SURVEY_URL",
492         "http://st.unicode.org/cldr-apps/survey");
493 
494     static private String METAZONE_PREFIX = "//ldml/dates/timeZoneNames/metazone[@type=\"";
495     static private String METAZONE_SUFFIX = "\"]/long/generic";
496     static private String METAZONE_SUFFIX2 = "\"]/long/standard";
497 
hasDaylight(TimeZone tz)498     private static boolean hasDaylight(TimeZone tz) {
499         int dateOffset = tz.getOffset(date);
500         return dateOffset != tz.getRawOffset() || dateOffset != tz.getOffset(date6);
501     }
502 
getStandardDate(TimeZone tz)503     private static long getStandardDate(TimeZone tz) {
504         return tz.getOffset(date) == tz.getRawOffset() ? date : date6;
505     }
506 
getDaylightDate(TimeZone tz)507     private static long getDaylightDate(TimeZone tz) {
508         return tz.getOffset(date) == tz.getRawOffset() ? date6 : date;
509     }
510 
captureErrors(Set<String> debugCreationErrors, Set<String> errors, String locale, String length)511     private static void captureErrors(Set<String> debugCreationErrors, Set<String> errors, String locale, String length) {
512         if (debugCreationErrors.size() != 0) {
513             for (String s : debugCreationErrors) {
514                 errors.add(locale + "\t" + length + "\t" + s);
515             }
516             debugCreationErrors.clear();
517         }
518     }
519 }
520