mirror of
https://github.com/RPCS3/discord-bot.git
synced 2026-01-31 01:25:22 +01:00
106 lines
4.2 KiB
C#
106 lines
4.2 KiB
C#
namespace CompatBot.Utils;
|
|
|
|
public static class TimeParser
|
|
{
|
|
public static readonly Dictionary<string, TimeZoneInfo> TimeZoneMap;
|
|
|
|
public static readonly Dictionary<string, string[]> TimeZoneAcronyms = new()
|
|
{
|
|
["PT"] = ["Pacific Standard Time", "America/Los_Angeles"],
|
|
["PST"] = ["Pacific Standard Time", "America/Los_Angeles"],
|
|
["PDT"] = ["Pacific Standard Time", "Pacific Daylight Time", "America/Los_Angeles"],
|
|
["EST"] = ["Eastern Standard Time", "America/New_York"],
|
|
["EDT"] = ["Eastern Standard Time", "Eastern Daylight Time", "America/New_York"],
|
|
["CEST"] = ["Central European Standard Time", "Europe/Berlin"],
|
|
["BST"] = ["British Summer Time", "GMT Standard Time", "Europe/London"],
|
|
["JST"] = ["Japan Standard Time", "Tokyo Standard Time", "Asia/Tokyo"],
|
|
};
|
|
|
|
static TimeParser()
|
|
{
|
|
var uniqueNames = new HashSet<string>(
|
|
from tznl in TimeZoneAcronyms.Values
|
|
from tzn in tznl
|
|
select tzn,
|
|
StringComparer.InvariantCultureIgnoreCase
|
|
);
|
|
Config.Log.Trace("[TZI] Unique TZA names: " + uniqueNames.Count);
|
|
var tzList = TimeZoneInfo.GetSystemTimeZones();
|
|
Config.Log.Trace("[TZI] System TZI count: " + tzList.Count);
|
|
var result = new Dictionary<string, TimeZoneInfo>();
|
|
var standardNames = new Dictionary<string, TimeZoneInfo>();
|
|
var daylightNames = new Dictionary<string, TimeZoneInfo>();
|
|
foreach (var tzi in tzList)
|
|
{
|
|
Config.Log.Trace($"[TZI] Checking {tzi.Id} ({tzi.DisplayName} / {tzi.StandardName} / {tzi.DaylightName})");
|
|
if (uniqueNames.Contains(tzi.StandardName) || uniqueNames.Contains(tzi.DaylightName) || uniqueNames.Contains(tzi.Id))
|
|
{
|
|
Config.Log.Trace("[TZI] Looks like it's a match!");
|
|
var acronyms = (
|
|
from tza in TimeZoneAcronyms
|
|
where tza.Value.Contains(tzi.StandardName) || tza.Value.Contains(tzi.DaylightName) || tza.Value.Contains(tzi.Id)
|
|
select tza.Key
|
|
).ToList();
|
|
Config.Log.Trace("[TZI] Matched acronyms: " + string.Join(", ", acronyms));
|
|
foreach (var tza in acronyms)
|
|
result[tza] = tzi;
|
|
}
|
|
else
|
|
{
|
|
var a = tzi.StandardName.GetAcronym(includeAllCaps: true, includeAllDigits: true);
|
|
if (TimeZoneAcronyms.ContainsKey(a))
|
|
continue;
|
|
|
|
standardNames.TryAdd(a, tzi);
|
|
a = tzi.DaylightName.GetAcronym(includeAllCaps: true, includeAllDigits: true);
|
|
if (TimeZoneAcronyms.ContainsKey(a) || standardNames.ContainsKey(a))
|
|
continue;
|
|
|
|
daylightNames.TryAdd(a, tzi);
|
|
}
|
|
}
|
|
Config.Log.Trace("[TZI] Total matched acronyms: " + result.Count);
|
|
TimeZoneMap = result.Concat(standardNames).Concat(daylightNames)
|
|
.DistinctBy(kvp => kvp.Key)
|
|
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
|
}
|
|
|
|
public static bool TryParse(string dateTime, out DateTime result)
|
|
{
|
|
result = default;
|
|
if (string.IsNullOrEmpty(dateTime))
|
|
return false;
|
|
|
|
dateTime = dateTime.ToUpperInvariant();
|
|
if (char.IsDigit(dateTime[^1]))
|
|
return DateTime.TryParse(dateTime, out result);
|
|
|
|
var cutIdx = dateTime.LastIndexOf(' ');
|
|
if (cutIdx < 0)
|
|
return false;
|
|
|
|
var tza = dateTime[(cutIdx+1)..];
|
|
dateTime = dateTime[..cutIdx];
|
|
if (TimeZoneMap.TryGetValue(tza, out var tzi))
|
|
{
|
|
if (!DateTime.TryParse(dateTime, out result))
|
|
return false;
|
|
|
|
result = TimeZoneInfo.ConvertTimeToUtc(result, tzi);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
public static DateTime Normalize(this DateTime date) =>
|
|
date.Kind switch
|
|
{
|
|
DateTimeKind.Utc => date,
|
|
DateTimeKind.Local => date.ToUniversalTime(),
|
|
_ => date.AsUtc(),
|
|
};
|
|
|
|
public static List<string> GetSupportedTimeZoneAbbreviations() => TimeZoneMap.Keys.ToList();
|
|
} |