DRY string formatting
Asked Answered
C

4

7

What is an elegant way to pull out common formats (e.g. datetime) for string.format into accessible constants?

Ideally I would like to do something like the following, but I get the below error when I try to use this code.

var now = DateTime.Now;
var format = "yyyy-MM-dd";
Console.WriteLine(string.Format("The date is {1:{0}}", format, now));

[System.FormatException: Input string was not in a correct format.] at Program.Main(): line 9

The reasoning behind this is that certain API's require a specific datetime format. I would like to be able to reference a single place to get that format, such that all or none of the calls will work.

I realize that the following will work, but it doesn't seem very elegant.

Console.WriteLine(string.Format("The date is {1:" + format + "}", format, now));
Cristionna answered 31/3, 2014 at 19:20 Comment(2)
Do you have a limited list of Date formats you need to support?Eagre
@YuriyRozhovetskiy for the time being yes, though it would take some time to enumerate all of them.Cristionna
L
2

You could go an app constant route - a static class that holds your format strings.

namespace App.Framework {
    public static class AppConstant {
        public static readonly string DisplayDateShort = "MM/dd/yyyy";
    }
}

As far as your example goes, it's kind of flawed; you want to call ToString() on your DateTime value.

Console.WriteLine(now.ToString(AppConstant.DisplayDateShort));

Leddy answered 31/3, 2014 at 19:28 Comment(2)
So you are proposing the following, Console.WriteLine(string.Format("The date is {0}", now.ToString(format)));, correct?Cristionna
I have a FormatWith string extension method that I use to cut down on the noise a bit ("The date is {0}".FormatWith(now.ToString(format))), but otherwise, yes.Leddy
P
2

You can find all the used format strings under DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns().

Afterwards you can individually try to parse your input data with each value and see which on returns true (see: DateTime.TryParseExact()).

Console.WriteLine (DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns());

enter image description here

Sample code:

void Main()
{
    var now = DateTime.Now.ToString();

    foreach(var format in DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns()){
        DateTime result;
        if(DateTime.TryParseExact(now, format, CultureInfo.CurrentCulture, DateTimeStyles.None, out result)){
            Console.WriteLine(string.Format("The date is {0}, the format is: {1}", result, format));
        }
    }
}

enter image description here

Phylissphyll answered 31/3, 2014 at 19:27 Comment(1)
Thank you for sharing this, as I was unaware that you could do this. In my particular case, the datetime is in the correct format.Cristionna
L
2

You could go an app constant route - a static class that holds your format strings.

namespace App.Framework {
    public static class AppConstant {
        public static readonly string DisplayDateShort = "MM/dd/yyyy";
    }
}

As far as your example goes, it's kind of flawed; you want to call ToString() on your DateTime value.

Console.WriteLine(now.ToString(AppConstant.DisplayDateShort));

Leddy answered 31/3, 2014 at 19:28 Comment(2)
So you are proposing the following, Console.WriteLine(string.Format("The date is {0}", now.ToString(format)));, correct?Cristionna
I have a FormatWith string extension method that I use to cut down on the noise a bit ("The date is {0}".FormatWith(now.ToString(format))), but otherwise, yes.Leddy
N
1

You could consider pushing the format into an extension method that could be consumed as needed, i.e.:

public static class DateExt
{
    public static string FormatAsSomething( this DateTime dt )
    {
        string format = "yyyy-MM-dd";
        string result = dt.ToString( format );
        return result;
    }
}

And then:

var now = DateTime.Now;
Console.WriteLine( "The date is {0}", now.FormatAsSomething() );

Whenever the format needs to be updated, simply update the extension method.

Nobles answered 31/3, 2014 at 19:35 Comment(0)
E
0

You can use custom format provider for DateTime values:

static void Main(string[] args)
{
    var now = DateTime.Now;

    var str = string.Format(new MyDateFormatter(), "The date is {0}", now);

    Console.WriteLine(str);

    MyDateFormatter.DefaultDateFormat = "dd-MM-yyyy HH:mm";

    str = string.Format(new MyDateFormatter(), "The date is {0}", now);

    Console.WriteLine(str);
}

public class MyDateFormatter: IFormatProvider, ICustomFormatter
{
    public static string DefaultDateFormat = "yyyy-MM-dd";

    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;

        return null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        // Check whether this is an appropriate callback              
        if (!this.Equals(formatProvider))
            return null;

        var argFormat = "{0:" + (arg is DateTime ? DefaultDateFormat : string.Empty) + "}";

        return string.Format(argFormat, arg);
    }
}
Eagre answered 31/3, 2014 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.