我有一个系统,它从外部源获取信息,然后存储它以供以后显示。
其中一个数据项是日期。在源系统中,它们有一个模糊日期的概念,即不准确到特定的日子或有时也不准确到一个月。所以我得到的日期格式是:
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来做这个?我看了一下文化方面的东西,但好像不太对。
回答你的问题:. net中没有任何内置的东西可以优雅地处理这个问题。
你的解决方案和我所见过的一样有效。您可能希望用ToString()方法的重写来修饰您的类,该方法将根据DateType适当地呈现日期。下面是其他几个尝试解决这个问题的线程:
不完整日期策略
实现"部分日期"对象
祝你好运!
如果您的数据类型总是处理特定的时间段(即1972年是特定的时间段,但7月4日不是特定的),您可以将数据存储为开始时间和时间跨度。
- 如果你的日期是"1972",那么开始日期就是19720101,时间跨度就是366天。
- 如果您的日期为"07/1972",则开始日期为19720701,时间跨度为31天。
- 如果你的日期是"04/07/1972",那么开始日期将是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";
}
}
当我开始阅读您的问题时,我很快得出结论,答案是实现您自己的FuzzyDate类。你瞧,这正是你所做的。
我可以想象您可能希望随着时间的推移添加功能(例如考虑到DateType的比较)。
我不相信在。net框架中有什么本质上能帮助你的,所以我认为你在做正确的事情。
我认为你走的路是对的。没有"模糊"日期或部分日期的概念,您需要建立自己的日期。
您可能需要更多的构造函数方法,例如
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;
}
希望这有帮助,凯文
在我看来你的方法是对的。. net DateTime确实支持多种格式,但我想,鉴于所有这些格式都支持一个步骤(纳秒)的概念,那么将与特定的日期和时间相关。
我要做的一件事是使用可为空的值(或使用-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 enum,就会失去一些分辨率。
据我所知,. 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,这样你就可以在上面做数学/比较了。
http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.icomparable.aspx