27

Does anyone know of a .NET date/time parser similar to Chronic for Ruby (handles stuff like "tomorrow" or "3pm next thursday")?

Note: I do write Ruby (which is how I know about Chronic) but this project must use .NET.

palmsey
  • 5,812
  • 3
  • 37
  • 41
  • See answer about NChronic http://stackoverflow.com/questions/14583285/clever-way-to-parse-dates-c-sharp/25588407#25588407 – Michael Freidgeim Jul 02 '16 at 13:56
  • Since I can't add an additional answer here apparently, I'll comment. I've been using [Microsoft.Recognizers.Text](https://github.com/Microsoft/Recognizers-Text) to great effect. – starbeamrainbowlabs Nov 24 '18 at 11:44

9 Answers9

12

We developed exactly what you are looking for on an internal project. We are thinking of making this public if there is sufficient need for it. Take a look at this blog for more details: http://precisionsoftwaredesign.com/blog.php.

Feel free to contact me if you are interested: contact@precisionsoftware.us

This library is now a SourceForge project. The page is at:

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

The assembly is in the downloads section, and the source is available with Mercurial.

Community
  • 1
  • 1
Eric
  • 2,029
  • 2
  • 26
  • 36
6

A .NET port of Chronic exists. See https://github.com/robertwilczynski/nChronic. I created a fork of it with some improvements and bug fixes, here: https://github.com/dorony/nChronic (sent pull requests, the author still hasn't responded).

Doron Yaacoby
  • 9,412
  • 8
  • 48
  • 59
5

I don't, but there's a Java port called jchronic. If nothing else, it could provide a good jumping-off point for your own. Or perhaps you could use a semi-automatic Java to C# translator like Octopus to help translate it. (Or something better, if anyone knows of anything.)

Okay, another possible avenue: could you use the chronic code using IronRuby?

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
4

@Blair Conrad - Good ideas! I tried to get Chronic running under IronRuby but had some problems with dependencies - I don't know that it's ready yet.

I found a project on Codeplex (DateTimeEnglishParser) that is attempting to do the same thing. It doesn't handle years or time yet, but it's a good start. I've worked on the project a little and contributed a patch to better handle written numbers.

It's an interesting problem, and has definitely helped me understand regular expressions better, so I think I'll keep working on it.

palmsey
  • 5,812
  • 3
  • 37
  • 41
3

There was a similar thread earlier and it gave a link to a library on CodeProject that seems to do what you want: http://www.codeproject.com/KB/edit/dateparser.aspx but unfortunately the library seems to be written in MFC so you would have to make a DLL out of it and then call it from your .NET program.

Community
  • 1
  • 1
Sanjay Sheth
  • 1,539
  • 1
  • 9
  • 9
3

Palmsey, I have just recently had the same requirment so I went ahead and wrote a simple parser. Its not the nicest code but it will handle things like:

"Today at 2pm" "Tuesday at 2pm - 15th july 2010 at 2am" "Previous Year at 2am - Tommorow at 14:30" "18th july 2010 at 2:45pm"

Stuck it on codeplex as maybe someone else will find it useful. Check it out: http://timestamper.codeplex.com/

Owen
  • 6,992
  • 7
  • 44
  • 77
3

I've checked several frameworks and Python's ParseDateTime worked the best. It can be used from .NET using IronPython.

If anyone's interested in a full sample project, comment on the answer and I'll try to create one.

EDIT

As requested, here is a simple project that you can use with the library:

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

Try the following usage case, for example:

  • August 25th, 2008
  • 25 Aug 2008
  • Aug 25 5pm
  • 5pm August 25
  • next saturday
  • tomorrow
  • next thursday at 4pm
  • at 4pm
  • eod
  • tomorrow eod
  • eod tuesday
  • eoy
  • eom
  • in 5 minutes
  • 5 minutes from now
  • 5 hours before now
  • 2 hours before noon
  • 2 days from tomorrow
VitalyB
  • 12,397
  • 9
  • 72
  • 94
2

I'm not aware of one, but it sounded like a cool problem, so here's my whack at it (VB.NET):

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

It's really not as sophisticated as ones that already exist, but it works alright I guess. Could be a nice extension method.

Burton
  • 343
  • 1
  • 10
1

@ Burton: I think he meant the other way, at least from the example on the linked page:

  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

I thought I would take a stab at it too until I realized! (nice implementation though)

Nick
  • 13,238
  • 17
  • 64
  • 100