【问题标题】:Convert relative datetime string into DateTime object将相对日期时间字符串转换为 DateTime 对象
【发布时间】:2012-08-13 17:38:49
【问题描述】:

我有相对的datetime 字符串,例如:

  • “5 分钟前”
  • “10 小时前”
  • “3 天前”等

如何将其转换为精确的 datetime,与 this question 完全相反

【问题讨论】:

标签: c# datetime datetime-format


【解决方案1】:

这段代码应该可以工作:

        string input = "10 days ago";

        DateTime result = DateTime.MinValue;
        int minutesMultiplier = 0;

        if (input.Contains("minute"))
            minutesMultiplier = 1;
        else
            if (input.Contains("hour"))
                minutesMultiplier = 60;
            else
                if (input.Contains("day"))
                    minutesMultiplier = 1440;
                else
                    throw new Exception("Couldn't parse time format");

        string numberStr = input.Split(' ')[0];
        int number;
        if (int.TryParse(numberStr, out number))
            result = DateTime.Now.AddMinutes(-number * minutesMultiplier);

它解析一个间隔名称(例如分钟,小时,天)并将它们相乘以获得分钟数,因为稍后它使用DateTime.Now.AddMinutes方法,同样的事情可以使用TimeSpan并调用DateTime.Now.Add.

这里还有一个示例,它处理包含多个间隔名称的字符串的大小写,例如“10 小时 15 分钟前”:

        // If there are mixed interval types in an input string
        string input = "10 days and 10 hours ago";

        // Parse out the intervals and numbers
        var matches = Regex.Matches(input, 
                       @"(?<number>\d+)\s(?<interval>(day)|(minute)|(hour))");

        // Convert them to dictionary
        var dic = matches
            .Cast<Match>()
            .ToDictionary(
                key => key.Groups["interval"].Value, 
                o => int.Parse(o.Groups["number"].Value));

        // Calculate the total number of minutes for each interval
        DateTime result = DateTime.MinValue;
        int totalMinutes = 0;

        foreach (var keyValue in dic)
        {
             if (keyValue.Key.Contains("minute"))
                 totalMinutes += keyValue.Value;
            else
                 if (keyValue.Key.Contains("hour"))
                    totalMinutes += keyValue.Value * 60;
                else
                     if (keyValue.Key.Contains("day"))
                        totalMinutes += keyValue.Value * 1440;
                    else
                        throw new Exception("Unparsable time format");
        }

        result = DateTime.Now.AddMinutes(-totalMinutes);

【讨论】:

  • 请注意,此代码依赖于格式正确的输入字符串。
  • 是的,假设输入是可预测的并且可能自动生成。
  • string input = "10 hours and 30 minutes ago"; -- 你的代码是做什么的?我知道您无法预见所有可能的输入,但是当输入不是您期望的格式时,您应该抛出异常,而不是默默地做错事。
  • 我假设在单个字符串中只能提到一个间隔,因为 OP 从未说过可能有多个。我添加了抛出异常,尽管很明显这不会处理字符串中超过一个间隔的情况。如果可以有多个,则必须以不同的方式进行解析。
  • 你的异常不会被输入抛出,因为input.Contains("minute") 是真的,所以它减去了 10 分钟。根据问题中的输入,我可能会将input.Split(' ') 存储在一个变量中,检查它的长度是否正好为3,并检查words[1] 是否正好是“分钟”(或“小时”、“天”等)否则你想添加),而words[2] 正是“以前”。
【解决方案2】:

您需要编写自己的例程来这样做,就像做相反的人必须做的那样。

基本上,您将需要解析文本以查找时间间隔(即分钟、小时、天等...)、数量以及它是过去还是将来(使用agofrom) .

此时,您将有足够的数据来构造一个合适的TimeSpan 实例并将其与DateTime.Now 一起使用以获得该时间。

为了使上述工作正常进行,您需要确保要解析的字符串值是标准化的。

【讨论】:

    【解决方案3】:

    正确的方法是将您的相对值存储为 TimeSpan 值,然后从 DateTime.Now(或您想用作基础的任何 DateTime 中减去)。

    您可以使用int.Parse 等方法将数字(分钟数、小时数等)转换为整数值,并将其复制到您的TimeSpan 值中。确切的解析算法取决于字符串的实际格式,即其中允许使用哪些单词,以及数字可能出现的顺序。

    如果字符串已经被隔离,如您的问题所示,您可以尝试使用正则表达式(使用Regex class)反汇编它们:

    ^(\d+)\s+([a-z]+)\s+ago$
    

    【讨论】:

      猜你喜欢
      • 2014-12-13
      • 2018-08-29
      • 1970-01-01
      • 2012-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多