繁体   English   中英

C# 从字符串中解析日期变量(例如 %today-4days%、%now+15min%)

[英]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%

todayStart-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM