Cron: Bereich mit Schritt (7-22/3) lesen, ungueltige Ausdruecke im Scanner melden (#597)

Der Nachrichten-Digest im Dauerbetrieb der Test-VM lief nie: CronExpression
verstand 'von-bis/schritt' nicht, TaskSchedule verschluckte den Fehler.
Version 0.1.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-14 15:51:36 +02:00
co-authored by Claude Opus 5
parent 6581fd0187
commit 8ab9d99abe
6 changed files with 118 additions and 13 deletions
@@ -2,7 +2,7 @@ namespace ClawdDotNet.Core.Scheduling;
/// <summary>
/// Einfaches Cron-Parsing für 5-Felder-Ausdrücke: Minute Stunde Tag Monat Wochentag
/// Unterstützt: Zahlen, Wildcards (*), Bereiche (1-5), Listen (1,3,5), Schritte (*/5)
/// Unterstützt: Zahlen, Wildcards (*), Bereiche (1-5), Listen (1,3,5), Schritte (*/5, 7-22/3, 10/15)
/// </summary>
public sealed class CronExpression
{
@@ -103,21 +103,19 @@ public sealed class CronExpression
if (split.Length != 2)
throw Bad(field, "Schrittangabe erwartet die Form 'basis/schritt'");
var start = split[0] == "*" ? min : ParseNumber(field, split[0], min, max);
// Basis: "*" (ganzer Bereich), "a-b" (Bereich, #597) oder "a" (ab a bis Feldende).
// "0 7-22/3 * * *" fiel vorher durch, und der Scanner verschwieg es.
var (start, end) = split[0] == "*"
? (min, max)
: split[0].Contains('-')
? ParseRange(field, split[0], min, max)
: (ParseNumber(field, split[0], min, max), max);
var step = ParseNumber(field, split[1], 1, max); // Schritt 0 wäre eine Endlosschleife
for (var i = start; i <= max; i += step) result.Add(i);
for (var i = start; i <= end; i += step) result.Add(i);
}
else if (part.Contains('-'))
{
var split = part.Split('-');
if (split.Length != 2)
throw Bad(field, "Bereich erwartet die Form 'von-bis'");
var from = ParseNumber(field, split[0], min, max);
var to = ParseNumber(field, split[1], min, max);
if (from > to)
throw Bad(field, $"Bereich {from}-{to} ist rückwärts");
var (from, to) = ParseRange(field, part, min, max);
for (var i = from; i <= to; i++) result.Add(i);
}
else
@@ -129,6 +127,20 @@ public sealed class CronExpression
return result;
}
private static (int From, int To) ParseRange(string field, string value, int min, int max)
{
var split = value.Split('-');
if (split.Length != 2)
throw Bad(field, "Bereich erwartet die Form 'von-bis'");
var from = ParseNumber(field, split[0], min, max);
var to = ParseNumber(field, split[1], min, max);
if (from > to)
throw Bad(field, $"Bereich {from}-{to} ist rückwärts");
return (from, to);
}
private static int ParseNumber(string field, string value, int min, int max)
{
if (!int.TryParse(value, out var n))