[英]C# Invoking members from string expression e.g. “”DateTime.Today“”
[英]C# Parse Date Variables from String (e.g. %today-4days%, %now+15min%)
我有一个控制台应用程序,我经常需要将变量 DateTime 传递给它。 我目前正在使用开关在变量与确切的字符串匹配时返回值,并根据需要添加新的值。 我想对其进行设计,使其能够解析变量并根据字符串执行正确的操作。
以下是我目前使用的格式中的一些示例。
%today%
%today-5day%
%today-1sec%
%today+1month%
%now+15min%
%now-30sec%
%now+1week%
我也想解析变量,例如
%lastmonday%
%nextfriday%
%monthstart%
%yearend%
等等,但这些似乎最好在交换机中处理,如果不匹配则传递给 function 以解析和计算上面的示例。
我不确定实现这一目标的最优雅的方法,并且在我的搜索中找不到太多。
您可以尝试正则表达式以进行解析。 首先,让我们提取一个 model:因为命令是格式
Start (zero or more Modifiers)
例如
%today-5day+3hour%
today
是Start
, -5day
和+3hour
3hour 是Modifiers
,我们想要两个模型
using System.Linq;
using System.Text.RegularExpressions;
...
//TODO: add more starting points here
private static Dictionary<string, Func<DateTime>> s_Starts =
new Dictionary<string, Func<DateTime>>(StringComparer.OrdinalIgnoreCase) {
{ "now", () => DateTime.Now},
{ "today", () => DateTime.Today},
{ "yearend", () => new DateTime(DateTime.Today.Year, 12, 31) },
};
//TODO: add more modifiers here
private static Dictionary<string, Func<DateTime, int, DateTime>> s_Modifiers =
new Dictionary<string, Func<DateTime, int, DateTime>>(StringComparer.OrdinalIgnoreCase) {
{ "month", (source, x) => source.AddMonths(x)},
{ "week", (source, x) => source.AddDays(x * 7)},
{ "day", (source, x) => source.AddDays(x)},
{ "hour", (source, x) => source.AddHours(x)},
{ "min", (source, x) => source.AddMinutes(x)},
{ "sec", (source, x) => source.AddSeconds(x)},
};
有了 model (上面的两个字典),我们可以实现MyParse
例程:
private static DateTime MyParse(string value) {
if (null == value)
throw new ArgumentNullException(nameof(value));
var match = Regex.Match(value,
@"^%(?<start>[a-zA-Z]+)(?<modify>\s*[+-]\s*[0-9]+\s*[a-zA-Z]+)*%$");
if (!match.Success)
throw new FormatException("Invalid format");
string start = match.Groups["start"].Value;
DateTime result = s_Starts.TryGetValue(start, out var startFunc)
? startFunc()
: throw new FormatException($"Start Date(Time) {start} is unknown.");
var adds = Regex
.Matches(match.Groups["modify"].Value, @"([+\-])\s*([0-9]+)\s*([a-zA-Z]+)")
.Cast<Match>()
.Select(m => (kind : m.Groups[3].Value,
amount : int.Parse(m.Groups[1].Value + m.Groups[2].Value)));
foreach (var (kind, amount) in adds)
if (s_Modifiers.TryGetValue(kind, out var func))
result = func(result, amount);
else
throw new FormatException($"Modification {kind} is unknown.");
return result;
}
演示:
string[] tests = new string[] {
"%today%",
"%today-5day%",
"%today-1sec%",
"%today+1month%",
"%now+15min%",
"%now-30sec%",
"%now+1week%",
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test,-15} :: {MyParse(test):dd MM yyyy HH:mm:ss}")
);
Console.Write(report);
结果:
%today% :: 07 05 2020 00:00:00
%today-5day% :: 02 05 2020 00:00:00
%today-1sec% :: 06 05 2020 23:59:59
%today+1month% :: 07 06 2020 00:00:00
%now+15min% :: 07 05 2020 18:34:55
%now-30sec% :: 07 05 2020 18:19:25
%now+1week% :: 14 05 2020 18:19:55
这是一个解析包含今天和日期的字符串的小示例(使用 %today-5day% 的示例)。
注意:这仅在为添加的天数传入的值在 0-9 之间时才有效,要处理大量数字,您必须循环遍历字符串的结果。
您也可以按照此代码块解析其他结果。
switch (date)
{
case var a when a.Contains("day") && a.Contains("today"):
return DateTime.Today.AddDays(char.GetNumericValue(date[date.Length - 5]));
default:
return DateTime.Today;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.