1 package org.unicode.cldr.tool; 2 3 import com.ibm.icu.util.TimeZone; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 import java.text.ParseException; 7 import java.util.Arrays; 8 import java.util.Collection; 9 import java.util.Comparator; 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Set; 13 import java.util.TreeMap; 14 import java.util.TreeSet; 15 import org.unicode.cldr.draft.FileUtilities; 16 import org.unicode.cldr.util.ArrayComparator; 17 import org.unicode.cldr.util.CLDRPaths; 18 import org.unicode.cldr.util.CldrUtility; 19 import org.unicode.cldr.util.Factory; 20 import org.unicode.cldr.util.ICUServiceBuilder; 21 import org.unicode.cldr.util.StandardCodes; 22 import org.unicode.cldr.util.Tabber; 23 import org.unicode.cldr.util.TimezoneFormatter; 24 import org.unicode.cldr.util.ZoneInflections; 25 26 public class ShowZoneEquivalences { 27 main(String[] args)28 public static void main(String[] args) throws Exception { 29 double deltaTime = System.currentTimeMillis(); 30 try { 31 ShowZoneEquivalences.getZoneEquivalences(); 32 } finally { 33 deltaTime = System.currentTimeMillis() - deltaTime; 34 System.out.println("Elapsed: " + deltaTime / 1000.0 + " seconds"); 35 System.out.println("Done"); 36 } 37 } 38 getZoneEquivalences()39 public static void getZoneEquivalences() throws IOException, ParseException { 40 // String tzid = "America/Argentina/ComodRivadavia"; 41 // TimeZone tz = TimeZone.getTimeZone(tzid); 42 // int offset = tz.getOffset(new Date().getTime()); 43 // System.out.println(tzid + ":\t" + offset); 44 // System.out.println("in available? " + 45 // Arrays.asList(TimeZone.getAvailableIDs()).contains(tzid)); 46 // System.out.println(new TreeSet(Arrays.asList(TimeZone.getAvailableIDs()))); 47 48 Set<String> needsTranslation = 49 new TreeSet<>(Arrays.asList(CountItems.needsTranslationString.split("[,]?\\s+"))); 50 Set<String> singleCountries = 51 new TreeSet<>( 52 Arrays.asList( 53 "Africa/Bamako America/Godthab America/Santiago America/Guayaquil Asia/Shanghai Asia/Tashkent Asia/Kuala_Lumpur Europe/Madrid Europe/Lisbon Europe/London Pacific/Auckland Pacific/Tahiti" 54 .split("\\s"))); 55 Set<String> defaultItems = 56 new TreeSet<>( 57 Arrays.asList( 58 "Antarctica/McMurdo America/Buenos_Aires Australia/Sydney America/Sao_Paulo America/Toronto Africa/Kinshasa America/Santiago Asia/Shanghai America/Guayaquil Europe/Madrid Europe/London America/Godthab Asia/Jakarta Africa/Bamako America/Mexico_City Asia/Kuala_Lumpur Pacific/Auckland Europe/Lisbon Europe/Moscow Europe/Kiev America/New_York Asia/Tashkent Pacific/Tahiti Pacific/Kosrae Pacific/Tarawa Asia/Almaty Pacific/Majuro Asia/Ulaanbaatar Arctic/Longyearbyen Pacific/Midway" 59 .split("\\s"))); 60 61 StandardCodes sc = StandardCodes.make(); 62 Collection<String> codes = sc.getGoodAvailableCodes("tzid"); 63 TreeSet<String> extras = new TreeSet<>(); 64 Map<String, Set<String>> m = sc.getZoneLinkNew_OldSet(); 65 for (String code : codes) { 66 Collection<String> s = m.get(code); 67 if (s == null) continue; 68 extras.addAll(s); 69 } 70 extras.addAll(codes); 71 Set<String> icu4jTZIDs = new TreeSet<>(Arrays.asList(TimeZone.getAvailableIDs())); 72 Set<String> diff2 = new TreeSet<>(icu4jTZIDs); 73 diff2.removeAll(extras); 74 System.out.println("icu4jTZIDs - StandardCodes: " + diff2); 75 diff2 = new TreeSet<>(extras); 76 diff2.removeAll(icu4jTZIDs); 77 System.out.println("StandardCodes - icu4jTZIDs: " + diff2); 78 ArrayComparator ac = 79 new ArrayComparator( 80 new Comparator[] { 81 ArrayComparator.COMPARABLE, 82 ArrayComparator.COMPARABLE, 83 ArrayComparator.COMPARABLE 84 }); 85 Map<String, String> zone_countries = sc.getZoneToCounty(); 86 87 TreeSet<Object[]> country_inflection_names = new TreeSet<Object[]>(ac); 88 PrintWriter out = FileUtilities.openUTF8Writer(CLDRPaths.GEN_DIRECTORY, "inflections.txt"); 89 90 TreeMap<Integer, TreeSet<String>> minOffsetMap = new TreeMap<>(); 91 TreeMap<Integer, TreeSet<String>> maxOffsetMap = new TreeMap<>(); 92 93 for (Iterator<String> it = codes.iterator(); it.hasNext(); ) { 94 String zoneID = it.next(); 95 String country = zone_countries.get(zoneID); 96 TimeZone zone = TimeZone.getTimeZone(zoneID); 97 ZoneInflections zip = new ZoneInflections(zone); 98 out.println(zoneID + "\t" + zip); 99 country_inflection_names.add(new Object[] {country, zip, zoneID}); 100 101 TreeSet<String> s = minOffsetMap.get(zip.getMinOffset()); 102 if (s == null) minOffsetMap.put(zip.getMinOffset(), s = new TreeSet<>()); 103 s.add(zone.getID()); 104 105 s = maxOffsetMap.get(zip.getMaxOffset()); 106 if (s == null) maxOffsetMap.put(zip.getMaxOffset(), s = new TreeSet<>()); 107 s.add(zone.getID()); 108 } 109 System.out.println("Minimum Offset: " + minOffsetMap); 110 System.out.println("Maximum Offset: " + maxOffsetMap); 111 out.close(); 112 113 out = 114 FileUtilities.openUTF8Writer( 115 CLDRPaths.GEN_DIRECTORY, "modernTimezoneEquivalents.html"); 116 out.println( 117 "<html>" 118 + "<head>" 119 + "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" 120 + "<title>Modern Equivalent Timezones</title><style>"); 121 out.println("td.top,td.topr { background-color: #EEEEFF }"); 122 out.println("td.r,td.topr { text-align:right }"); 123 out.println( 124 "td.gap { font-weight:bold; border-top: 3px solid #0000FF; border-bottom: 3px solid #0000FF; background-color: #CCCCCC }"); 125 out.println( 126 "</style>" 127 + "</head>" 128 + "<body>" 129 + "<table border='1' cellspacing='0' cellpadding='2' style='border-collapse: collapse'>"); 130 Tabber.HTMLTabber tabber1 = new Tabber.HTMLTabber(); 131 tabber1.setParameters(4, "class='r'"); 132 tabber1.setParameters(5, "class='r'"); 133 Tabber.HTMLTabber tabber2 = new Tabber.HTMLTabber(); 134 tabber2.setParameters(0, "class='top'"); 135 tabber2.setParameters(1, "class='top'"); 136 tabber2.setParameters(2, "class='top'"); 137 tabber2.setParameters(3, "class='top'"); 138 tabber2.setParameters(4, "class='topr'"); 139 tabber2.setParameters(5, "class='topr'"); 140 Tabber.HTMLTabber tabber3 = new Tabber.HTMLTabber(); 141 tabber3.setParameters(0, "class='gap'"); 142 tabber3.setParameters(1, "class='gap'"); 143 tabber3.setParameters(2, "class='gap'"); 144 tabber3.setParameters(3, "class='gap'"); 145 tabber3.setParameters(4, "class='gap'"); 146 tabber3.setParameters(5, "class='gap'"); 147 148 long minimumDate = ICUServiceBuilder.isoDateParse("2000-1-1T00:00:00Z").getTime(); 149 out.println( 150 "<h1>Modern Equivalent Timezones: <a target='_blank' href='instructions.html'>Instructions</a></h1>"); 151 out.println(ShowData.dateFooter()); 152 out.println( 153 "<p>Zones identical after: " 154 + ICUServiceBuilder.isoDateFormat(minimumDate) 155 + "</p>"); 156 String lastCountry = ""; 157 ZoneInflections.OutputLong diff = new ZoneInflections.OutputLong(0); 158 Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*"); 159 TimezoneFormatter tzf = new TimezoneFormatter(cldrFactory, "en", true); 160 Map<String, Set<String>> country_zoneSet = sc.getCountryToZoneSet(); 161 boolean shortList = true; 162 boolean first = true; 163 int category = 1; 164 Tabber tabber = tabber1; 165 for (Iterator<Object[]> it = country_inflection_names.iterator(); it.hasNext(); ) { 166 Object[] row = it.next(); 167 String country = (String) row[0]; 168 if (country.equals("001")) continue; 169 if (shortList && (country_zoneSet.get(country)).size() < 2) continue; 170 ZoneInflections zip = (ZoneInflections) row[1]; 171 String zoneID = (String) row[2]; 172 173 if (!country.equals(lastCountry)) { 174 if (first) first = false; 175 category = 1; 176 CountItems.subheader(out, tabber3); 177 } else if (diff.value >= minimumDate) { 178 // out.println(tabber.process("\tDiffers at:\t" + 179 // ICUServiceBuilder.isoDateFormat(diff.value))); 180 tabber = tabber == tabber1 ? tabber2 : tabber1; 181 ++category; 182 } 183 String zoneIDShown = zoneID; 184 if (needsTranslation.contains(zoneID)) { 185 zoneIDShown = "<b>" + zoneIDShown + "\u00B9</b>"; 186 } 187 if (singleCountries.contains(zoneID)) { 188 zoneIDShown = "<i>" + zoneIDShown + "</i> \u00B2"; 189 } 190 if (defaultItems.contains(zoneID)) { 191 zoneIDShown = 192 "<span style='background-color: #FFFF00'>" + zoneIDShown + "</span> ?"; 193 } 194 // if (country.equals(lastCountry) && diff.value >= minimumDate) System.out.print("X"); 195 String newCountry = country; 196 String mapLink = CountItems.country_map.get(country); 197 if (mapLink != null) { 198 newCountry = "<a target='map' href='" + mapLink + "'>" + country + "</a>"; 199 } 200 String minOffset = ZoneInflections.formatHours(zip.getMinOffset(minimumDate)); 201 String maxOffset = ZoneInflections.formatHours(zip.getMaxOffset(minimumDate)); 202 if (!icu4jTZIDs.contains(zoneID)) { 203 minOffset = maxOffset = "??"; 204 } 205 206 out.println( 207 tabber.process( 208 newCountry 209 + "\t" 210 + "<b>" 211 + category 212 + "</b>" 213 + "\t" 214 + zoneIDShown 215 + "\t" 216 + tzf.getFormattedZone(zoneID, "vvvv", minimumDate, false) 217 + "\t" 218 + minOffset 219 + "\t" 220 + maxOffset)); 221 lastCountry = country; 222 } 223 CountItems.subheader(out, tabber3); 224 out.println("</table>"); 225 out.println(CldrUtility.ANALYTICS); 226 out.println("</body></html>"); 227 out.close(); 228 } 229 } 230