- JobScheduler: a stored job whose zone lookup throws no longer fails StartAsync; timer re-armed under the lock; a delivery cut off by shutdown isn't recorded (one-offs fire again after restart); CancelJobAsync in one step - Schedules.ParseAt: ISO 8601 with a date only (no machine-clock date for a bare 09:00) - core: a FollowUp prompt that loses the race to a starting run joins it as a follow-up, not steering - Telegram: TimeZoneFor tolerates non-numeric targets; RunPromptAsync waits only when queued; one agent dir - ScriptRunner: bad workspace paths are Failed, not exceptions; zone id helpers share TimeZoneIds.ToIana's rule - tests: no wall-clock sleeps in scheduler tests; transcript-entry, disabled-scheduler and failing-prompt coverage - docs: spec notes for the above; README row for the scheduler
23 lines
1.1 KiB
C#
23 lines
1.1 KiB
C#
namespace Volcanic.AgenticCore.Extensions.Scheduler;
|
|
|
|
/// <summary>
|
|
/// Zone ids for display and <c>TZ</c>. Mirrors the core's <c>Volcanic.AgenticCore.Hosting.TimeZoneIds</c> (the extension
|
|
/// references only the Abstractions); keep the two in step.
|
|
/// </summary>
|
|
internal static class ZoneNames
|
|
{
|
|
/// <summary>
|
|
/// The IANA id (converting a Windows id), or null when there is none that resolves back to a system zone (an unnamed
|
|
/// <c>Local</c> zone: <c>TZ=Local</c> would run the script in UTC). Same rule as <c>TimeZoneIds.ToIana</c>.
|
|
/// </summary>
|
|
public static string? Iana(TimeZoneInfo zone)
|
|
{
|
|
if (string.Equals(zone.Id, "Local", StringComparison.OrdinalIgnoreCase)) return null;
|
|
var id = zone.HasIanaId ? zone.Id : TimeZoneInfo.TryConvertWindowsIdToIanaId(zone.Id, out var iana) ? iana : null;
|
|
return id is not null && TimeZoneInfo.TryFindSystemTimeZoneById(id, out _) ? id : null;
|
|
}
|
|
|
|
/// <summary>The IANA id when there is one, else the zone's own id (<c>TimeZoneIds.Name</c>).</summary>
|
|
public static string Name(TimeZoneInfo zone) => Iana(zone) ?? zone.Id;
|
|
}
|