有没有一种优化的方法可以让两个约会之间有工作周?

本文关键字:两个 约会 工作周 之间 一种 优化 有没有 方法 | 更新日期: 2023-09-27 18:02:38

只是想知道是否有一种更优化和/或更整洁的方式(例如使用LINQ)来编写我下面的内容,以获得两个日期之间的商业周日期范围列表?

这是我目前拥有的…

// Some storage
public class Bucket
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}
// Other code removed for brevity ...
DateTime start = new DateTime(2015, 7, 1);
DateTime end = new DateTime(2015, 9, 1);
DayOfWeek firstDayOfWeek = DayOfWeek.Monday;
DayOfWeek lastDayOfWeek = DayOfWeek.Friday;
var buckets = new List<Bucket>();
var currentDate = start;
DateTime startOfBucket = currentDate;
DateTime endOfBucket = currentDate;
while (currentDate <= end)
{
    var currentDayOfWeek = currentDate.DayOfWeek;
    // Skip days outside the business week
    if (currentDayOfWeek >= firstDayOfWeek && currentDayOfWeek <= lastDayOfWeek)
    {
        if (currentDayOfWeek == firstDayOfWeek)
        {
            // Start a new bucket
            startOfBucket = currentDate;
        }
        if ((currentDayOfWeek == lastDayOfWeek) || (currentDate == end))
        {
            // End of bucket
            endOfBucket = currentDate;
            // Create bucket
            buckets.Add(new Bucket() 
            { 
                StartDate = startOfBucket, 
                EndDate = endOfBucket 
            });
        }
    }
    currentDate = currentDate.AddDays(1);
}

这将给我以下日期范围…

  • 开始:2015年7月01日结束:2015年7月03日
  • 开始:2015年7月6日结束:2015年7月10日
  • 开始:2015年7月13日结束:2015年7月17日
  • 开始:2015年7月20日结束:2015年7月24日
  • 开始:2015年7月27日结束:2015年7月31日
  • 开始:2015年8月03日结束:2015年8月07日
  • 开始:2015年8月10日结束:2015年8月14日
  • 开始:2015年8月17日结束:2015年8月21日
  • 开始时间:2015年8月24日结束时间:2015年8月28日
  • 开始:2015年8月31日结束:2015年9月01日

注意:第一周和最后一周故意不是完整的周(它们遵守给定的日期范围)。

编辑这里提供的解决方案给出了两个日期之间的天数,但我感兴趣的是获取日期范围的集合。

还有,我不需要考虑任何假期。

谢谢,

有没有一种优化的方法可以让两个约会之间有工作周?

使用linq非常方便

var startDate = new DateTime(2015, 7, 1);
var endDate = new DateTime(2015, 9, 1);
var workDates = Enumerable.Range(0, (int)(endDate - startDate).TotalDays + 1)
    .Select(i => startDate.AddDays(i))
    .Where(date => (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday))
    .Select(i => i);

var display = workDates
    .GroupAdjacentBy((x, y) => x.AddDays(1) == y)
    .Select(g => string.Format("Start: {0:dd/MMM/yyyy} End: {1:dd/MMM/yyyy}", g.First(), g.Last()));

用扩展方法GroupAdjacentBy<T>

public static class IEnumerableExtension
{
    public static IEnumerable<IEnumerable<T>> GroupAdjacentBy<T>(
        this IEnumerable<T> source, Func<T, T, bool> predicate)
    {
        using (var e = source.GetEnumerator())
        {
            if (e.MoveNext())
            {
                var list = new List<T> { e.Current };
                var pred = e.Current;
                while (e.MoveNext())
                {
                    if (predicate(pred, e.Current))
                    {
                        list.Add(e.Current);
                    }
                    else
                    {
                        yield return list;
                        list = new List<T> { e.Current };
                    }
                    pred = e.Current;
                }
                yield return list;
            }
        }
    }
}

小提琴

这是基于Eric的公认答案,所以请给他点赞。我刚刚修改了他的解决方案,以处理可能长达7天的工作周,也可以处理一个周末的工作周。

var startDate = new DateTime(2015, 7, 1);
var endDate = new DateTime(2015, 9, 1);
DayOfWeek firstDayOfWeek = DayOfWeek.Monday;
DayOfWeek lastDayOfWeek = DayOfWeek.Friday;
var workDates = Enumerable.Range(0, (int)(endDate - startDate).TotalDays + 1)
            .Select(i => startDate.AddDays(i))
            .Where(date => 
                // Normal work weeks where first day of week is before last (numerically) e.g. Monday -> Friday or Sunday -> Saturday
                (firstDayOfWeek < lastDayOfWeek && date.DayOfWeek >= firstDayOfWeek && date.DayOfWeek <= lastDayOfWeek) ||
                // Cater for business weeks whose start and end dates wrap over the weekend e.g. Thursday -> Tuesday
                (lastDayOfWeek < firstDayOfWeek && (date.DayOfWeek >= firstDayOfWeek || date.DayOfWeek <= lastDayOfWeek)))
            .Select(i => i);
var display = workDates
            .GroupAdjacentBy((x, y) => x.AddDays(1) == y && !(x.DayOfWeek == lastDayOfWeek && y.DayOfWeek == firstDayOfWeek))
            .Select(g => string.Format("Start: {0:dd/MMM/yyyy} End: {1:dd/MMM/yyyy}", g.First(), g.Last()));