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.
c# .net string parsing datetime
add a comment |
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.
c# .net string parsing datetime
18
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
8
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
2
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46
add a comment |
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.
c# .net string parsing datetime
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.
c# .net string parsing datetime
c# .net string parsing datetime
edited Jun 20 '18 at 7:18
Matt
15.6k767112
15.6k767112
asked Mar 20 '11 at 1:58
HoochHooch
10.5k2670135
10.5k2670135
18
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
8
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
2
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46
add a comment |
18
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
8
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
2
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46
18
18
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
8
8
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
2
2
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46
add a comment |
8 Answers
8
active
oldest
votes
DateTime.Parse()
will try figure out the format of the given date, and it usually does a good job. If you can guarantee dates will always be in a given format then you can use ParseExact()
:
string s = "2011-03-21 13:26";
DateTime dt =
DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
(But note that it is usually safer to use one of the TryParse methods in case a date is not in the expected format)
Make sure to check Custom Date and Time Format Strings when constructing format string, especially pay attention to number of letters and case (i.e. "MM" and "mm" mean very different things).
Another useful resource for C# format strings is String Formatting in C#
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variables
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.
– Matt
Sep 4 '15 at 13:11
|
show 3 more comments
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");
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
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
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).
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 patterns=new "dd-MM-yyyy", "dd.MM.yyyy" ;
(new "15-01-2019", "15.01.2019" ).Select(s => s.ToDate(patterns)).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 if
statement 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.
add a comment |
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!
add a comment |
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?
add a comment |
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);
add a comment |
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.
* */
add a comment |
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
add a comment |
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;
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5366285%2fparse-string-to-datetime-in-c-sharp%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
DateTime.Parse()
will try figure out the format of the given date, and it usually does a good job. If you can guarantee dates will always be in a given format then you can use ParseExact()
:
string s = "2011-03-21 13:26";
DateTime dt =
DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
(But note that it is usually safer to use one of the TryParse methods in case a date is not in the expected format)
Make sure to check Custom Date and Time Format Strings when constructing format string, especially pay attention to number of letters and case (i.e. "MM" and "mm" mean very different things).
Another useful resource for C# format strings is String Formatting in C#
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variables
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.
– Matt
Sep 4 '15 at 13:11
|
show 3 more comments
DateTime.Parse()
will try figure out the format of the given date, and it usually does a good job. If you can guarantee dates will always be in a given format then you can use ParseExact()
:
string s = "2011-03-21 13:26";
DateTime dt =
DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
(But note that it is usually safer to use one of the TryParse methods in case a date is not in the expected format)
Make sure to check Custom Date and Time Format Strings when constructing format string, especially pay attention to number of letters and case (i.e. "MM" and "mm" mean very different things).
Another useful resource for C# format strings is String Formatting in C#
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variables
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.
– Matt
Sep 4 '15 at 13:11
|
show 3 more comments
DateTime.Parse()
will try figure out the format of the given date, and it usually does a good job. If you can guarantee dates will always be in a given format then you can use ParseExact()
:
string s = "2011-03-21 13:26";
DateTime dt =
DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
(But note that it is usually safer to use one of the TryParse methods in case a date is not in the expected format)
Make sure to check Custom Date and Time Format Strings when constructing format string, especially pay attention to number of letters and case (i.e. "MM" and "mm" mean very different things).
Another useful resource for C# format strings is String Formatting in C#
DateTime.Parse()
will try figure out the format of the given date, and it usually does a good job. If you can guarantee dates will always be in a given format then you can use ParseExact()
:
string s = "2011-03-21 13:26";
DateTime dt =
DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
(But note that it is usually safer to use one of the TryParse methods in case a date is not in the expected format)
Make sure to check Custom Date and Time Format Strings when constructing format string, especially pay attention to number of letters and case (i.e. "MM" and "mm" mean very different things).
Another useful resource for C# format strings is String Formatting in C#
edited Oct 29 '15 at 1:21
answered Mar 20 '11 at 2:07
Mitch WheatMitch Wheat
256k36408501
256k36408501
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variables
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.
– Matt
Sep 4 '15 at 13:11
|
show 3 more comments
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variables
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.
– Matt
Sep 4 '15 at 13:11
3
3
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
Correction - it is ALWAYS safer ;) If you are calling a method with an exception, always check the exception condition first if possible.
– Gusdor
Aug 27 '13 at 12:36
3
3
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
I'd say it's safer to always pass your culture. I'd rather have an exception than having "01-02-2013" be misinterpreted as either the second of January or the first of February.
– Carra
Oct 14 '13 at 8:38
1
1
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
@Carra: dates in ISO8601 format (i.e. yyyy-mm-dd' are always interpreted the correct way. That';s why we use ISO8601 format dates...
– Mitch Wheat
Jul 16 '14 at 2:41
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
Parse exact can be useful. Sometimes, I would prefer my application crash and my computer light on fire, as opposed to producing incorrect output. Depends on the application.
– Allen
Jul 31 '15 at 18:03
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variable
s
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.– Matt
Sep 4 '15 at 13:11
ParseExact is great because it is flexible, but it has a downside: Note that ParseExact and Parse methods throw exceptions if there is a syntax error in the date format of variable
s
. Hence, it is better to use TryParseExcact. I have pointed out why in my answer below.– Matt
Sep 4 '15 at 13:11
|
show 3 more comments
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");
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
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
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).
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 patterns=new "dd-MM-yyyy", "dd.MM.yyyy" ;
(new "15-01-2019", "15.01.2019" ).Select(s => s.ToDate(patterns)).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 if
statement 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.
add a comment |
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");
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
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
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).
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 patterns=new "dd-MM-yyyy", "dd.MM.yyyy" ;
(new "15-01-2019", "15.01.2019" ).Select(s => s.ToDate(patterns)).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 if
statement 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.
add a comment |
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");
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
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
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).
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 patterns=new "dd-MM-yyyy", "dd.MM.yyyy" ;
(new "15-01-2019", "15.01.2019" ).Select(s => s.ToDate(patterns)).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 if
statement 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.
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");
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
// Extension method parsing a date string to a DateTime?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
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).
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 patterns=new "dd-MM-yyyy", "dd.MM.yyyy" ;
(new "15-01-2019", "15.01.2019" ).Select(s => s.ToDate(patterns)).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 if
statement 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.
edited Feb 1 at 16:07
answered Aug 27 '13 at 12:18
MattMatt
15.6k767112
15.6k767112
add a comment |
add a comment |
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!
add a comment |
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!
add a comment |
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!
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!
edited Jun 17 '15 at 8:50
DatRid
90021639
90021639
answered Mar 20 '11 at 2:08
Rob♦Rob
23.9k115777
23.9k115777
add a comment |
add a comment |
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?
add a comment |
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?
add a comment |
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?
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?
answered Mar 20 '11 at 2:09
cacoiscacois
1,64021518
1,64021518
add a comment |
add a comment |
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);
add a comment |
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);
add a comment |
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);
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);
answered Apr 30 '11 at 1:05
Zack PetersonZack Peterson
31.1k75192277
31.1k75192277
add a comment |
add a comment |
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.
* */
add a comment |
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.
* */
add a comment |
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.
* */
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.
* */
answered Jul 10 '18 at 6:33
Shivam BharadwajShivam Bharadwaj
11515
11515
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
edited Aug 3 '18 at 21:59
Andrea Perelli
952212
952212
answered Jun 5 '17 at 22:04
Amir ShenoudaAmir Shenouda
1,6471105
1,6471105
add a comment |
add a comment |
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;
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
add a comment |
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;
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
add a comment |
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;
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;
edited Jan 24 at 7:48
Ali
1,1771321
1,1771321
answered Jan 24 at 7:04
Adil AyoubAdil Ayoub
1
1
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
add a comment |
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
Hi, Welcome, Please provide an explanation when answering a question. Just posting code is not recommended
– Ali
Jan 24 at 7:27
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5366285%2fparse-string-to-datetime-in-c-sharp%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
18
So why don't you use DateTime.Parse?
– Austin Salonen
Mar 20 '11 at 2:06
8
I was one of the downvoters. It was because your original question (stackoverflow.com/revisions/…) stated that you WANTED to use DateTime.Parse() but you didn't state WHY you couldn't use it. This made it seem like a nonsense question, especially since a simple check would have made it clear that cacois's was correct: Your string "2011-03-21 13:26" is not a problem for DateTime.Parse(). Finally, you did not make any mention of ParseExact() in your original question. You waited until after Mitch's answer to add this in an edit.
– anon
Mar 20 '11 at 4:31
2
I just love those people down-voting question without giving any reason in comments.
– Hooch
Apr 21 '15 at 11:46