从字符串值中检索可能的DateTime格式列表

时间:2015-09-04 00:04:55

标签: c# datetime nodatime

我希望能够从csv文件中解析日期和/或日期时间值并获取其DateTime格式(或者用Excel术语NumberFormat)。

例如,我想将“2008-06-07 00:00:00.000”传递给一个函数,让它返回类似“yyyy-MM-dd hh:mm:ss.000”的内容。

问题是csv文件中可能有许多可能的日期格式,并且它们未提前知道,因此我不能使用DateTime.TryParseExact(),因为它要求您知道DateTime格式字符串之前是时候测试它是否适用于特定值。

通过了解日期格式,我可以将其设置为Excel中的自定义数字格式并输入值,它将与csv文件的文本完全相同,同时还能够在csv文件的文本中使用它Excel公式。

当然可能存在歧义,所以理想情况下,获取列表可能的日期格式然后检查多个日期以通过查看可能日期格式列表的交叉点来删除一些选项会很好。 / p>

我刚刚发现了NodaTime API,看起来它可能会做这样的事情,但我还没有看到实现这一点的示例代码,因为大多数关于类似查询的问题被要求用于早期版本它似乎没有被支持。

这样做的任何其他方法也将非常受欢迎。

修改

我认为,正如Jon Skeet所说,这样做的唯一方法是列出常见模式并对其进行测试。 通过执行以下操作,我可以获得所有培养日期时间模式的集合。但是,此列表将缺少一些可能常用的自定义模式。例如(我不知道这是否常用)yyyy / dd / MM不在列表中。

    private static HashSet<string> _patterns; 
    public static HashSet<string> AllCulturedDateTimePatterns
    {
        get
        {
            if (_patterns != null)
                return _patterns;

            _patterns = new HashSet<string>();
            var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
            foreach (var culture in cultures)
            {
                _patterns.UnionWith(culture.DateTimeFormat.GetAllDateTimePatterns());
            }
            return _patterns;
        }
    }

2 个答案:

答案 0 :(得分:3)

没有“所有可能的日期格式”之类的东西。格式"'Year:' yyyy 'Month:' MM 'Day:' dd"将是有效的,但非常不寻常,例如。 Noda Time在这里提供的任何东西都不会特别有用。我怀疑你需要创建自己所见过的所有日期/时间格式的列表 - 然后你可以在Noda Time中为每种格式创建一个模式,并尝试解析它以检查结果是否成功,或者在BCL中使用DateTime.TryParseExact。例如:

BCL版

var allFormats = new List<string>
{
    "yyyy-MM-dd HH:mm:ss",
    "dd/MM/yyyy HH:mm:ss",
    "MM/dd/yyyy HH:mm:ss",
    // etc
};

DateTime ignored;
var matchingFormats = allFormats
    .Where(format => DateTime.TryParseExact(text, format, CultureInfo.InvariantCulture,
                                            DateTimeStyles.None, out ignored))
    .ToList();

Noda Time版本

var allFormats = ...; // As before
var allPatterns = allFormats
    .Select(format => LocalDateTimePattern.CreateWithInvariantCulture(format))
    .ToList();

var matchingPatterns = allPatterns.Where(pattern => pattern.Parse(text).Success)
                                  .ToList();

请注意,IIRC,我们目前不会从LocalDateTimePattern(或任何其他模式)公开底层格式字符串。我们可以这样做,但我们现在不会......

答案 1 :(得分:1)

您必须对传入数据有标准。没有这个,你会让自己疯狂。即使你用vba宏清理它(我建议你不管怎么做),如果你盲目地接受阳光下没有接受规则的每种格式,数据永远不会是正确的。

您可以做的一件事(使用您的vba宏)输入数据源(应该具有已知的日期格式)并根据该格式进行清理。例如,网站example.com以日期格式MM / dd / yyyy为您提供.csv,您的宏应该足够聪明,知道它的格式不是dd / MM / yyyy。

如果您熟悉Excel vba,这对您来说应该是有意义的。如果您不欢迎使用Excel vba进行编程!