Created
January 12, 2021 18:34
-
-
Save ArtemAvramenko/b703c3ea75b4866dddf317ed820a30fa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Xml; | |
namespace tztest | |
{ | |
class Program | |
{ | |
private static XmlDocument LoadCldrXml(string path) | |
{ | |
var xmlDoc = new XmlDocument(); | |
xmlDoc.Load($"/home/username/Desktop/tztest/cldr" + path); | |
return xmlDoc; | |
} | |
private static Dictionary<string, string> WinToIANA( | |
Dictionary<string, TimeZoneInfo> zoneById, | |
Dictionary<string, string[]> zoneToAlias) | |
{ | |
var xmlDoc = LoadCldrXml("/supplemental/windowsZones.xml"); | |
var zoneList = xmlDoc.SelectNodes("//supplementalData/windowsZones/mapTimezones/mapZone"); | |
var winToIana = new Dictionary<string, string>(); | |
foreach (XmlNode node in zoneList) | |
{ | |
var winId = node.Attributes["other"].Value; | |
var ianaId = node.Attributes["type"].Value; | |
if (!winToIana.TryGetValue(winId, out var prevIanaName) || prevIanaName.StartsWith("Etc/")) | |
{ | |
if (!zoneById.ContainsKey(ianaId)) | |
{ | |
ianaId = zoneToAlias[ianaId].FirstOrDefault(_ => zoneById.ContainsKey(_)) ?? ianaId; | |
} | |
winToIana[winId] = ianaId; | |
} | |
} | |
winToIana["UTC"] = "UTC"; | |
return winToIana; | |
} | |
private static Dictionary<string, string> ReadZoneNames(string culture) | |
{ | |
var xmlDoc = LoadCldrXml($"/main/{culture}.xml"); | |
var zoneToName = new Dictionary<string, string>(); | |
var itemNodes = xmlDoc.SelectNodes("//ldml/dates/timeZoneNames/zone/exemplarCity"); | |
foreach (XmlNode item in itemNodes) | |
{ | |
var zoneId = item.ParentNode.Attributes["type"].Value; | |
var zoneName = item.InnerText; | |
zoneToName[zoneId] = zoneName; | |
} | |
var utcNode = xmlDoc.SelectSingleNode("//ldml/dates/timeZoneNames/zone[@type='Etc/UTC']/long/standard"); | |
zoneToName["UTC"] = utcNode.InnerText; | |
zoneToName["Etc/GMT+12"] = "Линия перемены дат"; // International Date Line, Линия перемены дат, Die Datumsgrenze | |
return zoneToName; | |
} | |
private static Dictionary<string, string[]> ReadZoneAliases() | |
{ | |
var xmlDoc = LoadCldrXml("/bcp47/timezone.xml"); | |
var zoneToAlias = new Dictionary<string, string[]>(); | |
var itemNodes = xmlDoc.SelectNodes("//ldmlBCP47/keyword/key/type"); | |
foreach (XmlNode item in itemNodes) | |
{ | |
var aliases = item.Attributes["alias"]?.Value?.Split(' '); | |
if (aliases != null) | |
{ | |
foreach (var alias in aliases) | |
{ | |
zoneToAlias[alias] = aliases.Where(_ => _ != alias).ToArray(); | |
} | |
} | |
} | |
return zoneToAlias; | |
} | |
static void Main(string[] args) | |
{ | |
var culture = "ru"; | |
var zoneToName = ReadZoneNames(culture); | |
var zoneToAlias = ReadZoneAliases(); | |
var systemZones = new[] { TimeZoneInfo.FindSystemTimeZoneById("Etc/GMT+12") } | |
.Union(TimeZoneInfo.GetSystemTimeZones()) | |
.ToDictionary(_ => _.Id); | |
foreach (var z in systemZones.Values) | |
{ | |
if (!zoneToName.TryGetValue(z.Id, out var name)) | |
{ | |
if (zoneToAlias.TryGetValue(z.Id, out var aliases)) | |
{ | |
foreach (var aliasId in aliases) | |
{ | |
if (zoneToName.TryGetValue(aliasId, out name)) | |
{ | |
break; | |
} | |
} | |
} | |
if (name == null) | |
{ | |
name = z.Id.Split('/').Last().Replace('_', ' '); | |
} | |
} | |
if (z.Id == "UTC") | |
{ | |
Console.WriteLine($"(UTC) {name}"); | |
} | |
else | |
{ | |
var sign = '-'; | |
var offset = z.BaseUtcOffset; | |
if (offset >= TimeSpan.Zero) | |
{ | |
sign = '+'; | |
} | |
else | |
{ | |
offset = -offset; | |
} | |
var hours = offset.Hours.ToString("00"); | |
var minutes = offset.Minutes.ToString("00"); | |
Console.WriteLine($"{z.Id} - (UTC{sign}{hours}:{minutes}) {name}"); | |
} | |
} | |
Console.WriteLine("================================"); | |
var winToIana = WinToIANA(systemZones, zoneToAlias); | |
foreach (var z in winToIana.Values.Where(_ => !systemZones.ContainsKey(_))) | |
{ | |
Console.WriteLine(z); | |
} | |
foreach (var pair in winToIana) | |
{ | |
Console.WriteLine($"WHEN '{pair.Key}' THEN '{pair.Value}'"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment