解析时间、日期/时间或日期

5
我希望能解析一个包含时间、日期和时间或只有日期的输入字符串,并且我需要知道哪些部分包含在输入字符串中。
解析实际值并不是问题:
var dt1 = DateTime.Parse("10:00:00", CultureInfo.CurrentCulture);
var dt2 = DateTime.Parse("10pm", CultureInfo.CurrentCulture);
var dt3 = DateTime.Parse("01/02/2014", CultureInfo.CurrentCulture);
var dt4 = DateTime.Parse("01/02/2014 10:00:00", CultureInfo.CurrentCulture);

所有这些都可以成功解析,就像你期望的那样。

然而,如果没有提供日期元素,DateTime.Parse会自动将当前日期添加到时间中。因此,如果今天是2014年1月1日,则DateTime.Parse("10pm")实际上返回一个设置为2014年1月1日10:00:00的DateTime对象。

另外,如果我解析一个没有时间元素的输入字符串,那么DateTime.Parse会假定时间为00:00:00。

因此,在解析完成后,仅通过检查生成的DateTime对象,我无法确定原始输入字符串是否指定了日期和时间,仅指定了日期或仅指定了时间。

我可以使用简单的正则表达式查找标准时间模式,例如^\d\d:\d\d$,但我不想假设所有文化都使用相同的模式来指定时间。

如何在不使用某些可能仅适用于某些文化的模糊正则表达式的情况下,强大地检测出原始输入字符串中提供的日期和时间元素?


好的,它被命名为DateTime - Steve
我还能用什么来做这个? - BG100
1
您想允许任何有效格式,还是只允许某些特定格式? - Jon
@scheien:用户可以在我的应用程序中输入时间、日期/时间或日期。应用程序需要知道输入了哪些元素,以便知道如何处理日期。 - BG100
@Steve:谢谢,我会研究一下...但如果可以避免的话,我宁愿不在我的项目中添加额外的依赖。 - BG100
显示剩余2条评论
1个回答

5
您可以使用带有DateTimeStyles.NoCurrentDateDefault参数的DateTime.Parse方法,这样可以避免使用当前日期:
CultureInfo culture = CultureInfo.InvariantCulture;

var dt1 = DateTime.Parse("10:00:00", culture, DateTimeStyles.NoCurrentDateDefault);
var dt2 = DateTime.Parse("10pm", culture, DateTimeStyles.NoCurrentDateDefault);
var dt3 = DateTime.Parse("01/02/2014", culture, DateTimeStyles.NoCurrentDateDefault);
var dt4 = DateTime.Parse("01/02/2014 10:00:00", culture, DateTimeStyles.NoCurrentDateDefault);
// problem, is this a date only or a date+time?
var dt5 = DateTime.Parse("01/02/2014 00:00:00", culture, DateTimeStyles.NoCurrentDateDefault);

现在是1年。这样你至少可以只识别时间。你仍然需要解决区分没有时间和午夜日期时间的问题。

所以,这可能已经足够了:

bool dt1TimeOnly, dt1DateOnly, dt1DateAndTime;
dt1TimeOnly = dt1.Year == 1;
dt1DateOnly = !dt1TimeOnly && dt1.TimeOfDay == TimeSpan.FromHours(0);
dt1DateAndTime = !dt1TimeOnly && !dt1DateOnly;

所以,唯一确定输入的方法是提供所有支持的格式,并对每个格式使用 DateTime.TryParseExact

例如,使用此枚举:

public enum DateTimeType
{ 
    Date,
    Time,
    DateTime,
    Unknown
}

并且这个方法:

public DateTimeType GetDateTimeType(string input, CultureInfo culture, out DateTime parsedDate)
{ 
   if(culture == null) culture = CultureInfo.CurrentCulture;
   var supportedFormats = new[] { 
        new{ Pattern = culture.DateTimeFormat.ShortDatePattern, Type = DateTimeType.Date },
        new{ Pattern = culture.DateTimeFormat.ShortTimePattern, Type = DateTimeType.Time },
        new{ Pattern = culture.DateTimeFormat.LongDatePattern, Type  = DateTimeType.Date },
        new{ Pattern = culture.DateTimeFormat.LongTimePattern, Type  = DateTimeType.Time },
        new{ Pattern = "hhtt", Type = DateTimeType.Time},
        new{ 
            Pattern = culture.DateTimeFormat.ShortDatePattern + " " + culture.DateTimeFormat.LongTimePattern, 
            Type = DateTimeType.DateTime
        }
    };

    foreach(var fi in supportedFormats)
    {
        DateTime dt;
        if (DateTime.TryParseExact(input, fi.Pattern, culture, DateTimeStyles.NoCurrentDateDefault, out dt))
        {
            parsedDate = dt;
            return fi.Type;
        }
    }
    parsedDate = default(DateTime);
    return DateTimeType.Unknown;
}

现在这将产生正确的日期和DateTimeTypes:
DateTime dt1;
DateTimeType type1 = GetDateTimeType("10:00:00", culture, out dt1);
DateTime dt2;
DateTimeType type2 = GetDateTimeType("10pm", culture, out dt2);
DateTime dt3;
DateTimeType type3 = GetDateTimeType("01/02/2014", culture, out dt3);
DateTime dt4;
DateTimeType type4 = GetDateTimeType("01/02/2014 10:00:00", culture, out dt4);
DateTime dt5;
DateTimeType type5 = GetDateTimeType("01/02/2014 00:00:00", culture, out dt5);

这太完美了...我没有注意到DateTimeStyles.NoCurrentDateDefault选项,这正是我需要检测仅时间输入的。我认为我也可以摆脱仅日期午夜部分...所以感谢您的帮助! - BG100
@BG100:请注意,我已经添加了一个示例,展示如何解决“日期”和“时间”的问题。 - Tim Schmelter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接