feat: Adds scheduler with wallclock timer (#2163)

### Summary

* Adds an event scheduler.
* Adds conveniences for hourly, daily, weekly, biweekly, monthly, ordinal monthly, and yearly recurrences

Example:

```cs
var tz = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");

// Specify the time of the day, and the day of the week you want it to occur. Make sure it is translated into Utc.
// The next occurrence will be _after_ the specified date/time.
var scheduledEvent = EventScheduler.WeeklyAt(new DateTime(2025, 04, 26, 17, 00, 00), StartEvent, tz);

void StartEvent()
{
    World.Broadcast(0x30, false, "The event has started!");
}

Console.WriteLine("Event starts on {0}", scheduledEvent.NextOccurrence);
```

In this example, on _Saturday, May 3rd, 2025 @ 5pm ET_, the message "The event has started!" will be broadcasted.
This commit is contained in:
Kamron Batman 2025-04-26 22:27:08 -07:00 committed by GitHub
parent 4e25c74cdf
commit 78feea86b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 686 additions and 96 deletions

View file

@ -1468,4 +1468,21 @@ public static partial class Utility
table.Remove(key);
table.Add(key, value);
}
public static DateTime LocalToUtc(this DateTime local, TimeZoneInfo tz)
{
if (tz.IsInvalidTime(local))
{
// For hourly recurrence, just subtract the standard offset (simulate as if the time exists)
return DateTime.SpecifyKind(local - tz.BaseUtcOffset, DateTimeKind.Utc);
}
if (tz.IsAmbiguousTime(local))
{
var offsets = tz.GetAmbiguousTimeOffsets(local);
return DateTime.SpecifyKind(local - offsets[1], DateTimeKind.Utc);
}
return DateTime.SpecifyKind(local - tz.GetUtcOffset(local), DateTimeKind.Utc);
}
}