/// <summary> /// Merge two WindowsZones objects together. The result has versions present in override, /// but falling back to the original for versions absent in the override. The set of MapZones /// in the result is the union of those in the original and override, but any ID/Territory /// pair present in both results in the override taking priority, unless the override has an /// empty "type" entry, in which case the entry is removed entirely. /// /// While this method could reasonably be in WindowsZones class, it's only needed in /// TzdbCompiler - and here is as good a place as any. /// /// The resulting MapZones will be ordered by Windows ID followed by territory. /// </summary> /// <param name="windowsZones">The original WindowsZones</param> /// <param name="overrideFile">The WindowsZones to override entries in the original</param> /// <returns>A merged zones object.</returns> internal static WindowsZones MergeWindowsZones(WindowsZones originalZones, WindowsZones overrideZones) { var version = overrideZones.Version == "" ? originalZones.Version : overrideZones.Version; var tzdbVersion = overrideZones.TzdbVersion == "" ? originalZones.TzdbVersion : overrideZones.TzdbVersion; var windowsVersion = overrideZones.WindowsVersion == "" ? originalZones.WindowsVersion : overrideZones.WindowsVersion; // Work everything out using dictionaries, and then sort. var mapZones = originalZones.MapZones.ToDictionary(mz => new { mz.WindowsId, mz.Territory }); foreach (var overrideMapZone in overrideZones.MapZones) { var key = new { overrideMapZone.WindowsId, overrideMapZone.Territory }; if (overrideMapZone.TzdbIds.Count == 0) { mapZones.Remove(key); } else { mapZones[key] = overrideMapZone; } } var mapZoneList = mapZones .OrderBy(pair => pair.Key.WindowsId) .ThenBy(pair => pair.Key.Territory) .Select(pair => pair.Value) .ToList(); return(new WindowsZones(version, tzdbVersion, windowsVersion, mapZoneList)); }
/// <summary> /// Creates a string pool which contains the most commonly-used strings within the given set /// of zones first. This will allow them to be more efficiently represented when we write them out for real. /// </summary> private static List <string> CreateOptimizedStringPool( IEnumerable <DateTimeZone> zones, IEnumerable <TzdbZoneLocation> zoneLocations, IEnumerable <TzdbZone1970Location> zone1970Locations, WindowsZones cldrWindowsZones) { var optimizingWriter = new StringPoolOptimizingFakeWriter(); foreach (var zone in zones) { optimizingWriter.WriteString(zone.Id); WriteZone(zone, optimizingWriter); } if (zoneLocations != null) { foreach (var location in zoneLocations) { location.Write(optimizingWriter); } } if (zone1970Locations != null) { foreach (var location in zone1970Locations) { location.Write(optimizingWriter); } } cldrWindowsZones.Write(optimizingWriter); return(optimizingWriter.CreatePool()); }
public void Write(TzdbDatabase database, WindowsZones cldrWindowsZones) { var timeZoneMap = new Dictionary <string, string>(); foreach (var zone in database.GenerateDateTimeZones()) { timeZoneMap.Add(zone.Id, zone.Id); WriteTimeZone(zone); } // Normalize the aliases foreach (var key in database.Aliases.Keys) { var value = database.Aliases[key]; while (database.Aliases.ContainsKey(value)) { value = database.Aliases[value]; } timeZoneMap.Add(key, value); } resourceWriter.AddResource(TzdbResourceData.VersionKey, database.Version); WriteDictionary(TzdbResourceData.IdMapKey, timeZoneMap); WriteDictionary(TzdbResourceData.WindowsToPosixMapKey, cldrWindowsZones.PrimaryMapping); resourceWriter.AddResource(TzdbResourceData.WindowsToPosixMapVersionKey, cldrWindowsZones.Version); resourceWriter.Close(); }
private static void LogWindowsZonesSummary(WindowsZones windowsZones) { Console.WriteLine("Windows Zones:"); Console.WriteLine(" Version: {0}", windowsZones.Version); Console.WriteLine(" TZDB version: {0}", windowsZones.TzdbVersion); Console.WriteLine(" Windows version: {0}", windowsZones.WindowsVersion); Console.WriteLine(" {0} MapZones", windowsZones.MapZones.Count); Console.WriteLine(" {0} primary mappings", windowsZones.PrimaryMapping.Count); }
private TzdbResourceData(ResourceSet source) { this.source = source; tzdbIdMap = CheckKey(LoadDictionary(source, IdMapKey), IdMapKey); tzdbVersion = CheckKey(source.GetString(VersionKey), VersionKey); var windowsMappingVersion = CheckKey(source.GetString(WindowsToPosixMapVersionKey), WindowsToPosixMapVersionKey); var windowsMapping = CheckKey(LoadDictionary(source, WindowsToPosixMapKey), WindowsToPosixMapKey); this.windowsMapping = WindowsZones.FromPrimaryMapping(windowsMappingVersion, windowsMapping); }
public void Properties() { var zones = new WindowsZones("version", "tzdbVersion", "windowsVersion", new[] { MapZone1, MapZone2, MapZone3 }); Assert.AreEqual("version", zones.Version); Assert.AreEqual("tzdbVersion", zones.TzdbVersion); Assert.AreEqual("windowsVersion", zones.WindowsVersion); Assert.AreEqual("primaryId2", zones.PrimaryMapping["windowsId2"]); Assert.AreEqual("primaryId3", zones.PrimaryMapping["windowsId3"]); Assert.AreEqual(new[] { MapZone1, MapZone2, MapZone3 }, zones.MapZones); }
private static void ReadWindowsZones(DateTimeZoneReader reader) { var zones = WindowsZones.Read(reader); Console.WriteLine($" Version: {zones.Version}"); Console.WriteLine($" TZDB version: {zones.TzdbVersion}"); Console.WriteLine($" Windows version: {zones.WindowsVersion}"); Console.WriteLine($" Mappings: {zones.MapZones.Count}"); foreach (var mapZone in zones.MapZones) { Console.WriteLine($" {mapZone}"); } }
public void MergeWindowsZones() { var originalZones = new WindowsZones("orig-version", "orig-tzdb-version", "orig-win-version", new[] { new MapZone("ID1", "001", new[] { "A" }), new MapZone("ID1", "T1-1", new[] { "B", "C" }), new MapZone("ID1", "T1-2", new[] { "D" }), new MapZone("ID2", "001", new[] { "E" }), new MapZone("ID2", "T2-1", new[] { "F" }) }); var overrideZones = new WindowsZones("override-version", "", "", new[] { // Replace ID1 / 001 new MapZone("ID1", "001", new[] { "A1" }), // Delete ID1 / T1-1 new MapZone("ID1", "T1-1", new string[0]), // (Leave ID1 / T1-2) // Add ID1 / T1-3 new MapZone("ID1", "T1-3", new[] { "B1", "C1", "G1" }), // (Leave ID2 / 001) // Replace ID2 / T2-1 new MapZone("ID2", "T2-1", new[] { "H1" }), // Add ID3 / 001 new MapZone("ID3", "001", new[] { "I1" }) }); var actual = Program.MergeWindowsZones(originalZones, overrideZones); var expected = new WindowsZones("override-version", "orig-tzdb-version", "orig-win-version", new[] { new MapZone("ID1", "001", new[] { "A1" }), new MapZone("ID1", "T1-2", new[] { "D" }), new MapZone("ID1", "T1-3", new[] { "B1", "C1", "G1" }), new MapZone("ID2", "001", new[] { "E" }), new MapZone("ID2", "T2-1", new[] { "H1" }), new MapZone("ID3", "001", new[] { "I1" }) }); // Could implement IEquatable<WindowsZones>, but it doesn't seem worth it right now. Assert.AreEqual(expected.Version, actual.Version); Assert.AreEqual(expected.TzdbVersion, actual.TzdbVersion); Assert.AreEqual(expected.WindowsVersion, actual.WindowsVersion); Assert.AreEqual(expected.MapZones, actual.MapZones); }
private TzdbStreamData(Builder builder) { stringPool = CheckNotNull(builder.stringPool, "string pool"); tzdbIdMap = CheckNotNull(builder.tzdbIdMap, "TZDB alias map"); tzdbVersion = CheckNotNull(builder.tzdbVersion, "TZDB version"); windowsMapping = CheckNotNull(builder.windowsMapping, "CLDR Supplemental Windows Zones"); zoneFields = builder.zoneFields; zoneLocations = builder.zoneLocations; // Add in the canonical IDs as mappings to themselves. foreach (var id in zoneFields.Keys) { tzdbIdMap[id] = id; } windowsAdditionalStandardNameToIdMapping = CheckNotNull(builder.windowsAdditionalStandardNameToIdMapping, "Windows additional standard name to ID mapping"); }
public void ReadWrite() { var zones = new WindowsZones("version", "tzdbVersion", "windowsVersion", new[] { MapZone1, MapZone2, MapZone3 }); var stream = new MemoryStream(); var writer = new DateTimeZoneWriter(stream, null); zones.Write(writer); stream.Position = 0; var reader = new DateTimeZoneReader(stream, null); var zones2 = WindowsZones.Read(reader); Assert.AreEqual("version", zones2.Version); Assert.AreEqual("tzdbVersion", zones2.TzdbVersion); Assert.AreEqual("windowsVersion", zones2.WindowsVersion); Assert.AreEqual("primaryId2", zones2.PrimaryMapping["windowsId2"]); Assert.AreEqual("primaryId3", zones2.PrimaryMapping["windowsId3"]); Assert.AreEqual(new[] { MapZone1, MapZone2, MapZone3 }, zones2.MapZones); }
internal void HandleSupplementalWindowsZonesField(TzdbStreamField field) { CheckSingleField(field, windowsMapping); windowsMapping = field.ExtractSingleValue(WindowsZones.Read, stringPool); }
public void Write(TzdbDatabase database, WindowsZones cldrWindowsZones) { FieldCollection fields = new FieldCollection(); var zones = database.GenerateDateTimeZones().ToList(); var stringPool = CreateOptimizedStringPool(zones, database.ZoneLocations, cldrWindowsZones); // First assemble the fields (writing to the string pool as we go) foreach (var zone in zones) { var zoneField = fields.AddField(TzdbStreamFieldId.TimeZone, stringPool); WriteZone(zone, zoneField.Writer); } fields.AddField(TzdbStreamFieldId.TzdbVersion, null).Writer.WriteString(database.Version); // Normalize the aliases var timeZoneMap = new Dictionary <string, string>(); foreach (var key in database.Aliases.Keys) { var value = database.Aliases[key]; while (database.Aliases.ContainsKey(value)) { value = database.Aliases[value]; } timeZoneMap.Add(key, value); } fields.AddField(TzdbStreamFieldId.TzdbIdMap, stringPool).Writer.WriteDictionary(timeZoneMap); // Windows mappings cldrWindowsZones.Write(fields.AddField(TzdbStreamFieldId.CldrSupplementalWindowsZones, stringPool).Writer); fields.AddField(TzdbStreamFieldId.WindowsAdditionalStandardNameToIdMapping, stringPool).Writer.WriteDictionary (PclSupport.StandardNameToIdMap.ToDictionary(pair => pair.Key, pair => cldrWindowsZones.PrimaryMapping[pair.Value])); // Zone locations, if any. var zoneLocations = database.ZoneLocations; if (zoneLocations != null) { var field = fields.AddField(TzdbStreamFieldId.ZoneLocations, stringPool); field.Writer.WriteCount(zoneLocations.Count); foreach (var zoneLocation in zoneLocations) { zoneLocation.Write(field.Writer); } } var stringPoolField = fields.AddField(TzdbStreamFieldId.StringPool, null); stringPoolField.Writer.WriteCount(stringPool.Count); foreach (string value in stringPool) { stringPoolField.Writer.WriteString(value); } // Now write all the fields out, in the right order. new BinaryWriter(stream).Write(Version); fields.WriteTo(stream); stream.Close(); }