将DateTime设置为最新营业时间的优雅方式

时间:2014-04-26 17:08:59

标签: c# date date-math

我想在反映最新营业时间的记录上设置“As Of”值。

例如,假设我们将营业时间定义为M-F,上午9点到下午5点。如果我在星期四下午4:00调用,“As Of”应该是星期四下午4:00;但是,如果我在星期一早上1:30调用此功能,则“As Of”应该是上周五下午5:00。

我可以通过一堆逻辑来解决这个问题,但看起来这似乎是某个类的“功能”,其中工作已经完成,或者有一种简单的方法可以做到。

有吗?还是我坚持写一些可恶的算法?

2 个答案:

答案 0 :(得分:1)

C#不包含任何开箱即用的内容,但你可以尝试这样的事情:

public DateTime? GetLatestOpen(DateTime current) 
{
    var openHours = ...collection of pairs of  int (Day) and two date times (TimeRange[])...
    if (!openHours.Any()) { return null; } //prevent inf. loop if no open hours ever

    var currentDay = current.DayOfWeek;
    var hoursToday = openHours.FirstOrDefault(oh => oh.DayOfWeek == currentDay);

    if (hoursToday != null)
    {
        var currentTime = current.TimeOfDay();
        if (currentTime >= hoursToday.TimeRange[0] && 
            currentTime <= hoursToday.TimeRange[1]) 
        {
            return currentTime;
        } 
        else 
        {
            return hoursToday.TimeRange[1];
        } 
    }

    return GetLatestOpen(current.AddDays(-1));
}


...

var latestOpen = GetLatestOpen(DateTime.Now);

...

您的openHours集合看起来类似于以下内容(为了简化示例,我使用了匿名类型):

var openHours = new [] { new { Day = 1, TimeRange = new DateTime[] { ...Open..., ...Close...} }, new { Day = 2...... } };


备注:

有关上述内容的几点注意事项:

  1. Day = 0是星期日,Day = 1是星期一.... Day = 6星期六
  2. 如果需要,您可以为TimeRange使用其他类型的集合
  3. 对于...Open......Close... DateTime个对象,您无需担心实际日期;你只携带时间部分

  4. 如果您对此有任何疑问,请与我们联系。我希望这有帮助!祝你好运,编码愉快! :)

答案 1 :(得分:1)

您可以使用Time Period Library for .NET CalendarPeriodCollector

// ----------------------------------------------------------------------
public DateTime GetLatestBusinessHour( DateTime moment )
{
  // filter the business hours: - Monday to Friday, 9AM to 5PM
  CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter();
  filter.AddWorkingWeekDays();
  filter.CollectingHours.Add( new HourRange( 9, 17 ) );

  // collect business hours of the past week
  CalendarPeriodCollector collector = new CalendarPeriodCollector( filter,
    new TimeRange( moment.AddDays( -7 ), moment ), SeekDirection.Forward,
    new TimeCalendar( new TimeCalendarConfig { EndOffset = TimeSpan.Zero } ) );
  collector.CollectHours();

  // end of the last period
  return collector.Periods.End;
} // GetLatestBusinessHour