Check DateTime format

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dan S

    Check DateTime format

    My application asks the user to enter in a date - in the mm/dd/yyyy format. Is there any quick and easy way to verify the date the user enters is formatted correctly? Right now I'm calling DateTime.Parse( ) and catching the FormatException but it seems this is a bit inefficient - catching the exception that is. There is some pretty obvious delay while it traces back up the call stack. Is there a better way? Something that returns a bool possibly?

    --
    Dan S
  • Shiva

    #2
    Re: Check DateTime format

    Hi,

    To just check the format you may use regular expressions like
    \d{1,2}\/\d{1,2}\/\d{4}. If this validates, use DateTime.Parse( ) to check
    the actual values.


    "Dan S" <DanS@discussio ns.microsoft.co m> wrote in message
    news:2B32202C-A4BF-4FB1-824C-A79826A6CA34@mi crosoft.com...
    My application asks the user to enter in a date - in the mm/dd/yyyy format.
    Is there any quick and easy way to verify the date the user enters is
    formatted correctly? Right now I'm calling DateTime.Parse( ) and catching
    the FormatException but it seems this is a bit inefficient - catching the
    exception that is. There is some pretty obvious delay while it traces back
    up the call stack. Is there a better way? Something that returns a bool
    possibly?

    --
    Dan S


    Comment

    • Jon Skeet [C# MVP]

      #3
      Re: Check DateTime format

      Dan S <DanS@discussio ns.microsoft.co m> wrote:[color=blue]
      > My application asks the user to enter in a date - in the mm/dd/yyyy
      > format. Is there any quick and easy way to verify the date the user
      > enters is formatted correctly? Right now I'm calling DateTime.Parse( )
      > and catching the FormatException but it seems this is a bit
      > inefficient - catching the exception that is. There is some pretty
      > obvious delay while it traces back up the call stack. Is there a
      > better way? Something that returns a bool possibly?[/color]

      After the first time, which may involve a delay due to loading
      resources, throwing an exception is likely to be very fast - far faster
      than a user can actually notice. On my laptop I can throw a hundred
      thousand exceptions in a second - I think that's rather more than a
      user is likely to enter.

      I'm not saying that exceptions are always a nice way to go, but I
      wouldn't dismiss them for performance reasons - at least not in this
      case.

      You can use a regular expression to check the format, of course - but
      you may well find that doing so is more expensive than just trying to
      parse the date and catching the exception.

      You could probably do slightly better with a hard-coded test, something
      like:

      static readonly char[] LowerBounds = "00/00/1000".ToCharArr ay();
      static readonly char[] UpperBounds = "19/39/2999".ToCharArr ay();
      static bool IsProbablyValid Date(string date)
      {
      if (date.Length != 10)
      {
      return false;
      }
      for (int i=0; i < date.Length; i++)
      {
      char c=date[i];
      if (c < LowerBounds[i] || c > UpperBounds[i])
      {
      return false;
      }
      }
      return true;
      }

      That gets rid of *many* invalid dates, but not all - you'll still need
      to call DateTime.Parse (or preferrably DateTime.ParseE xact) and catch
      the potential exception, unless you want to do all the parsing
      correctly.

      Note that it also requires the leading zeroes for months and days - if
      you don't want that, it becomes slightly trickier.

      (That only deals with dates in years 1000-2999; if you need to deal
      with earlier or later years, change the 7th character in
      LowerBounds/UpperBounds.)

      Here's a benchmark to compare the three approaches mentioned:

      using System;
      using System.Windows. Forms; // For MethodInvoker
      using System.Text.Reg ularExpressions ;
      using System.Globaliz ation;

      delegate void DoSomething();

      class Test
      {
      static string[] invalid = {"123123", "wibble", "32/12/3223",
      "14/23/1999", "04/35/1992", "02/29/2003"};

      static string[] valid = {"12/02/2321", "02/12/2312", "02/29/2004",
      "01/30/2000"};

      const int Iterations = 100000;

      static void Main()
      {
      Time (new MethodInvoker(T estRegex));
      Time (new MethodInvoker(T estHardCoded));
      Time (new MethodInvoker(T estNoPreCheck)) ;
      }

      static void Time(MethodInvo ker test)
      {
      DateTime start = DateTime.Now;
      test();
      DateTime end = DateTime.Now;

      Console.WriteLi ne ("{0}: {1}", test.Method.Nam e, end-start);
      }

      static readonly Regex Expression = new Regex
      (@"\d{1,2}\/\d{1,2}\/\d{4}", RegexOptions.Co mpiled);
      static void TestRegex()
      {
      for (int i=0; i < Iterations; i++)
      {
      foreach (string x in invalid)
      {
      if (Expression.IsM atch(x))
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);
      throw new Exception("Inva lid date passed");
      }
      catch
      {
      }
      }
      }
      foreach (string x in valid)
      {
      if (Expression.IsM atch(x))
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);

      }
      catch
      {
      throw new Exception("Vali d date failed");
      }
      }
      else
      throw new Exception("Vali d date failed");
      }
      }
      }

      static void TestHardCoded()
      {
      for (int i=0; i < Iterations; i++)
      {
      foreach (string x in invalid)
      {
      if (IsProbablyVali dDate(x))
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);

      throw new Exception("Inva lid date passed");
      }
      catch
      {
      }
      }
      }
      foreach (string x in valid)
      {
      if (IsProbablyVali dDate(x))
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);

      }
      catch
      {
      throw new Exception("Vali d date failed");
      }
      }
      else
      throw new Exception("Vali d date failed");
      }
      }
      }

      static void TestNoPreCheck( )
      {
      for (int i=0; i < Iterations; i++)
      {
      foreach (string x in invalid)
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);
      throw new Exception("Inva lid date passed");
      }
      catch
      {
      }
      }
      foreach (string x in valid)
      {
      try
      {
      DateTime.ParseE xact(x, "dd/mm/yyyy",
      CultureInfo.Inv ariantCulture);
      }
      catch
      {
      throw new Exception("Vali d date failed");
      }
      }
      }
      }

      static readonly char[] LowerBounds = "00/00/1000".ToCharArr ay();
      static readonly char[] UpperBounds = "19/39/2999".ToCharArr ay();
      static bool IsProbablyValid Date(string date)
      {
      if (date.Length != 10)
      {
      return false;
      }
      for (int i=0; i < date.Length; i++)
      {
      char c=date[i];
      if (c < LowerBounds[i] || c > UpperBounds[i])
      {
      return false;
      }
      }
      return true;
      }
      }

      The results on my laptop were:
      TestRegex: 00:00:09.343750 0
      TestHardCoded: 00:00:04.343750 0
      TestNoPreCheck: 00:00:12.515625 0

      Changing the regex to require exactly two digits instead of 1 or 2 for
      the month and day sped it up very slightly, but not really
      significantly.

      --
      Jon Skeet - <skeet@pobox.co m>
      Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

      If replying to the group, please do not mail me too

      Comment

      • Cor Ligthert

        #4
        Re: Check DateTime format

        Hi Dan,

        Probably you are using C# because you write so nice your DateTme.Parse() .

        However when you use VBNet you can use this.



        Cor
        [color=blue]
        > My application asks the user to enter in a date - in the mm/dd/yyyy[/color]
        format. Is there any quick and easy way to verify the date the user enters
        is formatted correctly? Right now I'm calling DateTime.Parse( ) and catching
        the FormatException but it seems this is a bit inefficient - catching the
        exception that is. There is some pretty obvious delay while it traces back
        up the call stack. Is there a better way? Something that returns a bool
        possibly?[color=blue]
        >[/color]


        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: Check DateTime format

          Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue]
          > Probably you are using C# because you write so nice your DateTme.Parse() .
          >
          > However when you use VBNet you can use this.
          > http://msdn.microsoft.com/library/de...ary/en-us/vblr
          > 7/html/vafctisdate.asp[/color]

          In fact, you can use that from within C# as well, if you really want to
          (although personally I'd recommend against using it).

          You just need to add a reference to the Microsoft.Visua lBasic.dll
          assembly, and then add

          using Microsoft.Visua lBasic;

          at the top of the source file, then use

          Information.IsD ate(foo);

          However, I very much doubt that that would be any faster than a
          straight try/catch round DateTime.ParseE xact.

          --
          Jon Skeet - <skeet@pobox.co m>
          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

          If replying to the group, please do not mail me too

          Comment

          • Cor Ligthert

            #6
            Re: Check DateTime format

            Hi Jon,

            I stuffed this row from the message while I was afraid to offend you.

            \\\
            As Jon often write it can be used in C# as well, when you want maybe he can
            than give you the proper code.
            ///

            :-)

            Cor
            [color=blue][color=green]
            > > Probably you are using C# because you write so nice your[/color][/color]
            DateTme.Parse() .[color=blue][color=green]
            > >
            > > However when you use VBNet you can use this.
            > > http://msdn.microsoft.com/library/de...ary/en-us/vblr
            > > 7/html/vafctisdate.asp[/color]
            >
            > In fact, you can use that from within C# as well, if you really want to
            > (although personally I'd recommend against using it).
            >
            > You just need to add a reference to the Microsoft.Visua lBasic.dll
            > assembly, and then add
            >
            > using Microsoft.Visua lBasic;
            >
            > at the top of the source file, then use
            >
            > Information.IsD ate(foo);
            >
            > However, I very much doubt that that would be any faster than a
            > straight try/catch round DateTime.ParseE xact.
            >[/color]


            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: Check DateTime format

              Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue]
              > I stuffed this row from the message while I was afraid to offend you.
              >
              > \\\
              > As Jon often write it can be used in C# as well, when you want maybe he can
              > than give you the proper code.
              > ///[/color]

              LOL - certainly no offence taken. I just don't think it's any better to
              use the VB function than to write their equivalent in "straight" .NET
              code :)

              --
              Jon Skeet - <skeet@pobox.co m>
              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

              If replying to the group, please do not mail me too

              Comment

              • Cor Ligthert

                #8
                Re: Check DateTime format

                Jon,

                For me is a try catch the same as a late binding, when it is for in advance
                catchable error handling, it should be avoided.

                However just my opinion.

                Cor
                [color=blue]
                > However, I very much doubt that that would be any faster than a
                > straight try/catch round DateTime.ParseE xact.
                >[/color]


                Comment

                • Cor Ligthert

                  #9
                  Re: Check DateTime format

                  > >[color=blue][color=green]
                  > > \\\
                  > > As Jon often write it can be used in C# as well, when you want maybe he[/color][/color]
                  can[color=blue][color=green]
                  > > than give you the proper code.
                  > > ///[/color]
                  >
                  > LOL - certainly no offence taken. I just don't think it's any better to
                  > use the VB function than to write their equivalent in "straight" .NET
                  > code :)
                  >[/color]
                  When you had not written that "straight" I would not have answered on this.
                  You mean with this *the not "straight" .Net* the simple basic namespace
                  without those very well intressing extentions as in the
                  Microsoft.Visua lBasic namespace.

                  However I agree with you that it is not right to use that function in C#
                  with the VB namespace. That difficult it cannot be to write it yourself as
                  your own class.

                  Cor


                  Comment

                  • Jon Skeet [C# MVP]

                    #10
                    Re: Check DateTime format

                    Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue]
                    > For me is a try catch the same as a late binding, when it is for in advance
                    > catchable error handling, it should be avoided.
                    >
                    > However just my opinion.[/color]

                    You seem to make an assumption that the VB function won't have a
                    try/catch inside it. I suspect that's not the case. A try/catch inside
                    someone else's method is going to take just as long as a try/catch
                    inside your own method...

                    --
                    Jon Skeet - <skeet@pobox.co m>
                    Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                    If replying to the group, please do not mail me too

                    Comment

                    • Cor Ligthert

                      #11
                      Re: Check DateTime format

                      > You seem to make an assumption that the VB function won't have a[color=blue]
                      > try/catch inside it. I suspect that's not the case. A try/catch inside
                      > someone else's method is going to take just as long as a try/catch
                      > inside your own method...[/color]

                      No a try catch can used everywhere so as well in a method in the VB
                      namespace however I think that it is not nice programming to use them for an
                      error which can be evaluated without to use that.

                      I said, my opinion.

                      Cor


                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: Check DateTime format

                        Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue][color=green]
                        > > LOL - certainly no offence taken. I just don't think it's any better to
                        > > use the VB function than to write their equivalent in "straight" .NET
                        > > code :)[/color][/color]
                        [color=blue]
                        > When you had not written that "straight" I would not have answered on this.
                        > You mean with this *the not "straight" .Net* the simple basic namespace
                        > without those very well intressing extentions as in the
                        > Microsoft.Visua lBasic namespace.[/color]

                        Not entirely sure what you mean there, but I don't count using
                        Microsoft.Visua lBasic namespace as writing "straight" .NET code. The
                        namespace is not documented under the main framework documentation -
                        it's only documented under the VB documentation, and it doesn't even
                        appear if you have the C# filter on. Sure, the assembly is probably
                        written entirely in .NET itself, but it's not part of the main
                        framework in my view.
                        [color=blue]
                        > However I agree with you that it is not right to use that function in C#
                        > with the VB namespace. That difficult it cannot be to write it yourself as
                        > your own class.[/color]

                        Um, I think I agree, depending on exactly what you mean.

                        --
                        Jon Skeet - <skeet@pobox.co m>
                        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                        If replying to the group, please do not mail me too

                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: Check DateTime format

                          Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue]
                          > For me is a try catch the same as a late binding, when it is for in advance
                          > catchable error handling, it should be avoided.[/color]

                          Just for fun, I included using Information.IsD ate in the benchmark
                          posted earlier. Here's the appropriate method:

                          static void TestIsDate()
                          {
                          for (int i=0; i < Iterations; i++)
                          {
                          foreach (string x in invalid)
                          {
                          if (Information.Is Date(x))
                          {
                          try
                          {
                          DateTime.ParseE xact(x, "dd/mm/yyyy",
                          CultureInfo.Inv ariantCulture);
                          throw new Exception("Inva lid date passed");
                          }
                          catch
                          {
                          }
                          }
                          }
                          foreach (string x in valid)
                          {
                          if (Information.Is Date(x))
                          {
                          try
                          {
                          DateTime.ParseE xact(x, "dd/mm/yyyy",
                          CultureInfo.Inv ariantCulture);
                          }
                          catch
                          {
                          throw new Exception("Vali d date failed");
                          }
                          }
                          else
                          throw new Exception("Vali d date failed: "+x);
                          }
                          }
                          }

                          The additional call to DateTime.ParseE xact is required if you want to
                          actually *get* the date. If you don't, and you trust IsDate completely,
                          the performance will obviously be better.

                          It only worked after setting the current culture of the current thread
                          to US:

                          Thread.CurrentT hread.CurrentCu lture = CultureInfo.Cre ateSpecificCult ure
                          ("en-US");

                          Results:
                          With DateTime.ParseE xact as well: 27.53s
                          Without DateTime.ParseE xact : 25.97s

                          So using the VB libraries is about 5 times slower than using a hard-
                          coded method, and requires extra changes to the running environment.
                          It's also over twice as slow as just using try/catch directly.

                          --
                          Jon Skeet - <skeet@pobox.co m>
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                          If replying to the group, please do not mail me too

                          Comment

                          • Jon Skeet [C# MVP]

                            #14
                            Re: Check DateTime format

                            Cor Ligthert <notfirstname@p lanet.nl> wrote:[color=blue][color=green]
                            > > You seem to make an assumption that the VB function won't have a
                            > > try/catch inside it. I suspect that's not the case. A try/catch inside
                            > > someone else's method is going to take just as long as a try/catch
                            > > inside your own method...[/color]
                            >
                            > No a try catch can used everywhere so as well in a method in the VB
                            > namespace however I think that it is not nice programming to use them for an
                            > error which can be evaluated without to use that.
                            >
                            > I said, my opinion.[/color]

                            I fail to see why writing your own method which uses try/catch is any
                            better than using a VB function which probably uses try/catch and
                            performs significantly worse than other alternatives. (See my other
                            post for performance figures.) Why is a try/catch buried in someone
                            else's code any better than a try/catch buried in yours? (You don't
                            have to have it everywhere - just in the method where you implement the
                            parsing/testing.)

                            --
                            Jon Skeet - <skeet@pobox.co m>
                            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                            If replying to the group, please do not mail me too

                            Comment

                            • Cor Ligthert

                              #15
                              Re: Check DateTime format

                              Jon,

                              I only wrote that in my opinion using a try and catch, for things that can
                              be catched in advance with code, should be avoided.

                              That does not mean that I did not believe you about the performance, the
                              code for testing a date can be very long, I did not even try to write an
                              example.

                              When I disagree with you about something, I write that, I think that you
                              have enough expirience with that. And when not there is no need to prove it
                              for me.

                              Maybe you think only C# people have principles, no it is not.

                              :-)

                              Cor


                              Comment

                              Working...