我应该制作一个DateRange对象吗?

问题描述:

我的一些领域对象包含日期范围为一对的开始和结束日期属性:我应该制作一个DateRange对象吗?

public class Period { 
    public DateTime EffectiveDate { get; set; } 
    public DateTime ThroughDate { get; set; } 
} 

public class Timeline { 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
} 

而且我发现自己用了很多这样的:

abstract public int Foo(DateTime startDate, DateTime endDate); 
abstract public decimal Bar(DateTime startDate, DateTime endDate); 
abstract public ICollection<C5.Rec<DateTime, DateTime>> FooBar(DateTime startDate, DateTime endDate); 

最后一个让我奇怪...我应该实现一个DateRange类吗?我不知道BCL中有一个人。

根据我的经验,使对象层次更深往往使事情复杂化。这些对象确实发送到ReportViewer控件显示的RDLC报表,但这是次要的。我会将视角转向模型,而不是相反。我们不依赖于属性名称,不过,愿意与像妥协:结束日期开始日期之后到来的

public class DateRange { 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
} 

Period p = new Period(); 
DateTime t = p.EffectiveDateRange.StartDate; 

一个日期范围类的好处是集中验证和这将简化我的方法签名:

abstract public int Foo(DateRange dateRange); 
abstract public decimal Bar(DateRange dateRange); 
abstract public ICollection<DateRange> FooBar(DateRange dateRange); 

我只是不知道,一类DATERANGE不会得到我到超过其价值的麻烦。意见?

旁边的问题:我错过了BCL某处的通用通用元组类吗?我知道在各种命名空间中有一些非常特殊的东西。使用C5类型污染我的公共领域方法签名感觉非常非常肮脏。

+0

我绝对认为DateRange类可以提供帮助。我开始为后面一段时间写下基础:http://www.adamjamesnaylor.com/2012/11/04/C-DateRange-Class.aspx – 2012-11-07 15:38:39

+0

@AdamNaylor:您的链接似乎已经停止...... – testing 2016-01-11 15:57:20

不,你没有错过一个通用类。

我有一个Range类型MiscUtil您可能会感兴趣 - 它肯定会使简单的DateTime操作。参考Marc的回答,我不记得这是一个结构还是一个类 - 当然欢迎您改变它。

很高兴,易步,由于马克的仿制药有心计(假设你使用.NET 3.5,至少 - 这是可行的,2。0但目前不支持);

Range<DateTime> range = 19.June(1976).To(DateTime.Today); 

foreach (DateTime date in range.Step(1.Days()) 
{ 
    // I was alive in this day 
} 

(这也是使用大量的扩展方法 - 测试不是生产更多有用)

为了解决马克的回答其他问题,Noda Time一定能表达日期的概念比.NET API更合适,但目前我们没有任何类似的范围......虽然这是一个好主意 - 我已经添加了feature request

+0

对不起,如果我误解了野田时间 - 这看起来很适合那些对时间感兴趣的人。 – 2009-12-04 08:04:37

+0

不,这很好 - 如果你没有提到它,我不确定我是否想过为该项目添加一个功能请求:)我认为这是一个相当普遍的要求 - 棘手的一点是工作需要什么来适应人们会需要的各种调整! – 2009-12-04 08:10:10

+9

有趣的语法。 – 2009-12-04 08:15:22

如果你做了很多日期的工作,是的 - 一个范围可以很方便。这实际上就是其中一种很罕见的情况,其中您应该将编写为struct(不可变)的。但是,请注意,“野田时间”可能会给你所有这些和更多(当它完成时)。我之前做过调度软件;我有几个这样的结构(对于稍微不同的工作)。

请注意,这没有一个方便的BCL构造。

此外 - 想想你有一个范围时,你可以集中所有美好的方法(和可能的运营商); “包含”(另一个范围的日期时间?包括/不包括限制?),“相交”,偏移量(时间跨度)等。确定具有处理它的类型的情况。请注意,在ORM级别,如果您的ORM支持复合值,这会更容易一些 - 我相信NHibernate可以,也可能是EF 4.0。

+0

哦,是的,野田。等待它...... – 2009-12-04 08:01:37

+0

鉴于这是一个重构,以更好地处理日期和范围的操作,我想它是有道理的,给它一个类。 我只希望我在这个项目上使用NHibernate。如果我自己这么说,那么所有这些小时都会写得相当不错,但相比之下,DAL却显得苍白无力。下一个项目,但。我现在正在玩它来获取它的窍门。 – 2009-12-04 08:22:41

我不知道任何本地.NET类的DATERANGE性质。最接近的可能是DateTime + TimeSpan或DateTime/DateTime组合。

我想你想要的是相当合理的。

正如马克和乔恩已经提到的那样,我会将它创建为一个值类型,它是不可变的。我会选择将它作为一个结构来实现,并实现IEquatable和IComparable接口。

当使用像NHibernate这样的ORM时,您将能够在表示实体的表格中存储值类型。

+0

因此,让DateRange子对象应该不会很困难,但使用NHibernate(Fluent)保持开始和结束日期列的平坦表结构?我不这么认为,但事先知道是很好的。 – 2009-12-04 08:44:16

+0

你可以实现你的DateRange作为一个值对象,并在NHibernate中用它作为'组件'。 然后,你确实可以保持平坦的表结构与开始和结束日期列。 – 2009-12-04 08:49:30

在.NET 4.0或更高版本中,Tuple <>类型被添加来处理多个值。

使用元组类型,您可以即时定义自己的值组合。你的问题是非常普遍的,并且与函数想要返回多个值时类似。以前,您只能使用变量或为函数的响应创建一个新类。

Tuple<DateTime, DateTime> dateRange = 
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now); 

无论你走哪条路线,我都认为你确实采取了正确的做法。你给予两个日期配对在一起的真正意义。这是自我记录代码,最好的方式就是在代码结构中。