-2

I am trying a more efficient way to write this datetime function shown here, so that it can still give a correct date whether the datetime is in 24 hour notation or not. Currently, it works but throws errors when the notation changes.

using System;
using System.Web;
using System.Globalization;

class Program 
{
    private static string req =  "01/26/2023 5:32 PM"; 
    private static int hourNotation;
    private static DateTime? expectedDate; 
  
    static void Main(string[] args) 
    {
        Console.WriteLine("Hello, world!");
        hourNotation = Convert.ToInt32(req[11].ToString());

        // Task task = Task.Delay(1000);
        if (hourNotation >= 1)
        {
            expectedDate = DateTime.ParseExact(req.Substring(0, req.Length - 3), "MM/dd/yyyy HH:mm",
                                                      new CultureInfo("en-US"),
                                                      DateTimeStyles.None);
            Console.WriteLine("greater than 10");
        }
        else
        {
            expectedDate = DateTime.ParseExact(req.Substring(0, req.Length - 3), "MM/dd/yyyy h:mm",
                                                         new CultureInfo("en-US"),
                                                         DateTimeStyles.None);
            Console.WriteLine("Less than 10");
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Zidane
  • 1,696
  • 3
  • 21
  • 35
  • 1
    1) What is the exact error that it throws? 2) Note that you can pass an [array of formats to DateTime.ParseExact](https://learn.microsoft.com/en-us/dotnet/api/system.datetime.parseexact?view=net-7.0#system-datetime-parseexact(system-string-system-string()-system-iformatprovider-system-globalization-datetimestyles)) for it to try with. – Andrew Morton Jan 29 '23 at 19:44

2 Answers2

2

You can greatly simplify this by using one the ParseExact() overloads that accepts an array of formats.

Just keep in mind: they mean it when they use "Exact" in the ParseExact() name. If your formats are not defined perfectly you'll get exceptions at run time. In this case, the format string for the 12 hour format is not right, because it's missing the time of day specifier. So you need this:

MM/dd/yyyy h:mm tt

Additionally, if you're allowing users to enter date or time values by hand, you WILL eventually (usually sooner than later) have users enter ambiguous or unparseable data. In this case, we see it expects the U.S. format, so a common failure is a visitor from the UK will naturally cause something like 29/1/2023 to go in the field, because that's how they and everyone else from that country have always done it. Even worse, they'll use 3/2/2023 expecting to get Feb 3 instead of March 2.

Better to have UI support to help the user select a date or time value via a guided process or clock/calendar control of some kind, and immediately show unambiguous feedback (using the written month name) of how an input will be interpreted.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
1

What about:

using System.Globalization;
class Program
{

    private static string req = "01/26/2023 21:32";
    private static List<string> dates = new List<string> { "01/26/2023 21:32", "01/26/2023 1:32", "01/26/2023 1:32 AM", "01/26/2023 11:32 PM" };


    private static DateTime? expectedDate;

    static void Main(string[] args)
    {

        Console.WriteLine("Hello, world!");
        foreach (string date in dates)
        {
            var isTwelveHour = date.ToUpper().Contains("PM") | date.ToUpper().Contains("AM");

            expectedDate = isTwelveHour
                ? DateTime.ParseExact(date, "MM/dd/yyyy h:mm tt",
                                                  new CultureInfo("en-US"),
                                                  DateTimeStyles.None)
                : DateTime.ParseExact(date, "MM/dd/yyyy H:mm",
                                                     new CultureInfo("en-US"),
                                                     DateTimeStyles.None);

            var clock = isTwelveHour ? "12 Hour Clock" : "24 Hour Clock";

            Console.WriteLine($"{clock} : {expectedDate.ToString()}");
        }
    }
}
MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31
  • This can still fail for 12 hour inputs, because there's no indication on what to do with the time of day indicator. Also, the output at the end will repeat the "Hour clock" part. – Joel Coehoorn Jan 29 '23 at 20:18
  • [Polite]. Yes on the repeated "Hour Clock" but it was only a `WriteLine`. What format fails? – MrC aka Shaun Curtis Jan 29 '23 at 20:49
  • I missed that you had reversed the order of formats from the original question, so when I looked for the `tt` at the end of the 2nd format I didn't see it – Joel Coehoorn Jan 29 '23 at 21:07
  • NP. The order was dictated by the bool check and checking for 12 hour format seemed the logical way to do it. This is enlightening - https://www.youtube.com/watch?v=-5wpm-gesOY – MrC aka Shaun Curtis Jan 29 '23 at 21:50