1

I need to convert this DateTime string("6/12/2018 12:00:03 a. m.") to DateTime type using the function DateTime.ParseExact().

I converted the string using this option and it works:

var date = "6/01/2018  12:00:03 a. m.";
var x=Convert.ToDateTime(date);

Also I was able to convert this string("6/12/2018 12:00:03") using DateTime.ParseExact() but when the date doesn´t contain the indicator a. m. or p. m.:

var date = "6/01/2018  12:00:03";
var x=DateTime.ParseExact(date, "d/MM/yyyy  h:mm:ss", CultureInfo.InvariantCulture);

How can I convert that datetime string when the time part contains the a. m. or p. m. part using DateTime.ParseExact() function?

dbc
  • 104,963
  • 20
  • 228
  • 340
Andres Camacho
  • 367
  • 4
  • 17
  • 2
    Possible duplicate of [how to convert a string containing AM/PM to DateTime?](https://stackoverflow.com/questions/28672191/how-to-convert-a-string-containing-am-pm-to-datetime) – Ňɏssa Pøngjǣrdenlarp Dec 06 '18 at 17:30
  • @WelcomeOverflow - not really , the AM and PM strings are non-standard – pm100 Dec 06 '18 at 17:32
  • `Convert.ToDateTime("6/12/2018 12:00:03 a. m.")` fails and throws an exception, see https://dotnetfiddle.net/FfO76R. In what locale were you parsing? – dbc Dec 06 '18 at 18:45

3 Answers3

5

This is what the tt custom format specifier are for.

var date = "6/01/2018  12:00:03 am";
var x = DateTime.ParseExact(date, "d/MM/yyyy  h:mm:ss tt", CultureInfo.InvariantCulture);

But remember, this tt specifier does not parse a. m. or a.m. strings. If your strings have those, you have to manipulate your strings like removing dots and/or spaces between a and m etc.. It also parse AM and PM as well.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
2

You have to standardize the AM and PM strings first

var dateStr = "6/01/2018  12:00:03 a. m.";

var cleanDate = dateStr.Replace("a. m.", "AM").Replace("p. m.","PM");
var date = DateTime.ParseExact(cleanDate, "d/MM/yyyy  h:mm:ss tt", CultureInfo.InvariantCulture)
pm100
  • 48,078
  • 23
  • 82
  • 145
2

Since a. m. and p. m. are nonstandard designators for AM and PM, you will need to create your own custom DateTimeFormatInfo based on your desired locale (you are using the invariant locale currently) and modify its AMDesignator and PMDesignator properties. Then you can parse using the "tt" format specifier as explained in this answer by Soner Gönül as well as this answer by Complexity, passing the custom DateTimeFormatInfo as the IFormatProvider to DateTime.ParseExact(string s, string format, IFormatProvider provider):

// Construct an invariant DateTimeFormatInfo and modify its AMDesignator and PMDesignator.
// The DateTimeFormat must be cloned since the global instance is read-only.
var formatInfo = (DateTimeFormatInfo)CultureInfo.InvariantCulture.DateTimeFormat.Clone();
formatInfo.AMDesignator = "a. m.";
formatInfo.PMDesignator = "p. m.";

var x = DateTime.ParseExact(date, "d/MM/yyyy  h:mm:ss tt", formatInfo);

For performance reasons you may want to statically cache your DateTimeFormatInfo as shown, e.g., here.

Alternatively, there are several cultures that do use a. m. and p. m. as AM and PM designators, mainly Spanish and Catalan, and your app may be running with one of these cultures as the current culture. You can discover all such cultures as follows:

foreach (var info in CultureInfo.GetCultures(CultureTypes.AllCultures))
{
    if (info.DateTimeFormat.AMDesignator == "a. m." && info.DateTimeFormat.PMDesignator == "p. m.")
    {
        Console.WriteLine("Culture {0} ({1}) has the required AM and PM designators.", info.DisplayName, info.Name);
    }
}

Which outputs

Culture Catalan (ca) has the required AM and PM designators.
Culture Catalan (Andorra) (ca-AD) has the required AM and PM designators.
Culture Catalan (Catalan) (ca-ES) has the required AM and PM designators.
Culture Valencian (Spain) (ca-ES-valencia) has the required AM and PM designators.
Culture Catalan (France) (ca-FR) has the required AM and PM designators.
Culture Catalan (Italy) (ca-IT) has the required AM and PM designators.
Culture Spanish (Equatorial Guinea) (es-GQ) has the required AM and PM designators.
Culture Spanish (Mexico) (es-MX) has the required AM and PM designators.
Culture Spanish (Philippines) (es-PH) has the required AM and PM designators.

And you can examine the AM and PM designators of the current culture by printing to the console:

Console.WriteLine("Current culture AMDesignator=\"{0}\" and  PMDesignator=\"{1}\".",
                  CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator,
                  CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator);

You could parse your date string in any of these cultures and get your desired result:

var formatInfo = CultureInfo.GetCultureInfo("es-MX");

var x = DateTime.ParseExact(date, "d/MM/yyyy  h:mm:ss tt", formatInfo);

And if your user's current culture is one of these cultures, you could pass CultureInfo.CurrentCulture (or CultureInfo.CurrentUICulture if appropriate):

var x = DateTime.ParseExact(date, "d/MM/yyyy  h:mm:ss tt", CultureInfo.CurrentCulture);

Demo fiddle here.

dbc
  • 104,963
  • 20
  • 228
  • 340