关于datetime:.NET的自然语言日期/时间解析器?

关于datetime:.NET的自然语言日期/时间解析器?

Natural language date/time parser for .NET?

有谁知道一个类似于Ruby的Chronic的.NET日期/时间解析器(处理"明天"或"下周四3pm"之类的东西)?

注意:我确实写过Ruby(这是我对Chronic的了解),但是该项目必须使用.NET。


我们完全按照您在内部项目中寻找的内容进行开发。我们正在考虑是否有足够的必要将此公开。请查看此博客以获取更多详细信息:http://precisionsoftwaredesign.com/blog.php。

如果您有兴趣,请随时与我联系:contact@precisionsoftware.us

该库现在是SourceForge项目。该页面位于:

http://www.SourceForge.net/p/naturaldate

该程序集位于下载部分,Mercurial提供了源代码。


存在一个.NET的慢性端口。参见https://github.com/robertwilczynski/nChronic。我在其中创建了一个具有一些改进和错误修复的分支,网址为:https://github.com/dorony/nChronic(发送了请求请求,但作者仍未响应)。


我没有,但是有一个名为jchronic的Java端口。如果没有别的,它可以为您自己提供一个很好的起点。或者,您可以使用像Octopus这样的半自动Java到C#转换器来帮助翻译它。 (或者更好的东西,如果有人知道的话。)

好的,另一种可能的途径:您可以通过IronRuby使用长期代码吗?


@Blair Conrad-好主意!我试图让Chronic在IronRuby下运行,但是依赖项存在一些问题-我还不知道它已经准备好了。

我在Codeplex(DateTimeEnglishParser)上找到了一个试图做同样事情的项目。它还没有解决很多年或时间,但这是一个好的开始。我已经对该项目进行了一些工作,并贡献了一个补丁来更好地处理书面数字。

这是一个有趣的问题,并且绝对可以帮助我更好地理解正则表达式,因此我认为我将继续努力。


我检查了几个框架,Python的ParseDateTime效果最好。可以使用IronPython在.NET中使用它。

如果有人对完整的示例项目感兴趣,请对答案发表评论,我将尝试创建一个答案。

编辑

根据要求,这是一个可以与库一起使用的简单项目:

http://www.assembla.com/code/relativedateparser/subversion/nodes

请尝试以下使用案例,例如:

  • 2008年8月25日
  • 2008年8月25日
  • 8月25日下午5点
  • 8月25日下午5点
  • 下周六
  • 明天
  • 下周四下午4点
  • 在下午4点
  • 开除
  • 明天
  • 周二
  • oy
  • om
  • 5分钟内
  • 从现在起5分钟
  • 现在5小时前
  • 中午前2小时
  • 从明天起2天

Palmsey,我最近才有同样的要求,所以我继续写了一个简单的解析器。它不是最好的代码,但可以处理以下内容:

"今天下午2点"
"星期二下午2点-2010年7月15日上午2点"
"上一年的凌晨2点-汤姆莫罗14:30"
" 2010年7月18日下午2:45"

将其粘贴在Codeplex上,因为也许其他人会发现它有用。签出:http://timestamper.codeplex.com/


之前有一个类似的线程,它提供了一个指向CodeProject上的库的链接,该链接似乎可以满足您的要求:http://www.codeproject.com/KB/edit/dateparser.aspx,但不幸的是,该库似乎是用MFC,因此您必须使用它制作一个DLL,然后从.NET程序中调用它。


我不知道一个,但听起来像是一个很酷的问题,所以这是我的错(VB.NET):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Private Function ConvertDateTimeToStringRelativeToNow(ByVal d As DateTime) As String
    Dim diff As TimeSpan = DateTime.Now().Subtract(d)
    If diff.Duration.TotalMinutes < 1 Then Return"Now"

    Dim str As String
    If diff.Duration.TotalDays > 365 Then
        str = CInt(diff.Duration.TotalDays / 365).ToString() &" years"
    ElseIf diff.Duration.TotalDays > 30 Then
        str = CInt(diff.TotalDays / 30).ToString() &" months"
    ElseIf diff.Duration.TotalHours > 24 Then
        str = CInt(diff.Duration.TotalHours / 24) &" days"
    ElseIf diff.Duration.TotalMinutes > 60 Then
        str = CInt(diff.Duration.TotalMinutes / 60) &" minutes"
    Else
        str = CInt(diff.Duration.TotalMinutes).ToString() &" minutes"
    End If
    If str.StartsWith("1") Then str = str.SubString(0, str.Length - 1)
    If diff.TotalDays > 0 Then
        str &=" ago"
    Else
        str &=" from now"
    End If
    Return str
End Function

它确实不像已经存在的那样复杂,但是我猜它可以正常工作。可能是一个不错的扩展方法。


// @伯顿:我认为他的意思是相反的,至少从链接页面上的例子来看:

1
2
3
4
5
6
7
8
  Chronic.parse('tomorrow')
    #=> Mon Aug 28 12:00:00 PDT 2006

  Chronic.parse('monday', :context => :past)
    #=> Mon Aug 21 12:00:00 PDT 2006

  Chronic.parse('this tuesday 5:00')
    #=> Tue Aug 29 17:00:00 PDT 2006

我以为我也会刺中它,直到我意识到! (虽然很好的实现)


推荐阅读