C#比较日期然后递减

时间:2011-10-30 05:12:17

标签: c# date

好的,所以这应该很简单,但似乎我无法理解它。 我有一个名为Dates的表,其中列出了从2012年开始直到最后的所有日期。现在,当客户进行预订时,我需要采用开始日期和结束日期,以日期时间格式生成它们之间的范围,并根据表中的等效日期检查每个日期以查看容量。如果是这样,那么通过预订要求减少容量。 到目前为止,我有这个代码:

 private List<DateTime> getDateRange(DateTime startDate, DateTime endDate)
 {
        if (startDate > endDate)
        {
            return null;
        }
        List<DateTime> rv = new List<DateTime>();
        DateTime tmpDate = startDate;
        do
        {
            rv.Add(tmpDate);
            tmpDate = tmpDate.AddDays(1);
        } while (tmpDate <= endDate);
        return rv;
    }

代码应该生成一个日期在范围内的列表,稍后在此函数中调用:

public void checkDateRange(DateTime startDate, DateTime endDate)
{

        //need to check each element in the list against the table DateTest:
        //changing the parameters of parse will give error. Require type handling
        //First, extract the elements:
        DateTime StartingDate = DateTime.Parse("02/25/2007");
        DateTime EndingDate = DateTime.Parse("03/06/2007");
        foreach (DateTime date in getDateRange(StartingDate, EndingDate))
        {
            date.ToShortDateString();
        }
          //rest of code should go here...

}

我想更像是从表DateTest中检索整个集合,然后在循环中(不确定哪个)我会去检查x = y这些是日期。任何代码插图都将受到高度赞赏。的问候,

2 个答案:

答案 0 :(得分:2)

根据你在这里尝试做的(总)猜测:

public class Program
{
    static void Main(string[] args)
    {
        TestDateRange(DateTime.Today, DateTime.Today.AddMonths(1));
    }

    Dictionary<DateTime, List<string>> bookings;
    int maxOccupancy = 2;

    public Program(int year = 2011)
    {
        bookings = getDateRange(new DateTime(year, 1, 1), new DateTime(year,12,31)).ToDictionary(day => day, day => new List<string>());
    }

    private static void TestDateRange(DateTime startDate, DateTime endDate)
    {
        Program p = new Program();

        if (p.GetFullDaysInDateRange(startDate, endDate).Count() == 0)
        {
            string bookingName = "Booking for test";
            p.AddBooking(startDate, endDate, bookingName);
        }
    }

    private IEnumerable<DateTime> getDateRange(DateTime startDate, DateTime endDate)
    {
        if (startDate > endDate)
        {
            return null;
        }

        return Enumerable.Range((int)startDate.ToOADate(), endDate.Subtract(startDate).Days).Select(day => DateTime.FromOADate(day));
    }

    private void AddBooking(DateTime startDate, DateTime endDate, string name)
    {
        IEnumerable<DateTime> range = getDateRange(startDate, endDate);

        foreach (DateTime date in range)
        {
            if (bookings[date].Contains(name))
                return; //already placed this booking

            if (bookings[date].Count > maxOccupancy)
                throw new Exception(String.Format("Cannot book on {0}: full", date));

            bookings[date].Add(name);
        }
    }

    public IEnumerable<DateTime> GetFullDaysInDateRange(DateTime startDate, DateTime endDate)
    {
        IEnumerable<DateTime> testRange = getDateRange(startDate, endDate);
        List<DateTime> bookedDays = new List<DateTime>();

        foreach (DateTime date in testRange)
        {
            if (bookings[date].Count > maxOccupancy)
                bookedDays.Add(date);
        }

        return bookedDays;
    }
}

答案 1 :(得分:1)

我没有看过你的代码,但这里有一些评论:

  • 开始日期和结束日期之间的范围是TimeSpan,而不是DateTime
  • 如果您有兴趣重建StartDateEndDate,则可以使用其他值添加或减去TimeSpan
  • 如果您有兴趣检查重叠,那么您将进行一维交叉测试

以下是如何进行一维交叉测试:

One-Dimensional Line-Segments/Ranges Intersection Test: Solution Name?

bool intersects = !(
    (activity1.End < activity2.Begin)
    || (activity2.End < activity1.Begin)
    );

一旦验证了 两个日期范围之间的重叠,这里有一种计算重叠的方法:

DateTime end = activity1.End < activity2.End
    ? activity1.End
    : activity2.End;

DateTime beginning = activity1.Begin > activity2.Begin
    ? activity1.Begin
    : activity2.Begin;

有了这些检查,我有一个潜在的解决方案。

潜在解决方案

您可以创建一个不包含单个约会的特殊数据结构,而是包含所有消耗的容量。

向此数据结构添加预留时,检查新值是否与现有预留重叠。您计算其在所有现有值之间的交集。对于它重叠的每个值,只需将重叠部分添加到列表中,包括该重叠处当前预订的容量。

计算完所有重叠后,检查列表中的任何项目是否已达到最大容量。如果他们有,那么预订无效,因为它会让你超过容量。如果他们没有,您可以添加预订。

要添加预订,请将所有交叉路口的预订计数增加1。然后删除预留范围内数据结构中的所有现有值。如有必要,拆分项目仅删除重叠部分。完成后,将增加的交叉点添加回列表中。

您可以在删除预订时执行类似但相反的操作,但您必须在范围的结尾/开始时将预订合并在一起,而不是将它们分开。

或者您可以采用相反的方式对此进行建模,减去可用容量。无论哪个对你更有意义。

此模型适用于建模变量容量,因为您可以使用类似的数据结构建模容量。您只需在消耗的容量和可用容量之间进行额外的交叉测试,确保您始终有足够的可用容量来满足预订容量。

我会小心设计一个系统,这个系统并不是我所依赖的唯一数据,我可以从单独的结构/表中的数据中重新生成这些数据。例如,我会分别存储每个预订的开始和结束日期以及联系信息。

<强>优化

您可以利用排序和空间分区算法来加速与所有预订值进行比较的部分。例如,您可以将所有值分区为长达一个月的块,因此您只需要与预订相交的一两个月进行比较。在关系数据库中,这称为时间分区。

如果您选择进行分区,可以让您的生活更简单的一个要求是确保您的分区足够大,以至于您只需要检查两个单元格。使您的分区小于此值,您的算法将更复杂,因此更难以验证。

如果您的数据足够小,您可以动态计算整个表格,只需要感兴趣的日期范围,而不是将数据结构存储在数据库中。如果范围足够小,您可能也不必担心分区,以至于您可以在范围内每天(或任何单位,如果您有不同的分辨率)进行检查。这样可以简化一些操作,因为您可以构建数据结构并进行容量检查,而不必担心分割或合并容量范围等事情。