业务日期计算






4.49/5 (21投票s)
2005年2月4日
4分钟阅读

170272

2796
本文演示了一种使用 .NET Framework 库标准功能进行业务日期计算的简单方法。
引言
在许多情况下,开发人员都需要进行业务日期的计算和操作。常见的任务通常包括:
- 从当前日期计算下一个工作日。
- 从当前日期计算上一个工作日。
- 从当前日期计算未来或过去一段时间(以工作日为单位)的日期。
- 检查当前日期是否为工作日或节假日等。
从形式上讲,工作日集是日历日的一个子集,不包括周末和节假日。工作日和工作周期常用于定义与业务协议相关的日期,因此“**工作日**”这个术语非常流行且被广泛使用。
因此,拥有一个标准的处理工作日的方法似乎非常有益。
本文介绍的 `XDateTime` C# 类是一个应用类,它提供了业务日期操作和计算的基本功能。
目的
通常,**Microsoft .NET Framework Library** 已经包含了 `DateTime` 类,它提供了大量的日期操作功能。但是,如前所述,它没有工作日计算的功能。因此,`XDateTime` 类的基本思想不是重复标准 `DateTime` 中已有的功能,而是扩展其功能以涵盖工作日操作。
这就是 `XDateTime` 的用途。当您需要比 Microsoft .NET Framework 标准 `System.DateTime` 类型提供的**额外**的**工作日操作**功能时,请使用 `XDateTime` 类。`XDateTime` 类**不重复** `System.DateTime` 类型中已有的任何功能。因此,**没有理由****替代** `System.DateTime` 来使用 `XDateTime`。请将它们**一起使用**,以扩展 `System.DateTime` 类型的现有功能。
基本方法
基本上,`XDateTime` 是标准 `DateTime` 的一个*包装器*。`XDateTime` 包含一个 `DateTime` 类型的实例作为私有的类成员变量,并几乎所有操作都使用这个私有变量。所有处理工作日的功能都作为几个公共方法公开。还提供了一些属性用于辅助目的。
主要计算
事实上,我们只需要执行两个基本计算:从给定日期计算下一个工作日,以及上一个工作日。为了从给定日期计算任意工作日,我们可以根据需要重复上述基本计算。
这样,计算工作日实际上意味着沿着时间轴向前或向后连续移动,步长为一天,并跳过周末和节假日。
因此,工作日计算的基石是确切地知道哪些节假日应从日历日期集中排除。因此,`XDateTime` 包含一个特殊方法,用于初始化用于计算的节假日列表。
认识 XDateTime
最后,是时候仔细看看 `XDateTime` 类本身了。您可以从上面提供的压缩版 Visual Studio .NET 解决方案中获取完整的 `XDateTime` 代码。在这里,我们只考虑 `XDateTime` 实现中的关键部分,这些部分证明了基本假设。
成员变量
`XDateTime` 包含几个用于计算的私有成员变量
public enum XDateTimeType { Calendar=0, Business=1 };
public class XDateTime
{
private DateTime _date;
private XDateTimeType _type;
private Hashtable _holidays;
...
}
在这里,我定义了一个 `XDateTimeType` 枚举,并使用标准 `DateTime` 类型的私有 `_date` 成员。标准的 `Hashtable` 用于存储节假日列表。
构造函数
为了方便起见,我包含了三个构造函数用于类实例化。
public XDateTime();
public XDateTime(string dateTime);
public XDateTime(string dateTime, XDateTimeType dateType);
主要逻辑
首先,我们必须确定当前日期是否是工作日。正如我们之前提到的,工作日不包括周末和节假日。因此,以下逻辑表达式的结果就是对“*是否为工作日?*”这个问题的回答。
!(_date.DayOfWeek == DayOfWeek.Saturday ||
_date.DayOfWeek == DayOfWeek.Sunday || this.IsHoliday)
其中 `AddDays` 和 `DayOfWeek` 是 `DateTime` 类的标准功能,而 `IsHoliday` 是使用 `Hashtable` 的标准方法定义的。
_holidays.ContainsValue(_date.ToString())
现在我们可以找到下一个和上一个工作日。
下一个工作日
do
{
date = date.AddDays(1.0);
}
while (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday ||
_holidays.ContainsValue(date.ToString(_format)));
上一个工作日
do
{
date = date.AddDays(-1.0);
}
while (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday ||
_holidays.ContainsValue(date.ToString(_format)));
正如您所见,我重复添加或减去一天,直到它不再是根据我的定义的工作日。实际上就是这样。我唯一想补充的细节是,定义一个私有的辅助方法来检查当前日期是否符合工作日定义,并每次更改日期时都使用此方法是非常有用的。我们可以这样做:
private void check()
{
if (_type == XDateTimeType.Business && !this.IsWorkDay)
{
_date = this.NextBusinessDay();
}
}
非常重要的是要注意,我只向前滑动日期,而不向后滑动。这很明显;如果您更改一个日期,例如加五天,并且更改后,结果日期不是工作日,那么该日期应隐式更改为下一个工作日。
结论
在本文中,我简要描述了一种简单的业务日期计算方法。我必须指出,这种方法已在一个实际的开发项目中得到应用,并证明了其完全的准确性。在实际应用中,您可能希望根据您的需求调整 `XDateTime` 类,例如从数据库读取节假日列表或其他内容。您可以使用提供的源代码轻松做到这一点。并且,如果您有任何疑问或建议,请随时与我讨论。