Click here to Skip to main content
Click here to Skip to main content

C# Date Time Parser

By , 28 Jun 2012
Rate this:
Please Sign up or sign in to vote.

Introduction

Once I needed to parse date&time from internet messages. Those messages were sent by different users, and so could not comply with a single format. They consisted usually of 1 or 2 sentences, but it was hard to foresee where a date or time is within them. Thus, the use of DateTime.Parse() was impossible because this method accepts only an exact date presentation string to be parsed. Moreover, later, some date presentations appeared to not be recognized by DateTime.Parse().

What I needed was a C# function like the universal Perl's str2time() or PHP's strtotime(). After some Googling, I was surprised not to find such a code in C#. That's why I wrote the pretty simple class presented here. 

Description 

The class DateTimeRoutines exposes several date/time parsing methods. The general idea is finding the first instance of the date and (or) time within the passed string and converting it into DateTime

Method  Description 
TryParseDateTime()  Tries to find both a date and a time within the passed string. If a date or time is not found, then it returns false.
TryParseDate()  Tries to find a date within the passed string. It always returns the time 0Blush | :O Blush | :O  . If the year of the date was not found, then it accepts, by default, the current year; this rule can be changed by specifying DefaultDate. If a date is not found, then it returns false
TryParseTime()  Tries to find a time within the passed string. If a date previously found in the string is specified as a parameter, then it looks for a time around this date. It always returns the date 1/1/1. If a time is not found, then it returns false.
TryParseDateOrTime()  Tries to find a date and/or time within the passed string. If only a time is found, by default, the date is set by today's date; this rule can be changed by specifying DefaultDate. If neither the date nor the time is found, then it returns false.

These methods accept a DateTimeFormat parameter that specifies the recognition format used as preferred in ambivalent instances. 

These methods return a ParsedDateTime object. This object describes whether a date (or time) was found within the string and where it was found (if it exists), and also hosts a DateTime structure as a result of parsing. 

Also, these methods have derivations that return a DateTime directly instead of ParsedDateTime. The use of the origin methods is preferable though because their output allows knowing whether a date (or time) was really found or if it was constructed by default.

Notice that TryParseDateTime() and TryParseTime() may return different times in the case where the parsed string contains more than one time substring. TryParseDateTime() looks for a time around a date, while TryParseTime() returns a time that was found first.   

Local and Absolute Time 

ParsedDateTime.DateTime is always considered local meaning that it reflects the parsed string literally. If UTC offset or time zone abbreviation indicating that the time is absolute was found in the time string then ParsedDateTime.IsUtcOffsetFound is true and ParsedDateTime.UtcDateTime is UTC date&time. If ParsedDateTime.IsUtcOffsetFound is false, then ParsedDateTime.UtcDateTime should be regarded as undefined. 

Notice that TryParseDate() does not detect time zone      

Usage    

The date formats that can be recognized by DateTimeRoutines can be seen in the test strings listed below (the complete list of parsed formats can be found in Test project supplied with the code): 

@"Member since:  	10-Feb-2008"
@"Last Update: 18:16 11 Feb '08 "
@"date	Tue, Feb 10, 2008 at 11:06 AM"
@"see at 12/31/2007 14:16:32"
@"sack finish 14:16:32 November 15 2008, 1-144 app"
@"Genesis Message - Wed 04 Feb 08 - 19:40"
@"The day 07/31/07 14:16:32 is "
@"Shipping is on us until December 24, 2008 within the U.S." 
@" 2008 within the U.S. at 14:16:32"
@"5th November, 1994, 8:15:30 pm"
@"7 boxes January 31 , 14:16:32."
@"the blue sky of Sept  30th  2008 14:16:32"
@" e.g. 1997-07-16T19:20:30+01:00"
@"Apr 1st, 2008 14:16:32 tufa 6767"
@"wait for 07/31/07 14:16:32"
@"later 12.31.08 and before 1.01.09"
@"Expires: Sept  30th  2008 14:16:32"
@"Offer expires Apr 1st, 2007, 14:16:32"
@"Expires  14:16:32 January 31."
@"Expires  14:16:32 January 31-st."
@"Expires 23rd January 2010."
@"Expires January 22nd, 2010."
@"Expires DEC 22, 2010."

A code sample if you need to get only the date:

string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParseDate(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
    Console.WriteLine("Date was found: " + pdt.DateTime.ToString());

A code sample if you want to get the date and, if possible, the time:

string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParse(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt)
    && pdt.IsDateFound
    )
    Console.WriteLine("Date was found: " + pdt.DateTime.ToString());

A code sample if you want to get only the completely specified date and time: 

string str = @"The last round was June 10, 2005 10:30AM; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if(str.TryParseDateTime(DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
    Console.WriteLine("Date&time was found: " + pdt.DateTime.ToString());

A code sample if you want to get UTC date and time:  

string str = @"Your program recognizes string : 21 Jun 2010 04:20:19 -0430 blah blah.";
DateTimeRoutines.ParsedDateTime pdt;
if(str.TryParseDateTime(DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt) && pdt.IsUtcOffsetFound) 
Console.WriteLine("UTC date&time was found: " + pdt.UtcDateTime.ToString());

 .NET Version Consistency  

DateTimeRoutines is formed as a .NET 4 DLL that provides the above listed parsed methods as extensions for string class. The DLL can be called by .NET 2 code just as well. However, if you want to embed DateTimeRoutines source code into your .NET 2 project, you'll have to remove keyword this from the method parameters.

Conclusion

This code satisfied my needs. I did not want to implement too wide a recognition capability like say, the one provided by Perl's str2time(), because a more wide recognition means a higher error rate when the parser tries to find a date/time within any part of the passed string.

Nevertheless, DateTimeRoutines seems to be capable of recognizing the usual formats which can be found in a correspondence. If you find some prevalent date/time format that is not recognized, please let me know, and if I have time, I'll try to update the code.

The Code

In the attached code, you can find the DateTimeRoutines project containing:

  • A class DateTimeRoutines that is compiled as a DLL
  • Project Test

The code is licensed as public domain code. 

The latest version can be found on SourceForge

Be happy!

History

  • 11th February, 2009
    • Initial post
  • 14th February, 2009
    • TryParseDateTime() added
  • 18th December, 2009
    • TryParseDate() updated
  • 3rd March, 2010
    • TryParseDate() updated
  • 12th March, 2010
    • locks removed
  • 13th March, 2010
    • Formed as a DLL
    • Methods formed as extensions for string class
    • TryParse() renamed to TryParseDateOrTime()
  • 13th July, 2010
    • Updated source code 
  • 15th May, 2011
    • Fixed 12pm and 12am 
    • Upgraded to C# 4.0  
  • 18th April, 2012
    • Added one more date format;
  • 28th June, 2012
    • Added UTC recognition;

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

About the Author

Sergey Stoyan
Architect CliverSoft (www.cliversoft.com)
Ukraine Ukraine
Sergey is graduated as applied mathematician. He is specialized in client/server applications, backup systems, data parsing tools, web crawlers and search engines. Work for CliverSoft Co. Favorite languages are C#, C++, Perl

Comments and Discussions

 
GeneralMy vote of 5 Pinmemberamish kumar4-Dec-12 20:12 
GeneralRe: My vote of 5 PinmemberSergey Stoyan10-Dec-12 1:51 
GeneralRe: My vote of 5 Pinmemberamish kumar10-Dec-12 2:08 
GeneralRe: My vote of 5 Pinmemberamish kumar3-Feb-13 18:51 
GeneralRe: My vote of 5 PinmemberSergey Stoyan11-Apr-14 13:38 
GeneralRe: My vote of 5 Pinmemberamish kumar16-Apr-14 19:35 
GeneralMy vote of 5 Pinmemberdevvvy30-Oct-12 16:06 
GeneralMy vote of 5 Pinmemberrctaubert30-Jun-12 9:54 
GeneralMy vote of 5 PinmemberForogar28-Jun-12 3:37 
GeneralRe: My vote of 5 Pinmemberdave.dolan28-Jun-12 5:59 
GeneralRe: My vote of 5 PinmemberSergey Stoyan29-Jun-12 14:30 
Questionoffset from UTC (like +0300) [modified] Pinmemberzadront21-Jun-12 20:58 
Whats about parsing local offset from Coordinated Universal Time (UTC), for example: +0700, -0430 , +1000 ?
Your program recognizes string : "21 Jun 2010 04:20:19 -0400" as
"21 Jun 2010 04:20:19"
It will be cool to add method transforming parsed Date and Time to UTC.

modified 22-Jun-12 3:09am.

AnswerRe: offset from UTC (like +0300) PinmemberSergey Stoyan25-Jun-12 12:25 
GeneralRe: offset from UTC (like +0300) Pinmemberzadront26-Jun-12 21:27 
GeneralRe: offset from UTC (like +0300) PinmemberSergey Stoyan28-Jun-12 1:47 
GeneralRe: offset from UTC (like +0300) Pinmemberzadront2-Jul-12 1:55 
SuggestionSome more formats to add Pinmemberbbp12317-Apr-12 9:14 
GeneralRe: Some more formats to add PinmemberSergey Stoyan17-Apr-12 23:41 
GeneralRe: Some more formats to add Pinmemberbbp12325-Apr-12 11:08 
SuggestionMy vote of 5 - support for cultures PinmemberJani Giannoudis30-Aug-11 23:21 
GeneralRe: My vote of 5 - support for cultures PinmemberSergey Stoyan31-Aug-11 21:25 
AnswerRe: My vote of 5 - support for cultures PinmemberJani Giannoudis1-Sep-11 9:40 
GeneralMy vote of 5 PinmemberMBigglesworth7928-Jun-11 0:57 
GeneralBug with times between 12:00 and 1:00 Pinmemberdbrenth13-May-11 5:10 
GeneralRe: Bug with times between 12:00 and 1:00 [modified] Pinmemberdbrenth13-May-11 5:21 
GeneralRe: Bug with times between 12:00 and 1:00 [modified] PinmemberSergey Stoyan15-May-11 22:10 
GeneralRe: Bug with times between 12:00 and 1:00 Pinmemberdbrenth16-May-11 2:39 
GeneralRe: Bug with times between 12:00 and 1:00 PinmemberKanou9216-May-11 23:01 
GeneralRe: Bug with times between 12:00 and 1:00 PinmemberSergey Stoyan17-May-11 0:07 
GeneralRe: Bug with times between 12:00 and 1:00 PinmemberKanou9217-May-11 2:11 
GeneralMy vote of 5 Pinmemberdbrenth15-Apr-11 5:40 
GeneralFacilitate multiple matches PinmemberIIsi 50MHz6-Dec-10 11:05 
GeneralRe: Facilitate multiple matches PinmemberSergey Stoyan6-Dec-10 11:17 
GeneralMy vote of 5 PinmemberKentuckyEnglishman20-Jul-10 2:36 
QuestionWhat about the other countries ? PinmemberKanou9216-Jul-10 3:54 
AnswerRe: What about the other countries ? PinmemberSergey Stoyan18-Jul-10 23:00 
GeneralMy vote of 5 PinmemberRoger Wright13-Jul-10 16:29 
QuestionBug in TryParseDateTime ? PinmemberCoperNick6-Jun-10 23:48 
AnswerRe: Bug in TryParseDateTime ? PinmemberSergey Stoyan7-Jun-10 0:13 
GeneralRe: Bug in TryParseDateTime ? [modified] PinmemberCoperNick7-Jun-10 0:48 
GeneralRe: Bug in TryParseDateTime ? PinmemberCoperNick7-Jun-10 0:59 
GeneralRe: Bug in TryParseDateTime ? PinmemberSergey Stoyan7-Jun-10 1:11 
GeneralRe: Bug in TryParseDateTime ? PinmemberCoperNick7-Jun-10 2:29 
GeneralRe: Bug in TryParseDateTime ? PinmemberCoperNick7-Jun-10 2:57 
GeneralRe: Bug in TryParseDateTime ? [modified] PinmemberSergey Stoyan7-Jun-10 3:19 
Generalgood work PinmemberMohammad Elsheimy12-Mar-10 10:35 
GeneralRe: good work PinmemberSergey Stoyan12-Mar-10 22:46 
GeneralRe: good work PinmemberMohammad Elsheimy13-Mar-10 2:27 
GeneralRe: good work PinmemberSergey Stoyan13-Mar-10 6:47 
QuestionPointless locking? PinmemberRichard Deeming11-Mar-10 9:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140415.2 | Last Updated 28 Jun 2012
Article Copyright 2009 by Sergey Stoyan
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid