禁止模糊日期

时间:2015-09-01 13:13:13

标签: c# .net vb.net datetime

DateTime.Parse(myString, CultureInfo.InvariantCulture)很乐意解析以下明确的日期(假设当地时区是固定的):

2015-12-31T12:15:00
2015-12-31T12:15:00Z
2015-12-31T12:15:00+01:00
2015-12-31T12:15
2015-12-31
2015-12-31 12:15:00
2015-12-31 12:15:00Z
2015-12-31 12:15:00+01:00
2015-12-31 12:15

这很棒。我喜欢所有的灵活性。不幸的是,它还解析了以下含糊不清的日期:

4.3.2015   // The user intent could be March or April.

我知道我可以使用ParseExact,但是我必须提交一份包含可能提交给我的应用程序的所有明确日期格式的大型列表。

我能否以某种方式禁止含糊不清的日期格式而无需为ParseExact指定每种明确的格式?像DateTime.Parse(myString, IsoCulture)

这样的东西

2 个答案:

答案 0 :(得分:-1)

我认为你不能通过提供单一格式选项来实现这一目标。

这是我的十人入门者,至少可以确保日期部分格式正确:

Public Function ParseUnAmbiguousDate(s As String, ByRef aDateTime As DateTime) As Boolean

    'keep a track of how long the date portion is
    Dim dateLength As Integer = 0
    'there are only two valid date formats in ISO terms yyyy-MM-dd or yyyyMMdd so try these first

    'is it too short?
    If s.Length < 8 Then Return False
    'try the yyyyMMdd format
    If DateTime.TryParseExact(s.Substring(0, 8), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, aDateTime) Then
        dateLength = 8
    End If

    'try the yyyy-MM-dd format if the first option failed
    If dateLength = 0 Then
        'is it too short for this format?
        If s.Length < 12 Then Return False

        If DateTime.TryParseExact(s.Substring(0, 10), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, aDateTime) Then
            dateLength = 10
        End If
    End If

    'if we get here then check we have found a format
    If dateLength = 0 Then Return False

    'now substitue our date for a known one to try and parse the time
    Dim timePortion As Date
    If DateTime.TryParse("2000-01-01" & s.Substring(dateLength), timePortion) Then
        aDateTime = New DateTime(aDateTime.Year, aDateTime.Month, aDateTime.Day, timePortion.Hour, timePortion.Minute, timePortion.Second, timePortion.Kind)
        Return True
    Else
        Return False
    End If

End Function

答案 1 :(得分:-3)

可以使用此扩展程序完成:

using System;
using NUnit.Framework;

namespace UnitTestProject1
{
    [TestFixture]
    public class UnitTest1
    {
        [TestCase("2015-12-31", true)]
        [TestCase("2015-01-01", true)]
        [TestCase("2015-12-31 12:15:00+01:00", true)]
        [TestCase("4.3.2015", false)]
        [TestCase("4.13.2015", true)]
        [TestCase("13.13.2015", false, ExpectedException = typeof(FormatException))]
        public void TestMethod1(string input, bool expected)
        {
            Assert.AreEqual(expected, input.IsDateNotAmbigous());
        }
    }

    public static class Extensions
    {
        public static bool IsDateNotAmbigous(this string stringDateTime)
        {
            DateTime parsed = DateTime.Parse(stringDateTime);
            return parsed.Day == parsed.Month || parsed.Day>12;
        }
    }
}

<强>更新

我认为我必须在这方面与公众达成一致,即如果不了解传入的琴弦文化,这不是一个容易解决的问题。即使我们按照这样的方式迭代所有可用的文化:

    public static bool IsDateNotAmbigous(this string stringDateTime)
    {
        return CultureInfo.GetCultures(CultureTypes.AllCultures).AsParallel().Select(ci =>
        {
            DateTime parsed = default(DateTime);
            bool success = DateTime.TryParse(stringDateTime, ci, DateTimeStyles.AssumeLocal, out parsed);
            bool test = parsed.Day > 12 || parsed.Day == parsed.Month;
            Trace.WriteLine(String.Format("{0,12}:{1,5}:{2,5}:{3:O}", ci.Name, success, test, parsed));
            if (!success)
                return -1;
            if (test)
                return 1;
            return 0;
        }).Where(w=>w>=0).Select(s=>s==1).Aggregate((b, b1) => b || b1);
    }

有些测试不会通过。但也许它会帮助某人为此提出一个优雅的解决方案。

无法停止思考

好的,所以我们无法确切地知道,如果不了解传入的文化,但这会让你更接近:

#region

using System;
using System.Globalization;
using System.Linq;
using NUnit.Framework;

#endregion

namespace UnitTestProject1
{
    [TestFixture]
    public class UnitTest1
    {
        [TestCase("2015-12-31", true)]
        [TestCase("2015-01-01", true)]
        [TestCase("2015-02-01", false)]
        [TestCase("2015-12-31 12:15:00+01:00", true)]
        [TestCase("4.3.2015", false)]
        [TestCase("4.13.2015", true)]
        [TestCase("13.13.2015", null, ExpectedException = typeof (InvalidOperationException))]
        public void TestMethod1(string input, bool expected)
        {
            Assert.AreEqual(input.DateIsLikelyNotAmbigous(), expected);
        }
    }

    public static class Extensions
    {
        public static bool DateIsLikelyNotAmbigous(this string stringDateTime)
        {
            return CultureInfo.GetCultures(CultureTypes.AllCultures).AsParallel().Select(ci =>
            {
                DateTime parsed = default(DateTime);
                bool success = DateTime.TryParse(stringDateTime, ci, DateTimeStyles.AssumeLocal, out parsed);
                if (!success)
                    return -1;
                if (parsed.Day > 12 || parsed.Day == parsed.Month)
                    return 1;
                return 0;
            }).Where(w => w >= 0).Average(a => a) > 0.02;
        }
    }
}

很想听@hvd对此的看法。