C# 如何处理.Net中的模糊日期

C# 如何处理.Net中的模糊日期,c#,.net,datetime,C#,.net,Datetime,我有一个系统,从外部来源获取信息,然后将其存储起来,以便以后显示 其中一个数据项是日期。在源系统上,他们有模糊日期的概念,即不精确到特定日期,有时也不精确到一个月。因此,我以以下格式获取日期: dd/mm/yyyy mm/yyyy yyyy 我可以将这些解析为DateTime对象并使用它们,但在以后渲染时,我需要能够确定日期的准确性,因为解析“2010”将导致日期为“01/01/2010”。我只想显示年份,所以需要知道它的原始准确性 我已经模拟了一个快速类来处理这个问题: public cla

我有一个系统,从外部来源获取信息,然后将其存储起来,以便以后显示

其中一个数据项是日期。在源系统上,他们有模糊日期的概念,即不精确到特定日期,有时也不精确到一个月。因此,我以以下格式获取日期:

dd/mm/yyyy
mm/yyyy
yyyy
我可以将这些解析为DateTime对象并使用它们,但在以后渲染时,我需要能够确定日期的准确性,因为解析“2010”将导致日期为“01/01/2010”。我只想显示年份,所以需要知道它的原始准确性

我已经模拟了一个快速类来处理这个问题:

public class FuzzyDate
{
    public DateTime Date { get; set; }
    public DateType Type { get; set; }
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}
这将为我做这项工作,我可以在解析中做一些事情来处理它,但我觉得这可能是一个非常常见的问题,并且可能存在一个更干净的解决方案

Net中是否内置了这样做的功能?我看了一下文化方面的东西,但这似乎不太正确


任何帮助都将不胜感激。

当我开始阅读您的问题时,我迅速得出结论,答案是实现您自己的FuzzyDate类。瞧,这正是你所做的

我可以想象,随着时间的推移,您可能会希望为其添加功能(例如考虑日期类型的比较)


我不相信在.NET框架中有任何东西能从本质上帮助您,因此我认为您做的是正确的。

在我看来,您的方法是正确的。NET DateTime确实支持多种格式,但我想,如果所有格式都支持步长(纳秒)的概念,那么它们将与特定的日期和时间相关。

回答您的问题:在.NET中没有任何内置格式可以优雅地处理此问题

你的解决方案和我见过的一样有效。您可能希望通过重写ToString()方法来修饰类,该方法将根据日期类型适当地呈现日期

以下是尝试解决此问题的两个其他线程:


祝你好运

我要做的另一件事是在月份和日期使用可空值(或使用-1表示空语义),以指示收集了哪些数据。然后我将有一个工厂方法,它将接受DateType参数并返回DateTime。如果只有年份可用,并且客户端代码试图创建DateType.DayMonthYear,则此方法将引发和异常

public class FuzzyDate
{
    int _year;
    int? _month;
    int? _day;

    public DateTime Date { get; set; }
    public DateType Type { get; set; }

    public DateTime GetDateTime(DateType dateType) { // ...
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

这似乎有点过头了,但这种方法将显式存储原始数据,并且在请求时仅表示“伪造的”DateTime对象。如果将DateTime对象与DateType枚举一起在内部持久化,则会丢失一些分辨率。

据我所知,.NET中没有内置任何解决方案,我会选择基于可空值的解决方案,类似这样的解决方案

public class FuzzyDate
{
    private int Year;
    private int? Month;
    private int? Day;

    public FuzzyDate(int Year, int? Month, int? Day)
    {
        this.Year = Year;
        this.Month = Month;
        this.Day = Day;
    }

    public DateType DateType
    {
        get
        {
            if(Day.HasValue && Month.HasValue)
            {
                return DateType.DayMonthYear;
            }
            else if(Month.HasValue)
            {
                return DateType.MonthYear;
            }
            else
            {
                return DateType.Year;
            }
        }
    }

    public DateTime Date
    {
        get
        {
            return new DateTime(Year, Month.GetValueOrDefault(1), Day.GetValueOrDefault(1));
        }
    }
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

您可以根据datetime创建自己的结构(用户定义类型),该日期时间允许月为00,日为00。。。然后还实现了icomparable,这样就可以对它进行数学/比较了



我认为你走的路线是对的。没有“模糊”日期或部分日期的概念,您需要构建自己的日期

例如,您可能需要更多的构造函数方法

public FuzzyDate(int year)
{
   Date = new DateTime(year,1,1); // 1 Jan yy
   Type = DateType.Year;
}

public FuzzyDate(int year, int month)
{
   Date = new DateTime(year, month, 1); // 1 mm yy
   Type = DateType.MonthYear;
}

public FuzzyDate(int year, int month, int day)
{
   Date = new DateTime(year, month, day); // dd mm yy
   Type = DateType.DayMonthYear;
}
希望这有帮助,
Kevin

如果您的数据类型总是处理特定的时间段(即1972年是特定的时间段,但7月4日不是特定的),则可以将数据存储为开始时间和时间跨度

  • 如果您的日期为“1972”,则开始日期为19720101,时间跨度为366天
  • 如果您的日期为“1972年7月”,则开始日期为19720701,时间跨度为31天
  • 如果您的日期为“1972年7月4日”,则开始日期为19720704,时间跨度为1天
下面是一个可能的实现:

public struct VagueDate
{
    DateTime start, end;

    public DateTime Start { get { return start; } }
    public DateTime End { get { return end; } }
    public TimeSpan Span { get { return end - start; } }

    public VagueDate(string Date)
    {
        if (DateTime.TryParseExact(Date, "yyyy", null, 0, out start))
            end = start.AddYears(1);
        else if (DateTime.TryParseExact(Date, "MM/yyyy", null, 0, out start))
            end = start.AddMonths(1);
        else if (DateTime.TryParseExact(Date, "dd/MM/yyyy", null, 0, out start))
            end = start.AddDays(1);
        else
            throw new ArgumentException("Invalid format", "Date");
    }

    public override string ToString()
    {
        return Start.ToString("dd/MM/yyyy") + " plus " + Span.TotalDays + " days";
    }
}

我不知道有什么内置的支持这一点。我建议您看看NodaTime()——虽然我在浏览该源代码时没有看到任何专门解决您问题的方法,但您可能会这样做。还考虑存储字符串格式表示(或引用格式)而不是枚举值的可能性——这允许您在不重新编译和重新部署的情况下更改新的日期存储格式。可能的副本我有一段时间刻画有一年和一天但没有月份。我更喜欢OP的日期类型方法。在这方面,我可以更容易地想象想要存储没有年份的月份和日期:例如,存储一个人的生日而不知道他们的年龄。这里的“天”是指月份中的某一天,没有它就没有任何意义。@Neil:OP的方法很好。我关心的是显式存储捕获时的数据状态,一旦将标志附加到被攻击的日期时间值上,数据就会丢失。@djacobson:模糊日期问题实际上在许多域中都很常见。例如,发展中国家的人通常只知道自己的出生年份,而不知道月份或日期。有时他们甚至不知道这一点,必须记录近似值。在这种情况下,最好使用带有布尔标志的模糊日期对象存储额外的信息,例如近似值和GovernmentIdValidated。。。