[c#] Parse string to DateTime in C#

I have date and time in a string formatted like that one:

"2011-03-21 13:26" //year-month-day hour:minute

How can I parse it to System.DateTime?

I want to use functions like DateTime.Parse() or DateTime.ParseExact() if possible, to be able to specify the format of the date manually.

This question is related to c# .net string parsing datetime

The answer is


Try the following code

Month = Date = DateTime.Now.Month.ToString();   
Year = DateTime.Now.Year.ToString(); 
ViewBag.Today = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(Int32.Parse(Month)) + Year;

Put the value of a human-readable string into a .NET DateTime with code like this:

DateTime.ParseExact("April 16, 2011 4:27 pm", "MMMM d, yyyy h:mm tt", null);

var dateStr = @"2011-03-21 13:26";
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture);

Check out this link for other format strings!


The simple and straightforward answer -->

using System;

namespace DemoApp.App

{
public class TestClassDate
{
    public static DateTime GetDate(string string_date)
    {
        DateTime dateValue;
        if (DateTime.TryParse(string_date, out dateValue))
            Console.WriteLine("Converted '{0}' to {1}.", string_date, dateValue);
        else
            Console.WriteLine("Unable to convert '{0}' to a date.", string_date);
        return dateValue;
    }
    public static void Main()
    {
        string inString = "05/01/2009 06:32:00";
        GetDate(inString);
    }
}
}

/**
 * Output:
 * Converted '05/01/2009 06:32:00' to 5/1/2009 6:32:00 AM.
 * */

As I am explaining later, I would always favor the TryParse and TryParseExact methods. Because they are a bit bulky to use, I have written an extension method which makes parsing much easier:

var    dtStr = "2011-03-21 13:26";
DateTime? dt = dtStr.ToDate("yyyy-MM-dd HH:mm");

Or more simply, if you want to use the date patterns of your current culture implicitly, you can use it like:

 DateTime? dt = dtStr.ToDate();

In that case no specific pattern need to be specified.

Unlike Parse, ParseExact etc. it does not throw an exception, and allows you to check via

if (dt.HasValue) { // continue processing } else { // do error handling }

whether the conversion was successful (in this case dt has a value you can access via dt.Value) or not (in this case, it is null).

That even allows to use elegant shortcuts like the "Elvis"-operator ?., for example:

int? year = dtStr?.ToDate("yyyy-MM-dd HH:mm")?.Year;

Here you can also use year.HasValue to check if the conversion succeeded, and if it did not succeed then year will contain null, otherwise the year portion of the date. There is no exception thrown if the conversion failed.


Solution:  The   .ToDate()   extension method

Try it in .NetFiddle

public static class Extensions
{
    /// <summary>
    /// Extension method parsing a date string to a DateTime? <para/>
    /// </summary>
    /// <param name="dateTimeStr">The date string to parse</param>
    /// <param name="dateFmt">dateFmt is optional and allows to pass 
    /// a parsing pattern array or one or more patterns passed 
    /// as string parameters</param>
    /// <returns>Parsed DateTime or null</returns>
    public static DateTime? ToDate(this string dateTimeStr, params string[] dateFmt)
    {
      // example: var dt = "2011-03-21 13:26".ToDate(new string[]{"yyyy-MM-dd HH:mm", 
      //                                                  "M/d/yyyy h:mm:ss tt"});
      // or simpler: 
      // var dt = "2011-03-21 13:26".ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");
      const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces;
      if (dateFmt == null)
      {
        var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
        dateFmt=dateInfo.GetAllDateTimePatterns();
      }
      var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
                   style, out var dt) ? dt : null as DateTime?;
      return result;
    }
}

Some information about the code

You might wonder, why I have used InvariantCulture calling TryParseExact: This is to force the function to treat format patterns always the same way (otherwise for example "." could be interpreted as decimal separator in English while it is a group separator or a date separator in German). Recall we have already queried the culture based format strings a few lines before so that is okay here.

Update: .ToDate() (without parameters) now defaults to all common date/time patterns of the thread's current culture.
Note that we need the result and dt together, because TryParseExact does not allow to use DateTime?, which we intend to return. In C# Version 7 you could simplify the ToDate function a bit as follows:

 // in C#7 only: "DateTime dt;" - no longer required, declare implicitly
 if (DateTime.TryParseExact(dateTimeStr, dateFmt,
     CultureInfo.InvariantCulture, style, out var dt)) result = dt;

or, if you like it even shorter:

 // in C#7 only: Declaration of result as a "one-liner" ;-)
 var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
              style, out var dt) ? dt : null as DateTime?;

in which case you don't need the two declarations DateTime? result = null; and DateTime dt; at all - you can do it in one line of code. (It would also be allowed to write out DateTime dt instead of out var dt if you prefer that).

The old style of C# would have required it the following way (I removed that from the code above):

  // DateTime? result = null;
  // DateTime dt;
  // if (DateTime.TryParseExact(dateTimeStr, dateFmt,
  //    CultureInfo.InvariantCulture, style, out dt)) result = dt;

I have simplified the code further by using the params keyword: Now you don't need the 2nd overloaded method any more.


Example of usage

var dtStr="2011-03-21 13:26";    
var dt=dtStr.ToDate("yyyy-MM-dd HH:mm");
if (dt.HasValue)
{
    Console.WriteLine("Successful!");
    // ... dt.Value now contains the converted DateTime ...
}
else
{
    Console.WriteLine("Invalid date format!");
}

As you can see, this example just queries dt.HasValue to see if the conversion was successful or not. As an extra bonus, TryParseExact allows to specify strict DateTimeStyles so you know exactly whether a proper date/time string has been passed or not.


More Examples of usage

The overloaded function allows you to pass an array of valid formats used for parsing/converting dates as shown here as well (TryParseExact directly supports this), e.g.

string[] dateFmt = {"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"};
var dtStr="5/1/2009 6:32 PM"; 
var dt=dtStr.ToDate(dateFmt);

If you have only a few template patterns, you can also write:

var dateStr = "2011-03-21 13:26";
var dt = dateStr.ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");

Advanced examples

You can use the ?? operator to default to a fail-safe format, e.g.

var dtStr = "2017-12-30 11:37:00";
var dt = (dtStr.ToDate()) ?? dtStr.ToDate("yyyy-MM-dd HH:mm:ss");

In this case, the .ToDate() would use common local culture date formats, and if all these failed, it would try to use the ISO standard format "yyyy-MM-dd HH:mm:ss" as a fallback. This way, the extension function allows to "chain" different fallback formats easily.

You can even use the extension in LINQ, try this out (it's in the .NetFiddle above):

var strDateArray = new[] { "15-01-2019", "15.01.2021" };
var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
var dtRange = strDateArray.Select(s => s.ToDate(patterns));
dtRange.Dump(); 

which will convert the dates in the array on the fly by using the patterns and dump them to the console.


Some background about TryParseExact

Finally, Here are some comments about the background (i.e. the reason why I have written it this way):

I am preferring TryParseExact in this extension method, because you avoid exception handling - you can read in Eric Lippert's article about exceptions why you should use TryParse rather than Parse, I quote him about that topic:2)

This unfortunate design decision1) [annotation: to let the Parse method throw an exception] was so vexing that of course the frameworks team implemented TryParse shortly thereafter which does the right thing.

It does, but TryParse and TryParseExact both are still a lot less than comfortable to use: They force you to use an uninitialized variable as an out parameter which must not be nullable and while you're converting you need to evaluate the boolean return value - either you have to use an ifstatement immediately or you have to store the return value in an additional boolean variable so you're able to do the check later. And you can't just use the target variable without knowing if the conversion was successful or not.

In most cases you just want to know whether the conversion was successful or not (and of course the value if it was successful), so a nullable target variable which keeps all the information would be desirable and much more elegant - because the entire information is just stored in one place: That is consistent and easy to use, and much less error-prone.

The extension method I have written does exactly that (it also shows you what kind of code you would have to write every time if you're not going to use it).

I believe the benefit of .ToDate(strDateFormat) is that it looks simple and clean - as simple as the original DateTime.Parse was supposed to be - but with the ability to check if the conversion was successful, and without throwing exceptions.


1) What is meant here is that exception handling (i.e. a try { ... } catch(Exception ex) { ...} block) - which is necessary when you're using Parse because it will throw an exception if an invalid string is parsed - is not only unnecessary in this case but also annoying, and complicating your code. TryParse avoids all this as the code sample I've provided is showing.


2) Eric Lippert is a famous StackOverflow fellow and was working at Microsoft as principal developer on the C# compiler team for a couple of years.


You can also use XmlConvert.ToDateString

var dateStr = "2011-03-21 13:26";
var parsedDate = XmlConvert.ToDateTime(dateStr, "yyyy-MM-dd hh:mm");

It is good to specify the date kind, the code is:

var anotherParsedDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd hh:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

More details on different parsing options http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html


DateTime.Parse() should work fine for that string format. Reference:

http://msdn.microsoft.com/en-us/library/1k1skd40.aspx#Y1240

Is it throwing a FormatException for you?


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to parsing

Got a NumberFormatException while trying to parse a text file for objects Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Python/Json:Expecting property name enclosed in double quotes Correctly Parsing JSON in Swift 3 How to get response as String using retrofit without using GSON or any other library in android UIButton action in table view cell "Expected BEGIN_OBJECT but was STRING at line 1 column 1" How to convert an XML file to nice pandas dataframe? How to extract multiple JSON objects from one file? How to sum digits of an integer in java?

Examples related to datetime

Comparing two joda DateTime instances How to format DateTime in Flutter , How to get current time in flutter? How do I convert 2018-04-10T04:00:00.000Z string to DateTime? How to get current local date and time in Kotlin Converting unix time into date-time via excel Convert python datetime to timestamp in milliseconds SQL Server date format yyyymmdd Laravel Carbon subtract days from current date Check if date is a valid one Why is ZoneOffset.UTC != ZoneId.of("UTC")?