0

I'm looking for a way to be able to convert a date string like this:

"1st Oct 2018" => 2018-10-01

Or this:

"10th Mar 2015" => 2015-03-10

To it's equivalent string in the format yyyy mm dd. I have tried the following code, but no luck:

DateTime dt = DateTime.ParseExact(stringDate, "yyyy mm dd", CultureInfo.InvariantCulture);
  • 1
    do you see the gap between `10th Mar 2015` and `"yyyy mm dd"` – fubo Sep 03 '18 at 08:01
  • 1
    "yyyy mm dd" isn't a target format, it's the current format of the date. DateTime objects do not have any formatting themselves, and merely format the date when it's converted to a string, either through `ToString()` (or similar), or through the debugger display. – ProgrammingLlama Sep 03 '18 at 08:02
  • 2
    [Take a look at this](https://stackoverflow.com/questions/17710561/parse-very-long-date-format-to-datetime-in-c-sharp) - you need to remove the "dddd" part of course. – ProgrammingLlama Sep 03 '18 at 08:04
  • 1
    I think you have to remove the “st” “nd” “th” with a function, because I have read another question with the opposite problem and there is no built-in function in the datetime class – Andrea Bellizzi Sep 03 '18 at 08:05

3 Answers3

3

Just in addition to great answer from Daisy:

[TestCase("15th Oct 2018")]
[TestCase("1st Oct 2018")]
[TestCase("2nd Oct 2018")]
[TestCase("3rd Oct 2018")]
[TestCase("3d Oct 2018")]
public void Action(string dateStr)
{
    // Act
    var dt = DateTime.ParseExact(Regex.Replace(dateStr, "(th|st|nd|rd|d)", ""), "d MMM yyyy", CultureInfo.CurrentCulture);

    //Assert
    Console.WriteLine(dt);
}

UPD: added great suggestions from Dmitry Bychenko.

KozhevnikovDmitry
  • 1,660
  • 12
  • 27
2

A DateTime value doesn't have a format - it's just a value. (Just like an int isn't inherently decimal or hex - you choose how to format it when you convert it to a string, and the default is to use decimal.)

The string you're passing into DateTime.ParseExact is the expected input format - and your strings don't have the format "yyyy mm dd". (Note that in date/time format strings, "mm" means minutes, so you'd want "MM" instead of "mm" anyway... but that won't help here.)

Your date format is nearly "d MMM yyyy" (day, short month name, year) using English month names - but the problem is the ordinal part ("st", "nd", "th"). As far as I know there's no simple way of handling that with DateTime.ParseExact. Instead, I'd probably use a regular expression or simple string replacement to remove the ordinal part, so that you do have a string in the format "d MMM yyyy" and then parse that.

For the string replacement part, the answers to this question are appropriate. So here's a complete example using your sample data:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        Console.WriteLine(ParseWithOrdinals("10th Mar 2015"));
        Console.WriteLine(ParseWithOrdinals("1st Oct 2018"));
    }

    private static DateTime ParseWithOrdinals(string input) =>
        DateTime.ParseExact(
            RemoveOrdinals(input), // Text to parse
            "d MMM yyyy",          // Format of text
            CultureInfo.InvariantCulture); // Expect English month names, Gregorian calendar


    // From https://stackoverflow.com/questions/17710561
    private static string RemoveOrdinals(string input) =>
        input
            .Replace("0th", "0")
            .Replace("1st", "1")
            .Replace("2nd", "2")
            .Replace("3rd", "3")
            .Replace("11th", "11") // Need to handle these separately...
            .Replace("12th", "12")
            .Replace("13th", "13")
            .Replace("4th", "4")
            .Replace("5th", "5")
            .Replace("6th", "6")
            .Replace("7th", "7")
            .Replace("8th", "8")
            .Replace("9th", "9");
}

(Note that I haven't formatted the result as yyyy-MM-dd in the output, so you'll get your local date/time format.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks. How can I get a format like 2018-10-01 in output? Can you please consider this as well? –  Sep 03 '18 at 08:12
  • @J.P: You'd then want to look at how to format a `DateTime` to a string, which is a different matter. https://stackoverflow.com/questions/114983 is a good starting point. – Jon Skeet Sep 03 '18 at 08:31
  • @fubo: You can escape *specific* characters; you can't write a pattern that says "The next character is s or t" for example. – Jon Skeet Sep 03 '18 at 08:32
1

There is also a native approach without string remove / replace / Regex

If you know the characters, you can escape them with the ' character inside the date pattern. So "15th Oct 2018" works for this pattern "d'th' MMM yyyy"

Now there are "st","nd","rd","th" so you can try each of them and chose the working one.

Into the overload of TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime) you can pass a range of allowable formats.

string input = "15th Oct 2018";
DateTime result = DateTime.Now;
string[] patterns = { "d'st' MMM yyyy", "d'nd' MMM yyyy", "d'rd' MMM yyyy", "d'th' MMM yyyy"};
bool success = DateTime.TryParseExact(input, patterns, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
if (success)
    Console.WriteLine(result.ToString("yyyy-MM-dd"));

https://dotnetfiddle.net/H8ulyo

fubo
  • 44,811
  • 17
  • 103
  • 137