码迷,mamicode.com
首页 > 其他好文 > 详细

时间过滤和合并

时间:2015-05-26 14:22:29      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:时间   合并   过滤   

近期在做一项目的过程中,需要涉及到服务人员班次、请假及服务预定等一系列时间管理问题,最后要提供出人员空闲的时间段以供用户选择,归结到底,涉及到两大时间算法,一是时间过滤,即在原定上班班次安排的基础上扣除休假、请假以及已预定的时间段,另一个是时间段合并,需要将一个服务涉及的多位服务人员的有效时间合并,以便用户先选择时间,而后选择该时间段有空的服务人员。下面将分享一下涉及时间的两个算法。


1、合并集合中的各时间段

原始数据:
startTime=2015-05-26 12:06:00    endTime=2015-05-26 15:06:00
startTime=2015-05-27 16:08:00    endTime=2015-05-27 19:08:00
startTime=2015-05-27 13:10:00    endTime=2015-05-27 16:10:00
startTime=2015-05-27 14:57:00    endTime=2015-05-27 17:57:00
startTime=2015-05-27 10:16:00    endTime=2015-05-27 13:16:00
startTime=2015-05-26 11:50:00    endTime=2015-05-26 13:50:00
startTime=2015-05-26 13:46:00    endTime=2015-05-26 16:46:00
startTime=2015-05-27 9:09:00    endTime=2015-05-27 12:09:00
startTime=2015-05-27 16:36:00    endTime=2015-05-27 18:36:00
startTime=2015-05-26 14:39:00    endTime=2015-05-26 16:39:00

结果:
startTime=2015-05-26 11:50:00    endTime=2015-05-26 16:46:00
startTime=2015-05-27 9:09:00    endTime=2015-05-27 19:08:00


核心代码

public static List<EmptyDuration> MergeDateTime(List<EmptyDuration> emptyDurations)
{
    List<EmptyDuration> results = new List<EmptyDuration>();

    if (emptyDurations.Count == 0)
    {
        return results;
    }

    // 对原始数据进行排序
    List<EmptyDuration> em = emptyDurations.OrderBy(p => p.StartTime).ToList<EmptyDuration>();

    DateTime startTime = em[0].StartTime;
    DateTime endTime = em[0].EndTime;

    for (int i = 0; i < em.Count - 1; i++)
    {
        int j = i + 1;

        // 处理前后两个没有交叉重叠的情况
        if (em[i].EndTime < em[j].StartTime)
        {
            results.Add(new EmptyDuration
            {
                StartTime = startTime,
                EndTime = endTime
            });

            startTime = em[j].StartTime;
            endTime = em[j].EndTime;
        }
        else
        {
            endTime = em[i].EndTime > em[j].EndTime ? em[i].EndTime : em[j].EndTime;
        }
    }

    // 补上最后剩下的时间段
    results.Add(new EmptyDuration
    {
        StartTime = startTime,
        EndTime = endTime
    });

    return results;
}
其它辅助测试代码

public static void MergeTest(int num, int days)
{
    List<EmptyDuration> timeList = GeneralDuration(num, days);
    List<EmptyDuration> list = MergeDateTime(timeList);
}

public static List<EmptyDuration> GeneralDuration(int count, int maxDateDiff)
{
    Random random = new Random(DateTime.Now.Millisecond);
    List<EmptyDuration> list = new List<EmptyDuration>();
    for (int i = 0; i < count; i++)
    {
        int hour = random.Next(9, 20);
        int hourDiff = random.Next(2, 4);
        int min = random.Next(60);
        int dateDiff = random.Next(0, maxDateDiff);
        DateTime startTime = DateTime.Now.Date.AddDays(dateDiff).AddHours(hour).AddMinutes(min);
        DateTime endTime = DateTime.Now.Date.AddDays(dateDiff).AddHours(hour).AddHours(hourDiff).AddMinutes(min);
        list.Add(new EmptyDuration
        {
            ArtificerId = 10002,
            ShopId = 20001,
            StartTime = startTime,
            EndTime = endTime
        });
    }

    return list;
}

2、时间段过滤

在此代码中,左侧是服务人员原定上班时间集合,右侧是员工请假、预定所占时间集合。

原始数据(左):
startTime=2015-05-26 9:00:00    endTime=2015-05-26 22:00:00
startTime=2015-05-27 9:00:00    endTime=2015-05-27 22:00:00
startTime=2015-05-28 9:00:00    endTime=2015-05-28 22:00:00

原始数据(右):
startTime=2015-05-27 19:39:00    endTime=2015-05-27 21:39:00
startTime=2015-05-28 12:56:00    endTime=2015-05-28 15:56:00
startTime=2015-05-26 17:17:00    endTime=2015-05-26 20:17:00
startTime=2015-05-27 9:45:00    endTime=2015-05-27 12:45:00
startTime=2015-05-27 18:08:00    endTime=2015-05-27 20:08:00
startTime=2015-05-28 19:46:00    endTime=2015-05-28 22:46:00
startTime=2015-05-28 12:09:00    endTime=2015-05-28 15:09:00
startTime=2015-05-27 11:55:00    endTime=2015-05-27 13:55:00
startTime=2015-05-28 17:18:00    endTime=2015-05-28 20:18:00
startTime=2015-05-26 18:09:00    endTime=2015-05-26 20:09:00

结果:
startTime=2015-05-26 9:00:00    endTime=2015-05-26 17:17:00
startTime=2015-05-26 20:17:00    endTime=2015-05-26 22:00:00
startTime=2015-05-27 9:00:00    endTime=2015-05-27 9:45:00
startTime=2015-05-27 13:55:00    endTime=2015-05-27 18:08:00
startTime=2015-05-27 21:39:00    endTime=2015-05-27 22:00:00
startTime=2015-05-28 9:00:00    endTime=2015-05-28 12:09:00
startTime=2015-05-28 15:56:00    endTime=2015-05-28 17:18:00

核心代码

public static List<EmptyDuration> SubtractDateTime(List<EmptyDuration> minuend, List<EmptyDuration> subtrahend)
{
    List<EmptyDuration> results = new List<EmptyDuration>();

    if (minuend.Count == 0 )
    {
        return results;
    }

    if (subtrahend.Count == 0)
    {
        return minuend;
    }

    // 对原始数据进行排序
    List<EmptyDuration> lefts = minuend.OrderBy(p => p.StartTime).ToList<EmptyDuration>();
    List<EmptyDuration> rights = subtrahend.OrderBy(p => p.StartTime).ToList<EmptyDuration>();

    // 左右两个集合的指针
    int lIndex = 0;
    int rIndex = 0;

    // 左右两个集合的元素数量
    int lMax = lefts.Count;
    int rMax = rights.Count;

    DateTime startTime = DateTime.MinValue;
    DateTime endTime = DateTime.MinValue;

    // 左右指针是否要下移一位并获取元素数据
    bool lIncrease = true;

    while (lIndex < lMax && rIndex < rMax)
    {
        if (lIncrease)
        {
            startTime = lefts[lIndex].StartTime;
            endTime = lefts[lIndex].EndTime;
        }

        lIncrease = false;

        // 处理两个集合当前元素存在交叉重叠的情况
        if (endTime > rights[rIndex].StartTime && startTime < rights[rIndex].EndTime)
        {
            // 上班开始时间在请假预定时间之前
            if (startTime < rights[rIndex].StartTime)
            {
                results.Add(new EmptyDuration
                {
                    StartTime = startTime,
                    EndTime = rights[rIndex].StartTime
                });

                // 上班结束时间在请假预定结束时间之前
                if (endTime <= rights[rIndex].EndTime)
                {
                    lIncrease = true;
                }
                else
                {
                    startTime = rights[rIndex].EndTime;
                    rIndex++;
                }
            }
            else // 上班开始时间在请假预定时间之后
            {
                        
                // 上班结束在请假预定时间之后
                if (endTime > rights[rIndex].EndTime)
                {
                    startTime = rights[rIndex].EndTime;
                    rIndex++;
                }
                else
                {
                    lIncrease = true;
                }
            }
        }
        else
        {
            // 上班时间段在请假预定时间段之前
            if (startTime < rights[rIndex].StartTime)
            {
                results.Add(new EmptyDuration
                {
                    StartTime = startTime,
                    EndTime = endTime
                });

                lIncrease = true;
            }
            else
            {
                rIndex++;
            }
        }

        if (lIncrease)
        {
            lIndex++;
        }
    }

    // 处理剩余上班时间段
    if (lIndex < lMax)
    {
        results.Add(new EmptyDuration
        {
            StartTime = startTime,
            EndTime = endTime
        });

        for (int i = lIndex + 1; i < lMax; i++)
        {
            results.Add(new EmptyDuration
            {
                StartTime = lefts[i].StartTime,
                EndTime = lefts[i].EndTime
            });
        }
    }

    return results;
}
其它辅助测试代码:

public static void SubtractTest(int num, int days)
{
    List<EmptyDuration> leftList = GeneralDuration(days);
    List<EmptyDuration> rightList = GeneralDuration(num, days);

    List<EmptyDuration> list = SubtractDateTime(leftList, rightList);
}

public static List<EmptyDuration> GeneralDuration(int days)
{
    List<EmptyDuration> list = new List<EmptyDuration>();
    for (int i = 0; i < days; i++)
    {
        list.Add(new EmptyDuration
        {
            StartTime = DateTime.Now.Date.AddDays(i).AddHours(9),
            EndTime = DateTime.Now.Date.AddDays(i).AddHours(22)
        });
    }

    return list;
}






时间过滤和合并

标签:时间   合并   过滤   

原文地址:http://blog.csdn.net/mole/article/details/46007029

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!