mirror of
https://github.com/RPCS3/discord-bot.git
synced 2026-01-31 01:25:22 +01:00
implement proper time zone converter
This commit is contained in:
@@ -304,15 +304,13 @@ namespace CompatBot.Commands
|
||||
}
|
||||
else if (txt != null)
|
||||
{
|
||||
var newStartTime = FixTimeString(txt.Content);
|
||||
if (!DateTime.TryParse(newStartTime, out var newTime))
|
||||
if (!TimeParser.TryParse(txt.Content, out var newTime))
|
||||
{
|
||||
errorMsg = $"Couldn't parse `{newStartTime}` as a start date and time";
|
||||
errorMsg = $"Couldn't parse `{txt.Content}` as a start date and time";
|
||||
goto step1;
|
||||
}
|
||||
|
||||
var duration = evt.End - evt.Start;
|
||||
newTime = Normalize(newTime);
|
||||
evt.Start = newTime.Ticks;
|
||||
evt.End = evt.Start + duration;
|
||||
evt.Year = newTime.Year;
|
||||
@@ -487,25 +485,6 @@ namespace CompatBot.Commands
|
||||
return score > 0.5 ? name : eventName;
|
||||
}
|
||||
|
||||
private static string FixTimeString(string dateTime)
|
||||
{
|
||||
return dateTime.ToUpperInvariant()
|
||||
.Replace("PST", "-08:00")
|
||||
.Replace("EST", "-05:00")
|
||||
.Replace("BST", "-03:00")
|
||||
.Replace("JST", "+09:00")
|
||||
.Replace("AEST", "+10:00");
|
||||
}
|
||||
|
||||
private static DateTime Normalize(DateTime date)
|
||||
{
|
||||
if (date.Kind == DateTimeKind.Utc)
|
||||
return date;
|
||||
if (date.Kind == DateTimeKind.Local)
|
||||
return date.ToUniversalTime();
|
||||
return date.AsUtc();
|
||||
}
|
||||
|
||||
private static async Task<TimeSpan?> TryParseTimeSpanAsync(CommandContext ctx, string duration, bool react = true)
|
||||
{
|
||||
var d = Duration.Match(duration);
|
||||
|
||||
86
CompatBot/Utils/TimeParser.cs
Normal file
86
CompatBot/Utils/TimeParser.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Remotion.Linq.Clauses;
|
||||
|
||||
namespace CompatBot.Utils
|
||||
{
|
||||
public static class TimeParser
|
||||
{
|
||||
private static readonly Dictionary<string, TimeZoneInfo> TimeZoneMap;
|
||||
|
||||
static TimeParser()
|
||||
{
|
||||
var tzAcronyms = new Dictionary<string, string[]>
|
||||
{
|
||||
["PT"] = new[] { "Pacific Standard Time" },
|
||||
["PST"] = new[] { "Pacific Standard Time" },
|
||||
["PDT"] = new[] { "Pacific Standard Time" },
|
||||
["EST"] = new[] { "Eastern Standard Time" },
|
||||
["EDT"] = new[] { "Eastern Standard Time" },
|
||||
["CEST"] = new[] { "Central European Standard Time" },
|
||||
["BST"] = new[] { "British Summer Time", "GMT Standard Time" },
|
||||
["JST"] = new[] { "Japan Standard Time", "Tokyo Standard Time" },
|
||||
};
|
||||
var uniqueNames = new HashSet<string>(
|
||||
from tznl in tzAcronyms.Values
|
||||
from tzn in tznl
|
||||
select tzn
|
||||
);
|
||||
var tzList = TimeZoneInfo.GetSystemTimeZones();
|
||||
var result = new Dictionary<string, TimeZoneInfo>();
|
||||
foreach (var tzi in tzList)
|
||||
{
|
||||
if (uniqueNames.Contains(tzi.StandardName) || uniqueNames.Contains(tzi.StandardName))
|
||||
{
|
||||
var acronyms = from tza in tzAcronyms
|
||||
where tza.Value.Contains(tzi.StandardName) || tza.Value.Contains(tzi.DaylightName)
|
||||
select tza.Key;
|
||||
foreach (var tza in acronyms)
|
||||
result[tza] = tzi;
|
||||
}
|
||||
}
|
||||
TimeZoneMap = result;
|
||||
}
|
||||
|
||||
public static bool TryParse(string dateTime, out DateTime result)
|
||||
{
|
||||
result = default;
|
||||
if (string.IsNullOrEmpty(dateTime))
|
||||
return false;
|
||||
|
||||
dateTime = dateTime.ToUpperInvariant();
|
||||
if (char.IsDigit(dateTime[dateTime.Length - 1]))
|
||||
{
|
||||
return DateTime.TryParse(dateTime, out result);
|
||||
}
|
||||
|
||||
var cutIdx = dateTime.LastIndexOf(' ');
|
||||
if (cutIdx < 0)
|
||||
return false;
|
||||
|
||||
var tza = dateTime.Substring(cutIdx + 1);
|
||||
dateTime = dateTime.Substring(0, 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)
|
||||
{
|
||||
if (date.Kind == DateTimeKind.Utc)
|
||||
return date;
|
||||
if (date.Kind == DateTimeKind.Local)
|
||||
return date.ToUniversalTime();
|
||||
return date.AsUtc();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Tests/TimeParserTests.cs
Normal file
20
Tests/TimeParserTests.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using CompatBot.Utils;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TimeParserTests
|
||||
{
|
||||
[TestCase("2019-8-19 6:00 PT", "2019-08-19 13:00")]
|
||||
[TestCase("2019-8-19 17:00 bst", "2019-08-19 16:00")]
|
||||
public void TimeZoneConverterTest(string input, string utcInput)
|
||||
{
|
||||
var utc = DateTime.Parse(utcInput).Normalize();
|
||||
Assert.That(TimeParser.TryParse(input, out var result), Is.True);
|
||||
Assert.That(result, Is.EqualTo(utc));
|
||||
Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user