Skip to content

Instantly share code, notes, and snippets.

@ArtemAvramenko
Created January 12, 2021 18:34
Show Gist options
  • Save ArtemAvramenko/b703c3ea75b4866dddf317ed820a30fa to your computer and use it in GitHub Desktop.
Save ArtemAvramenko/b703c3ea75b4866dddf317ed820a30fa to your computer and use it in GitHub Desktop.
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