Разбор формата DateTime для получения строки формата

Я хотел бы иметь возможность получить строку формата из строки DateTime.

например

"2012-12-08 15:00:00" => "гггг-мм-дд чч: мм: сс"

"2013/30/01 16:00" => "гггг / дд / мм чч: мм"

Это возможно?

4 ответа

Решение

Было бы очень трудно сделать это полностью общим способом, но одним из вариантов было бы извлечь соответствующие DateTimeFormatInfo что вы заинтересованы (используя CultureInfo.DateTimeFormat), извлеките специфичные для культуры образцы из этого (LongDatePattern, LongTimePattern и т. д.), в некоторых случаях соответствующим образом комбинируйте шаблоны ShortDatePattern пространство ShortTimePattern), а затем попробуйте каждый шаблон по очереди, используя DateTime.TryParseExact - не забывая по-прежнему указывать культуру каждый раз, чтобы правильно обрабатывать разделители даты и т. д.

когда DateTime.TryParseExact возвращается true, вы знаете, у вас есть шаблон, который будет анализировать данный текст.

Пример кода - включая пример, где вы ожидаете, что он будет работать, но это не так:

using System;
using System.Collections.Generic;
using System.Globalization;

class Test
{
    static void Main()        
    {
        var us = new CultureInfo("en-US");
        var uk = new CultureInfo("en-GB");
        string text = "07/06/2013 11:22:11";

        // This one fails, as there's no appropriate time format
        Console.WriteLine(GuessPattern(text, us));
        // This one prints dd/MM/yyyy HH:mm:ss
        Console.WriteLine(GuessPattern(text, uk));
    }

    static string GuessPattern(string text, CultureInfo culture)
    {
        foreach (var pattern in GetDateTimePatterns(culture))
        {
            DateTime ignored;
            if (DateTime.TryParseExact(text, pattern, culture,
                                       DateTimeStyles.None, out ignored))
            {
                return pattern;
            }
        }
        return null;
    }

    static IList<string> GetDateTimePatterns(CultureInfo culture)
    {
        var info = culture.DateTimeFormat;
        return new string[]
        {
            info.FullDateTimePattern,
            info.LongDatePattern,
            info.LongTimePattern,
            info.ShortDatePattern,
            info.ShortTimePattern,
            info.MonthDayPattern,
            info.ShortDatePattern + " " + info.LongTimePattern,
            info.ShortDatePattern + " " + info.ShortTimePattern,
            info.YearMonthPattern
            // Consider the sortable pattern, ISO-8601 etc
        };        
    }
} 

Вы можете потенциально жестко закодировать некоторые "дополнительные" форматы даты и времени, которые вы ожидаете работать.

РЕДАКТИРОВАТЬ: Чтобы справиться с неопределенностью, вы могли бы легко сделать GuessPattern вернуть IEnumerable<string> вместо одной строки:

static IEnumerable<string> GuessPatterns(string text, CultureInfo culture)
{
    DateTime ignored;
    return GetDateTimePatterns(culture)
        .Where(pattern => DateTime.TryParseExact(text, pattern, culture,
                                             DateTimeStyles.None, out ignored))
    }
}

У меня была та же идея, что и у Джона Скита, и я решил ее реализовать:

// Helper method
IEnumerable<string> DateTimeFormatPatterns(DateTimeFormatInfo format)
{
    var accessors = new Func<DateTimeFormatInfo, string>[]
    {
        f => f.FullDateTimePattern,
        f => f.LongDatePattern,
        f => f.LongTimePattern,
        f => f.MonthDayPattern,
        f => f.ShortDatePattern,
        f => f.SortableDateTimePattern,
        f => f.UniversalSortableDateTimePattern,
        f => f.YearMonthPattern,
    };

    return accessors.Select(accessor => accessor(format));
}

// The real function
string DetectDateTimeFormat(string date, CultureInfo culture)
{
    DateTime dummy;
    foreach (var pattern in DateTimeFormatPatterns(culture.DateTimeFormat))
    {
        if (DateTime.TryParseExact(date, pattern, culture,
                                   DateTimeStyles.None, out dummy))
        {
            return pattern;
        }
    }

    return null;
}

Здесь есть место для улучшения (например, жестко DateTimeStyles.None не помогает, перегрузка, которая предполагает, что текущая культура также будет полезна), но вы можете использовать ее следующим образом:

var format = DetectDateTimeFormat("2012-12-08 15:00:00",
                                  CultureInfo.CurrentCulture);

Вы можете иметь набор предопределенных форматов, проанализировать дату и посмотреть, пройдет ли она, тогда вы можете получить искомый формат строки.

Обратитесь к ответу, но его в Java - Как получить заданный формат строки даты (шаблон) в Java?

Вы можете попробовать, написав приведенный ниже код, чтобы получить yyyy/dd/MM HH:mm формат.

DateTimeFormatInfo df1 = new DateTimeFormatInfo();
df1.SortTimePattern();

Это дало бы вам то же самое HH:mm формат.

Другие вопросы по тегам