How do I use DateTime.TryParse with a Nullable<DateTime>?

110,390

Solution 1

DateTime? d=null;
DateTime d2;
bool success = DateTime.TryParse("some date text", out d2);
if (success) d=d2;

(There might be more elegant solutions, but why don't you simply do something as above?)

Solution 2

As Jason says, you can create a variable of the right type and pass that. You might want to encapsulate it in your own method:

public static DateTime? TryParse(string text)
{
    DateTime date;
    if (DateTime.TryParse(text, out date))
    {
        return date;
    }
    else
    {
        return null;
    }
}

... or if you like the conditional operator:

public static DateTime? TryParse(string text)
{
    DateTime date;
    return DateTime.TryParse(text, out date) ? date : (DateTime?) null;
}

Or in C# 7:

public static DateTime? TryParse(string text) =>
    DateTime.TryParse(text, out var date) ? date : (DateTime?) null;

Solution 3

You can't because Nullable<DateTime> is a different type to DateTime. You need to write your own function to do it,

public bool TryParse(string text, out Nullable<DateTime> nDate)
{
    DateTime date;
    bool isParsed = DateTime.TryParse(text, out date);
    if (isParsed)
        nDate = new Nullable<DateTime>(date);
    else
        nDate = new Nullable<DateTime>();
    return isParsed;
}

Hope this helps :)

EDIT: Removed the (obviously) improperly tested extension method, because (as Pointed out by some bad hoor) extension methods that attempt to change the "this" parameter will not work with Value Types.

P.S. The Bad Hoor in question is an old friend :)

Solution 4

What about creating an extension method?

public static class NullableExtensions
{
    public static bool TryParse(this DateTime? dateTime, string dateString, out DateTime? result)
    {
        DateTime tempDate;
        if(! DateTime.TryParse(dateString,out tempDate))
        {
            result = null;
            return false;
        }

        result = tempDate;
        return true;

    }
}

Solution 5

This is the one liner you're looking for:

DateTime? d = DateTime.TryParse("some date text", out DateTime dt) ? dt : null;

If you want to make it a proper TryParse pseudo-extension method, you can do this:

public static bool TryParse(string text, out DateTime? dt)
{
    if (DateTime.TryParse(text, out DateTime date))
    {
        dt = date;
        return true;
    }
    else
    {
        dt = null;
        return false;
    }
}
Share:
110,390
Ram Rachum
Author by

Ram Rachum

Web developer and Microsoft MVP. Founder of the Red River .NET User Group.

Updated on April 15, 2021

Comments

  • Ram Rachum
    Ram Rachum about 3 years

    I want to use the DateTime.TryParse method to get the datetime value of a string into a Nullable. But when I try this:

    DateTime? d;
    bool success = DateTime.TryParse("some date text", out (DateTime)d);
    

    the compiler tells me

    'out' argument is not classified as a variable

    Not sure what I need to do here. I've also tried:

    out (DateTime)d.Value 
    

    and that doesn't work either. Any ideas?

  • Ram Rachum
    Ram Rachum over 15 years
    You're right, I was looking for more of a one-liner to get it done, but I suppose this will do. Don't like creating that temp variable, feels messy. :-/ Seems like this scenario should be better supported.
  • David Alpert
    David Alpert over 15 years
    see Binary Worrier's suggestion to psuedo-inline that into an extension method.
  • Aaron Powell
    Aaron Powell over 15 years
    Why are you casting a DateTime to a DateTime? You don't need to recased d2 before passing it into the TryParse.
  • Raymond
    Raymond over 15 years
    Ya dont wanna init the date [as you're using it as an out param] OK, I'll stop being picky!
  • Raymond
    Raymond over 15 years
    Dont have compiler on me, but as DateTime is a value type, does the extension method def compile?
  • Raymond
    Raymond over 15 years
    Result doesnt come back unless you make it out -- [TestFixture] public class WhenExtending { [Test] public void TryParseShouldWork() { DateTime? x = null; var res = Externders.TryParse( x, "1/1/1990" ); Assert.IsTrue( res )
  • Raymond
    Raymond over 15 years
    ;Assert.That( x != null ); } } fails on the Assert.That, i.e., the result doesnt get modified as DateTime is a value type (which is always a nice weed-out question on phone screens :D)
  • Raymond
    Raymond over 15 years
    (obv the first (non-extension) one will work, but it should be out, not ref - and you should be nulling the result if it fails to fit in with TryXXX APIs in general - Pretty sure FDG mentions that. Man, am I picky!
  • Rabeel
    Rabeel over 15 years
    Well obviously the samples shown are for illustration purposes . . . (and Ruben STOP NIT PICKING YA BAD HOOR!)
  • Rabeel
    Rabeel over 15 years
    P.S. . . . and what are these "Tests" and "Asserts" of which you speak? (Tell Me Of Your Home World Usul)
  • Rabeel
    Rabeel over 15 years
    Ruben: You're right mate, an extension method won't work for this (or any other value type). Well spotted . . . cough ya bad hoor cough
  • Drew Noakes
    Drew Noakes about 14 years
    @Slace -- I updated the answer to incorporate your suggestion.
  • Mike Zboray
    Mike Zboray over 11 years
    What is that first parameter, dateTime, for? It is never used.
  • Pimenta
    Pimenta over 11 years
    @Jason Kealey I hope this is already introduced in VS2012, otherwise I will have to continue using this good piece of code.
  • Erik Funkenbusch
    Erik Funkenbusch over 11 years
    @mikez - that's how how extension methods work, it's used by the compiler to know that it should be an extension method.
  • Mike Zboray
    Mike Zboray over 11 years
    @MystereMan I know what an extension method is. A more appropriate signature for an extension method would be DateTime? TryParse(this string dateString). This implementation is just bizarre.
  • Erik Funkenbusch
    Erik Funkenbusch over 11 years
    @mikez - then why did you ask what it was for? Why pollute the string namespace when you only need it for datetime? The purpose is to provide an analog to DateTime.TryParse that is DateTime?.TryParse
  • Myster
    Myster about 9 years
    I probably shouldn't argue with The Skeet, but... you should call your method Parse, since I would expect a method called TryParse to follow the TryParse convention and return a boolean. ;-)
  • Jon Skeet
    Jon Skeet about 9 years
    @Myster: Well in neither case does it follow the exact existing convention - those used to just Parse would expect it to return DateTime and throw an exception on failure, right? But yes, you can do whatever you want... and in Noda Time, I have named the relevant methods Parse instead.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 7 years
    The else keyword is unnecessary (in your first example) since the end-point of the if block can never be reached.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 7 years
    @ErikFunkenbusch This extension method will not allow a call syntax like (DateTime?).TryParse( ... ) or Nullable<DateTime>.TryParse( ... ). So mike z is right, this is a silly signature for the method.
  • Jon Skeet
    Jon Skeet over 7 years
    @JeppeStigNielsen: Yes, it's unnecessary - but it may be stylistically preferable for symmetry. It's just a personal preference (and I'm not consistent, either...)
  • Erik Funkenbusch
    Erik Funkenbusch over 7 years
    @JeppeStigNielsen - You apparently don't understand how extension methods work. You don't call them like static methods. You call them like normal methods, like variablename.TryParse(), not typename.TryParse()
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 7 years
    @ErikFunkenbusch Yes, you are right. The discussion here is what is the use of this DateTime? dateTime when that parameter is not used in the method body? This is the original question by mike z. If one were to use the method of this answer, one should do this: DateTime? dummy = null; DateTime? result; var isSuccess = dummy.TryParse("some date text", out result);. Otherwise one should assign a value to the out variable first, and use the out variable result as the "special" this argument as well, which seems strange. So can we answer mike z's first comment in a better way?
  • Kiquenet
    Kiquenet about 7 years
    Avoid Arrowhead anti-pattern else { return null; } by return null; View: blog.codinghorror.com/flattening-arrow-code
  • Jon Skeet
    Jon Skeet about 7 years
    @Kiquenet: using else makes it clearer that one or the other path will be taken, and both return. I'm against massively nested code, but in this case it's really not a problem IMO.
  • cpcolella
    cpcolella over 4 years
    @robnick How is that different than what i said?
  • robnick
    robnick over 4 years
    Ignore my previous comment (I have upvoted your solution!), for latest C# I needed to cast the null: DateTime? d = DateTime.TryParse(blah, out DateTime dt) ? dt : (DateTime?)null;
  • cpcolella
    cpcolella about 3 years
    so...you just copied my answer 4 months later?