2

I'm currently allowing users to set their preferred DateTime format using full patterns like so:

var formats = System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.GetAllDateTimePatterns('f').ToList();
formats.AddRange(System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.GetAllDateTimePatterns('F'));
formats.AddRange(System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.GetAllDateTimePatterns('g'));
formats.AddRange(System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.GetAllDateTimePatterns('G'));

This produces full pattern strings like this:

dddd, MMMM d, yyyy h:mm tt
dddd, MMMM d, yyyy hh:mm tt
dddd, MMMM d, yyyy H:mm
dddd, MMMM d, yyyy HH:mm
MMMM d, yyyy h:mm tt
dddd, d MMMM, yyyy h:mm:ss tt
M/d/yyyy h:mm tt

There are certain places in the UI where we don't want to show the Time because its irrelevant in context.

Is there a culture aware BCL class that allows me to extract just the Date pattern from a string?

Example api:

var datePattern = System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.GetDatePattern("M/d/yyyy h:mm tt");

Which would result in datePattern being set to:

M/d/yyyy

Update

Based on @SteveWellens comment I realized that Date/Time patterns are not in themselves culture variant which is what was throwing me off. In other words the "h" that represents a placeholder for the hour is always "h" no matter what culture the end user is in. I created a dead simple extension method to get what I wanted. (wish this didn't have to be a string extension though because it clutters intellisense)

public static string GetDatePattern(this string pattern)
{
    // set a default pattern if none is specified
    if (string.IsNullOrWhiteSpace(pattern))
        pattern = System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern;

    var start = pattern.IndexOf("h", StringComparison.InvariantCultureIgnoreCase);
    // cannot find the hour placeholder
    if (start < 0)
        return pattern;
    return pattern.Substring(0, start -1);
}

NOTES: I double checked all the cultures (CultureTypes.AllCultures) and none of the standard date and time patterns start with a time pattern for any of them so this is safe logic to use for standard date and time patterns. Custom patterns are a whole other story.

FYI, the longest standard date and time pattern for any culture is 48 in case you are saving this to a database.

TugboatCaptain
  • 4,150
  • 3
  • 47
  • 79
  • Have you seen this? http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx If so I don't understand the question. – Mike Cheel Jan 23 '14 at 18:53
  • When you say the string is 'culture aware', does that imply that you can convert the string into a DateTime using the appropriate `CultureInfo` argument? If so ([link to technique](http://stackoverflow.com/questions/5590180/how-to-convert-a-datetime-string-to-a-current-culture-datetime-string)), the `d` or `D` option below should work for you. – neontapir Jan 23 '14 at 19:08
  • 1
    I don't think so. It should be easy to do it...find the first h or H, go back one space and you've got it. – Steve Wellens Jan 23 '14 at 19:08
  • @SteveWellens, I think your right. For some reason I incorrectly transposed UI cultures into the actual patterns specifiers themselves. I believe the pattern specifiers used in .Net are always in a specific character set/encoding (utf-16?) – TugboatCaptain Jan 23 '14 at 19:20
  • All strings in .Net are UTF-16. Just hope there isn't some weird pattern that puts the time BEFORE the date. – Steve Wellens Jan 23 '14 at 22:41

1 Answers1

1

I'd be surprised if the framework provided something like this automatically. I can't seem to find anything regarding this.

If the list of datetime formats that you make available to users are under your control (i.e. you don't allow free-form formats), one option would be to create a lookup table from the normal format string to one without the time component, like so:

var mapping = new Dictionary<string, string>() {
    { "dddd, MMMM d, yyyy h:mm tt", "dddd, MMMM d, yyyy" },
    { "dddd, MMMM d, yyyy hh:mm tt", "dddd, MMMM d, yyyy" },
    ...
};

Tedious, but extremely simple, depending on how many formats you allow.

Alternatively, you could opt to create a simple function which tries to remove the time component from the format string. Depending on your goal, this could be a valid option. Datetime format string are designed to be culturally adaptable, if not strictly correct.

Alternatively, simply ask your user to also choose a format for date-only strings.

voithos
  • 68,482
  • 12
  • 101
  • 116