我有一个系统从外部源获取信息,然后存储它以便稍后显示。
其中一个数据项是日期。在源系统上,它们具有模糊日期的概念,即不准确到特定日期或有时不精确到一个月。所以我得到格式的日期:
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中有内置的东西吗?我看了一下文化的东西,但这看起来并不合适。
任何帮助都将不胜感激。
答案 0 :(得分:14)
回答你的问题:.NET中没有任何东西可以优雅地处理这个问题。
您的解决方案与我见过的一样有效。您可能希望使用覆盖修饰您的类ToString()方法,该方法将根据DateType适当地呈现您的日期。
以下是其他几个尝试解决此问题的主题:
祝你好运!答案 1 :(得分:6)
当我开始阅读你的问题时,我很快得出结论,答案是实现你自己的FuzzyDate类。瞧,这正是你所做的。
我可以想象您可能希望随着时间的推移添加功能(例如考虑DateType的比较)。
我不相信.NET Framework中会有任何固有的帮助,所以我认为你做的是正确的。
答案 2 :(得分:6)
如果您的数据类型始终处理特定的时间段(即1972年是特定时间段,但7月4日不具体),您可以将数据存储为开始时间跨度。 / p>
这是一个可能的实现:
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";
}
}
答案 3 :(得分:3)
我认为你走的是正确的路线。没有“模糊”日期或部分日期的概念,您需要建立自己的日期。
您可能需要更多构造函数方法,例如
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;
}
希望这有帮助, 凯文
答案 4 :(得分:1)
在我看来,你的方法是正确的。确实.NET DateTime支持多种格式,但我想,鉴于所有这些格式都支持步骤(纳秒)的概念,那么它将与特定的日期和时间相关。
答案 5 :(得分:0)
我会做的另一件事是使用null-able值(或使用-1表示null语义)指示月份和日期以指示收集了哪些数据。然后我会有一个工厂方法,它将采用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枚举,你将失去一些分辨率。
答案 6 :(得分:0)
据我所知,.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
}
答案 7 :(得分:0)
您可以根据日期时间创建自己的结构(用户定义类型),该日期时间允许00表示月份,00表示日期...然后还实现icomparable,这样您就可以对其进行数学/比较。< / p>
http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.icomparable.aspx