4

我正在尝试计算两个LocalDateTime值之间的时间量并排除特定日期(在此示例中,它是银行假期)。

var bankHolidays = new[] { new LocalDate(2013, 12, 25), new LocalDate(2013, 12, 26) };
var localDateTime1 = new LocalDateTime(2013, 11, 18, 10, 30);
var localDateTime2 = new LocalDateTime(2013, 12, 29, 10, 15);

var differenceBetween = Period.Between(localDateTime1, localDateTime2, PeriodUnits.Days | PeriodUnits.HourMinuteSecond);

如您所料,该differenceBetween值显示两个日期之间的天数/小时/分钟/秒数。

我可以从开始日期开始检查每一天,看看bankHolidays集合是否包含该日期,例如

var bankHolidays = new[] { new LocalDate(2013, 12, 25), new LocalDate(2013, 12, 26) };
var localDateTime1 = new LocalDateTime(2013, 11, 18, 10, 30);
var localDateTime2 = new LocalDateTime(2013, 12, 29, 10, 15);

var differenceBetween = Period.Between(localDateTime1, localDateTime2, PeriodUnits.Days | PeriodUnits.HourMinuteSecond);

var london = DateTimeZoneProviders.Tzdb["Europe/London"];

for (var i = 1; i < differenceBetween.Days; ++i)
{
    var x = localDateTime1.InZoneStrictly(london) + Duration.FromStandardDays(i);

    if (bankHolidays.Any(date => date == x.Date))
    {
        //subtract one day for the period.
    }
}

我觉得我遗漏了一些明显的东西,应该有一个更简单的方法,有没有更简单的方法可以找到两个日期之间的时间段,同时排除某些日期?

我还需要在此排除项中包括周末,显而易见的方法似乎是在检查银行假期的同时检查周末的星期几,但这似乎不是最好/正确的处理方式。

4

2 回答 2

4

我觉得我遗漏了一些明显的东西,应该有一个更简单的方法,有没有更简单的方法可以找到两个日期之间的时间段,同时排除某些日期?

好吧,计算日期范围内包含的银行假期数量相对容易:

  • 按时间顺序排列所有银行假期
  • 使用二分搜索找出集合中的开始日期
  • 使用二分搜索找出集合中的结束日期
  • 从另一个索引中减去一个索引以查找该范围内的条目数
  • Period.Between使用你已经在做的工作来计算整个时期
  • 从范围内的总天数中减去范围内的条目数

繁琐的一点是考虑到开始和/或结束日期可能是银行假期。一个错误的可能性很大,但是通过一组好的单元测试应该没问题。

或者,如果您的银行假期相对较少,您可以使用:

var period = Period.Between(start, end,
                            PeriodUnits.Days | PeriodUnits.HourMinuteSecond);
var holidayCount = holidays.Count(x => x >= start && x <= end);
period = period - Period.FromDays(holidayCount);
于 2013-11-19T04:47:04.377 回答
0

只需使用TimeSpan即可获得差异,所有时间都在您当前的本地时区:

var bankHolidays = new[] { new DateTime(2013, 12, 25), new DateTime(2013, 12, 26) };
var localDateTime1 = new DateTime(2013, 11, 18, 10, 30, 0);
var localDateTime2 = new DateTime(2013, 12, 29, 10, 15, 0);
var span = localDateTime2 - localDateTime1;
var holidays = bankHolidays[1] - bankHolidays[0];
var duration = span-holidays;

现在是您在和duration之间经过的时间。如果您想通过 排除两个日期,您可以轻松修改上述操作。localDateTime1localDateTime2bankHolidays

您可能会为此操作使用额外的方法:

public static TimeSpan GetPeriod(DateTime start, DateTime end, params DateTime[] exclude)
{
    var span = end - start;
    if (exclude == null) return span;
    span = exclude.Where(d => d >= start && d <= end)
    .Aggregate(span, (current, date) => current.Subtract(new TimeSpan(1, 0, 0, 0)));
    return span;
}

现在你可以使用这个:

var duration = GetPeriod(localDateTime1, localDateTime2, bankHolidays);
于 2013-11-18T11:09:36.537 回答