code: private void buildZoneRules() throws Exception {
          // build zones
          for (String zoneId : zones.keySet()) {
              printVerbose("Building zone " + zoneId);
              zoneId = deduplicate(zoneId);
              List<TZDBZone> tzdbZones = zones.get(zoneId);
              ZoneRulesBuilder bld = new ZoneRulesBuilder();
              for (TZDBZone tzdbZone : tzdbZones) {
                  bld = tzdbZone.addToBuilder(bld, rules);
              }
              ZoneRules buildRules = bld.toRules(zoneId, deduplicateMap);
              builtZones.put(zoneId, deduplicate(buildRules));
          }
  
          // build aliases
          for (String aliasId : links.keySet()) {
              aliasId = deduplicate(aliasId);
              String realId = links.get(aliasId);
              printVerbose("Linking alias " + aliasId + " to " + realId);
              ZoneRules realRules = builtZones.get(realId);
              if (realRules == null) {
                  realId = links.get(realId);  // try again (handle alias liked to alias)
                  printVerbose("Relinking alias " + aliasId + " to " + realId);
                  realRules = builtZones.get(realId);
                  if (realRules == null) {
                      throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId + "' for '" + version + "'");
                  }
              }
              builtZones.put(aliasId, realRules);
          }
  
          // remove UTC and GMT
          builtZones.remove("UTC");
          builtZones.remove("GMT");
          builtZones.remove("GMT0");
          builtZones.remove("GMT+0");
          builtZones.remove("GMT-0");
      }
docs: Build the rules, zones and links into real zones.
  
  @throws Exception if an error occurs