user5032790
user5032790

Reputation:

Convert 1st day string to Datetime

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);

Upvotes: 0

Views: 971

Answers (3)

fubo
fubo

Reputation: 45947

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

Upvotes: 1

KozhevnikovDmitry
KozhevnikovDmitry

Reputation: 1720

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.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1500135

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.)

Upvotes: 2

Related Questions