Skip to content

Commit

Permalink
[feat]新增时间表达式TimeExpression,一次解析多次使用,支持${dt+1M+4d:yy-MM-dd}
Browse files Browse the repository at this point in the history
  • Loading branch information
nnhy committed Aug 6, 2024
1 parent 6225663 commit 7bd9536
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 21 deletions.
2 changes: 1 addition & 1 deletion AntJob.Agent/AntJob.Agent.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NewLife.Stardust" Version="3.0.2024.802" />
<PackageReference Include="NewLife.Stardust" Version="3.0.2024.806" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion AntJob.Data/AntJob.Data.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<None Remove="Build.tt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NewLife.XCode" Version="11.15.2024.801" />
<PackageReference Include="NewLife.XCode" Version="11.15.2024.806" />
</ItemGroup>
<ItemGroup>
<None Update="Build.log">
Expand Down
2 changes: 1 addition & 1 deletion AntJob.Extensions/AntJob.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NewLife.XCode" Version="11.15.2024.801" />
<PackageReference Include="NewLife.XCode" Version="11.15.2024.806" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AntJob\AntJob.csproj" />
Expand Down
2 changes: 1 addition & 1 deletion AntJob.Web/AntJob.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="NewLife.Cube.Core" Version="6.1.2024.728-beta1411" />
<PackageReference Include="NewLife.Stardust.Extensions" Version="3.0.2024.802" />
<PackageReference Include="NewLife.Stardust.Extensions" Version="3.0.2024.806" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AntJob.Data\AntJob.Data.csproj" />
Expand Down
6 changes: 3 additions & 3 deletions AntJob/AntJob.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NewLife.Core" Version="10.10.2024.801" />
<PackageReference Include="NewLife.Remoting" Version="3.0.2024.801" />
<PackageReference Include="NewLife.Stardust" Version="3.0.2024.802" />
<PackageReference Include="NewLife.Core" Version="10.10.2024.803" />
<PackageReference Include="NewLife.Remoting" Version="3.0.2024.805" />
<PackageReference Include="NewLife.Stardust" Version="3.0.2024.806" />
</ItemGroup>

<ItemGroup>
Expand Down
36 changes: 23 additions & 13 deletions AntJob/Data/TemplateHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ public static String Build(String template, DateTime startTime, DateTime endTime
while (true)
{
var ti = Find(str, "DataTime", p);
ti ??= Find(str, "dt", p);
if (ti == null)
if (ti.IsEmpty) ti = Find(str, "dt", p);
if (ti.IsEmpty)
{
sb.Append(str.Substring(p));
break;
}

// 准备替换
var val = ti.Item3.IsNullOrEmpty() ? startTime.ToFullString() : startTime.ToString(ti.Item3);
sb.Append(str.Substring(p, ti.Item1 - p));
var val = ti.Format.IsNullOrEmpty() ? startTime.ToFullString() : startTime.ToString(ti.Format);
sb.Append(str.Substring(p, ti.Start - p));
sb.Append(val);

// 移动指针
p = ti.Item2 + 1;
p = ti.End + 1;
}

str = sb.ToString();
Expand All @@ -43,40 +43,50 @@ public static String Build(String template, DateTime startTime, DateTime endTime
while (true)
{
var ti = Find(str, "End", p);
if (ti == null)
if (ti.IsEmpty)
{
sb.Append(str.Substring(p));
break;
}

// 准备替换
var val = ti.Item3.IsNullOrEmpty() ? endTime.ToFullString() : endTime.ToString(ti.Item3);
sb.Append(str.Substring(p, ti.Item1 - p));
var val = ti.Format.IsNullOrEmpty() ? endTime.ToFullString() : endTime.ToString(ti.Format);
sb.Append(str.Substring(p, ti.Start - p));
sb.Append(val);

// 移动指针
p = ti.Item2 + 1;
p = ti.End + 1;
}

return sb.Put(true);
}

private static Tuple<Int32, Int32, String> Find(String str, String key, Int32 p)
private static VarItem Find(String str, String key, Int32 p)
{
// 头尾
var p1 = str.IndexOf("{" + key, p);
if (p1 < 0) return null;
if (p1 < 0) return _empty;

var p2 = str.IndexOf("}", p1);
if (p2 < 0) return null;
if (p2 < 0) return _empty;

// 格式化字符串
var format = "";
var p3 = str.IndexOf(":", p1);
if (p3 > 0 && p3 < p2) format = str.Substring(p3 + 1, p2 - p3 - 1);

// 左括号位置,右括号位置,格式化字符串
return new Tuple<Int32, Int32, String>(p1, p2, format);
return new VarItem(p1, p2, format);
}

private static VarItem _empty = new(-1, -1, "");
struct VarItem(Int32 start, Int32 end, String format)
{
public Int32 Start = start;
public Int32 End = end;
public String Format = format;

public readonly Boolean IsEmpty => Start < 0;
}

/// <summary>使用消息数组处理模板</summary>
Expand Down
170 changes: 170 additions & 0 deletions AntJob/Data/TimeExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
using NewLife;

namespace AntJob.Data;

/// <summary>时间表达式,一次解析多次使用。如{dt+1M+5d:yyyyMMdd}</summary>
public class TimeExpression
{
#region 属性
/// <summary>表达式</summary>
public String Expression { get; set; }

/// <summary>变量名</summary>
public String VarName { get; set; } = "dt";

/// <summary>格式化字符串</summary>
public String Format { get; set; }

/// <summary>时间表达式项集合</summary>
public IList<TimeExpressionItem> Items { get; } = [];
#endregion

#region 构造
/// <summary>实例化时间表达式</summary>
public TimeExpression() { }

/// <summary>实例化时间表达式</summary>
public TimeExpression(String expression) => Parse(expression);
#endregion

#region 方法
/// <summary>解析表达式</summary>
public Boolean Parse(String expression)
{
var p1 = expression.IndexOf('{');
if (p1 < 0) return false;

var p2 = expression.IndexOf('}', p1);
if (p2 < 0) return false;

expression = expression.Substring(p1 + 1, p2 - p1 - 1);

// 循环查找
var ms = Items;
p1 = -1;
while (true)
{
p2 = expression.IndexOfAny(['+', '-', ':', ','], p1 + 1);
if (p2 < 0) p2 = expression.Length;

// 第一段是变量名
if (p1 < 0 && p2 > 0)
{
VarName = expression[0..p2];
}
else if (expression[p1] is '+' or '-')
{
var str = expression[p1..p2];
var item = new TimeExpressionItem();
if (!item.Parse(str)) throw new InvalidDataException($"Invalid [{str}]");

ms.Add(item);
}
else if (expression[p1] is ':' or ',')
{
// 最后一段是格式化字符串
p2 = expression.Length;
Format = expression[(p1 + 1)..p2];
}

if (p2 >= expression.Length) break;
p1 = p2;
}

// 默认天级
if (ms.Count == 0) ms.Add(new TimeExpressionItem { Level = "d", Value = 0 });

Expression = expression;

return true;
}

/// <summary>执行时间偏移</summary>
public DateTime Execute(DateTime time)
{
foreach (var item in Items)
{
time = item.Execute(time);
}

return time;
}

/// <summary>构建时间字符串</summary>
public String Build(DateTime time)
{
time = Execute(time);

var ms = Items;
var format = Format;
if (format.IsNullOrEmpty() && ms.Count > 0) format = ms[ms.Count - 1].GetFormat();
if (format.IsNullOrEmpty()) format = "yyyyMMdd";

return time.ToString(format);
}
#endregion

/// <summary>处理时间偏移模版。如{dt+1M+5d:yyyyMMdd}</summary>
/// <param name="template"></param>
/// <param name="time"></param>
/// <returns></returns>
public static String Build(String template, DateTime time)
{
return null;
}
}

/// <summary>时间表达式项。如+5d</summary>
public class TimeExpressionItem
{
/// <summary>级别。如y/M/d/H/m/w</summary>
public String Level { get; set; }

/// <summary>数值。包括正负</summary>
public Int32 Value { get; set; }

/// <summary>分解表达式项。如+5d</summary>
/// <param name="value"></param>
/// <returns></returns>
public Boolean Parse(String value)
{
if (value.IsNullOrEmpty() || value.Length < 3) return false;

Level = value[^1..];
Value = value[..^1].ToInt();

return true;
}

/// <summary>执行时间偏移</summary>
public DateTime Execute(DateTime time)
{
return Level switch
{
"y" => new DateTime(time.Year, 1, 1, 0, 0, 0, time.Kind).AddYears(Value),
"M" => new DateTime(time.Year, time.Month, 1, 0, 0, 0, time.Kind).AddMonths(Value),
"d" => new DateTime(time.Year, time.Month, time.Day, 0, 0, 0, time.Kind).AddDays(Value),
"H" => new DateTime(time.Year, time.Month, time.Day, time.Hour, 0, 0, time.Kind).AddHours(Value),
"m" => new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0, time.Kind).AddMinutes(Value),
"s" => new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Kind).AddSeconds(Value),
"w" => new DateTime(time.Year, time.Month, time.Day, 0, 0, 0, time.Kind).AddDays(Value * 7),
_ => time,
};
}

/// <summary>获取格式化字符串</summary>
public String GetFormat()
{
return Level switch
{
"y" => "yyyy",
"M" => "yyyyMM",
"d" => "yyyyMMdd",
"H" => "yyyyMMddHH",
"m" => "yyyyMMddHHmm",
"s" => "yyyyMMddHHmmss",
"w" => "yyyyww",
_ => "",
};
}
}
Loading

0 comments on commit 7bd9536

Please sign in to comment.