10

我在使用时遇到问题DateTime.Parse

我正在处理各种格式的日期,其中一些是格式January 11th等等February 22nd

DateTime.Parse尝试解析这些日期时抛出异常。

我想知道 DateTime 中是否有我缺少的内置功能,例如我可以设置的标志,它会使 Parse 以更可接受的方式运行。

我知道这可以用一个相对简单的正则表达式来解决,而且我已经有一个模糊匹配我写的日期的类,但是我想知道是否有内置的方法来执行这种提取,因为它会从长远来看,比重新发明轮子更容易维护。

4

3 回答 3

18

.Net 框架中没有内置任何东西来解析January 11th or February 22nd等格式的日期。您必须删除后缀字符,然后才能使用 DateTime.TryParseExact.

对于后缀为st,的日期th,您可以使用string.Replace删除该部分,然后使用DateTime.TryParseExact。像。

string str = "1st February 2013";
DateTime dtObject;
string replacedStr =  str.Substring(0,4)
                         .Replace("nd","")
                         .Replace("th","")
                         .Replace("rd","")
                         .Replace("st","")
                         + str.Substring(4);


if (DateTime.TryParseExact(replacedStr, 
                            "dd MMMMM yyyy", 
                            CultureInfo.InstalledUICulture, 
                            DateTimeStyles.None, 
                            out dtObject))
{
 //valid date
}

对于多种格式,您可以在字符串数组中指定格式,稍后您可以使用它。它返回一个bool值,指示解析是否成功。

来自 MSDN 的示例:

string[] formats= {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                   "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                   "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                   "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                   "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
string[] dateStrings = {"5/1/2009 6:32 PM", "05/01/2009 6:32:05 PM", 
                        "5/1/2009 6:32:00", "05/01/2009 06:32", 
                        "05/01/2009 06:32:00 PM", "05/01/2009 06:32:00"}; 
DateTime dateValue;

foreach (string dateString in dateStrings)
{
   if (DateTime.TryParseExact(dateString, formats, 
                              new CultureInfo("en-US"), 
                              DateTimeStyles.None, 
                              out dateValue))
      Console.WriteLine("Converted '{0}' to {1}.", dateString, dateValue);
   else
      Console.WriteLine("Unable to convert '{0}' to a date.", dateString);
于 2013-01-29T12:49:02.373 回答
14

这是一个非常古老的问题,但是对于仍在研究复杂自然语言日期解析的任何人,我建议使用 nChronic,这是令人惊叹的(基于 ruby​​ 的)慢性日期解析器的 .NET 端口。

它的来源在这里: nChronic Github

它也在 Nuget 中作为慢性:Nuget 中的慢性

使用这个库的一些非常简单的示例代码如下所示:

using Chronic;
var parser = new Chronic.Parser ();
Span ParseObj;
DateTime ParsedDateTime;
ParseObj = parser.Parse ("January 11th");
ParsedDateTime = ParseObj.Start;

以下是它可以处理的一些示例:

简单的

  • 周四
  • 十一月
  • 夏天
  • 星期五
  • 13:00
  • 周一 2:35
  • 下午4点
  • 10到8
  • 10点2
  • 2点半
  • 早上 6 点
  • 周五下午 1 点
  • 晚上7点坐
  • 昨天
  • 今天
  • 明天
  • 上个星期
  • 下周
  • 本周二
  • 下个月
  • 去年冬天
  • 今天早上
  • 昨晚
  • 这一秒
  • 昨天 4:00
  • 上周五 20:00
  • 上周星期二
  • 明天下午 6:45
  • 下午
  • 昨天
  • 上周星期四

复杂的

  • 3年前
  • 一年前
  • 5个月前
  • 7 小时前
  • 从现在起 7 天
  • 1 周后
  • 3小时内
  • 1 年前 明天
  • 3 个月前 星期六 下午 5:00
  • 明天中午前 7 小时
  • 11 月的第三个星期三
  • 明年第三个月
  • 今年9月的第3个星期四
  • 上周第四天
  • 2010年6月14日晚上十一点
  • 97 年 5 月 7 日凌晨三点

具体日期

  • 1 月 5 日
  • 6月22日
  • 2017 年 5 月 5 日
  • 二月二十一日
  • 12月25日
  • 5月27日
  • 2006 年 10 月
  • 10 月 6 日
  • 2010 年 1 月 3 日
  • 2004 年 2 月 14 日
  • 2004 年 2 月 14 日
  • 2000 年 1 月 3 日
  • 85 年 4 月 17 日
  • 1979 年 5 月 27 日
  • 1979 年 5 月 27 日
  • 05/06
  • 1979-05-27
  • 星期五
  • 5
  • 4:00
  • 17:00
  • 0800

特定时间(上述许多时间都有附加时间)

  • 1 月 5 日晚上 7 点
  • 6月22日早上8点
  • 1979-05-27 05:00:00
  • 03/01/2012 07:25:09.234567

ETC

于 2014-08-31T02:16:17.570 回答
5

我有类似的问题,这里有更好的方法

  stringdate="August 19th 2000" 
  string pattern = @"\b(\d+)(?:st|nd|rd|th)\b";
  Regex rgx = new Regex(pattern);
  DateTime.Parse(String.Format("{0:MMMM,  d, yyyy}", rgx.Replace(stringdate, "$1"))  
  **result**    {19/08/2000 00:00:00}   System.DateTime

Microsoft正则表达式删除序数以及如何可视化各种 DateTime 格式的显示方式?

编辑

如果没有指定年份:

    stringdate= rgx.Replace(stringdate, "$1");
    DateTime datetime;
    if (!DateTime.TryParseExact(stringdate, "MMMM dd yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None, out datetime))
    {
     // assuming no gap exist
     datetime = DateTime.Parse(stringdate += " "+DateTime.Now.Year);
    }

现在,如果输入字符串 text 是"June 11th",它将是 11/6/2021

在DateTime 文档中有更多处理日期的函数和方法。

如果您根本不想要年份,则可以添加以下行:

datetime.ToString("MM/dd");

现在输出将是“11/6”

于 2017-01-04T04:19:08.240 回答