using System.Globalization; using System.Text.RegularExpressions; namespace Admin.NET.Plugin.AiDOP.DataPlatform.Executors; /// /// P-015:解析调度同步窗口(FULL / INCR / ROLLING),供抽数 SQL 使用。 /// public static class MdpSyncWindowResolver { private static readonly Regex DurationRegex = new( @"^\s*(?\d+)\s*(?[dDhHmM])\s*$", RegexOptions.Compiled); /// /// 将窗口类型落到上下文:FULL→全量;INCR→水位;ROLLING→下界时间。 /// 显式 FullRefresh 时强制 FULL。 /// public static void Apply(MdpPullContext ctx) { if (ctx.FullRefresh) { ctx.SyncWindowType = "FULL"; ctx.WindowFrom = null; return; } var type = (ctx.SyncWindowType ?? "INCR").Trim().ToUpperInvariant(); if (type is "ROLLING_WINDOW") type = "ROLLING"; switch (type) { case "FULL": ctx.SyncWindowType = "FULL"; ctx.FullRefresh = true; ctx.WindowFrom = null; break; case "ROLLING": ctx.SyncWindowType = "ROLLING"; ctx.WindowFrom = ResolveWindowFrom(ctx.SyncWindowValue, DateTime.Now) ?? DateTime.Now.AddDays(-7); break; default: // INCR / 其它:走 last_cursor ctx.SyncWindowType = "INCR"; ctx.WindowFrom = null; break; } } /// /// 解析窗口参数:支持 7d/24h/30m 或绝对时间 yyyy-MM-dd[ HH:mm:ss]。 /// public static DateTime? ResolveWindowFrom(string? value, DateTime now) { if (string.IsNullOrWhiteSpace(value)) return null; var raw = value.Trim(); var m = DurationRegex.Match(raw); if (m.Success) { var n = int.Parse(m.Groups["n"].Value, CultureInfo.InvariantCulture); return m.Groups["u"].Value.ToUpperInvariant() switch { "D" => now.AddDays(-n), "H" => now.AddHours(-n), "M" => now.AddMinutes(-n), _ => null }; } if (DateTime.TryParse(raw, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var abs) || DateTime.TryParse(raw, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out abs)) return abs; return null; } }