在 C# 中查找多个日期之间的间隔
Find gap between multiple dates in C#
我目前正在编写一个自动与 MS Exchange Server 同步的约会查找器。
该程序应在可用时查找多个用户的日历。
我编写了一些包含多个用户及其约会的演示数据。约会由两个日期时间组成。
所以我的问题是:如何找到多个用户约会之间的空档,让每个人都有空。
这是演示数据:
var appointment1ForPerson1 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
var appointment2ForPerson1 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
var appointment3ForPerson1 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });
var appointmentsForPerson1 = new List<Appointment>() { appointment1ForPerson1, appointment2ForPerson1, appointment3ForPerson1 };
var person1 = new Person("steven@example.de", appointmentsForPerson1);
_userList.Add(person1);
var appointment1ForPerson2 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
var appointment2ForPerson2 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
var appointment3ForPerson2 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });
var appointmentsForPerson2 = new List<Appointment>() { appointment1ForPerson2, appointment2ForPerson2, appointment3ForPerson2 };
var person2 = new Person("jonas@example.de", appointmentsForPerson2);
_userList.Add(person2);
class 有约会和时间的人是:
class Person
{
private readonly string _email;
private readonly List<Appointment> _appointments;
public Person(string email, List<Appointment> appointments)
{
_email = email;
_appointments = appointments;
}
public string Email
{
get { return _email; }
}
public List<Appointment> Appointments
{
get { return _appointments; }
}
internal class Appointment
{
private readonly List<Time> _appointmentHoursList;
public Appointment(List<Time> appointmentHoursList)
{
_appointmentHoursList = appointmentHoursList;
}
public List<Time> AppointmentHoursList
{
get { return _appointmentHoursList; }
}
internal class Time
{
private readonly DateTime _beginningTime;
private readonly DateTime _endTime;
public Time(DateTime beginningTime, DateTime endTime)
{
_beginningTime = beginningTime;
_endTime = endTime;
}
public DateTime BeginningTime
{
get { return _beginningTime; }
}
public DateTime EndTime
{
get { return _endTime; }
}
}
}
}
以下解决方案使用 TimePeriodLibraryforNET。请阅读代码中的注释:
//define working hours - obligatory part!
TimePeriodCollection workinghours = new TimePeriodCollection();
for(int i = 7; i<12; i+=2)
workinghours.Add(new TimeRange(new DateTime(2020, 7, i, 9, 0, 0), new DateTime(2020, 7, i, 17, 0, 0)));
ITimePeriodCollection workingperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(workinghours);
//define user#1 appointments
TimePeriodCollection allappointments = new TimePeriodCollection();
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0)));
//define user#2 appointments
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 15, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 30, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 30, 0), new DateTime(2020, 7, 11, 11, 45, 0)));
//combine periods
ITimePeriodCollection usersperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(allappointments);
//get gaps
TimePeriodCollection gaps = new TimePeriodCollection();
foreach (ITimePeriod basePeriod in workingperiods)
{
gaps.AddAll( new TimeGapCalculator<TimeRange>().GetGaps(usersperiods, basePeriod));
}
//enumerate gaps
foreach(ITimePeriod gap in gaps)
{
Console.WriteLine($"Gap: {gap}");
}
结果(基于示例数据):
Gap: 2020-07-07 09:00:00 - 16:45:00 | 0.07:45
Gap: 2020-07-09 12:30:00 - 17:00:00 | 0.04:30
Gap: 2020-07-11 09:00:00 - 10:00:00 | 0.01:00
Gap: 2020-07-11 12:00:00 - 17:00:00 | 0.05:00
我目前正在编写一个自动与 MS Exchange Server 同步的约会查找器。 该程序应在可用时查找多个用户的日历。 我编写了一些包含多个用户及其约会的演示数据。约会由两个日期时间组成。
所以我的问题是:如何找到多个用户约会之间的空档,让每个人都有空。 这是演示数据:
var appointment1ForPerson1 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
var appointment2ForPerson1 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
var appointment3ForPerson1 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });
var appointmentsForPerson1 = new List<Appointment>() { appointment1ForPerson1, appointment2ForPerson1, appointment3ForPerson1 };
var person1 = new Person("steven@example.de", appointmentsForPerson1);
_userList.Add(person1);
var appointment1ForPerson2 = new Appointment(1, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0))) });
var appointment2ForPerson2 = new Appointment(3, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0))) });
var appointment3ForPerson2 = new Appointment(5, new List<Appointment.Time>() { (new Appointment.Time(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0))) });
var appointmentsForPerson2 = new List<Appointment>() { appointment1ForPerson2, appointment2ForPerson2, appointment3ForPerson2 };
var person2 = new Person("jonas@example.de", appointmentsForPerson2);
_userList.Add(person2);
class 有约会和时间的人是:
class Person
{
private readonly string _email;
private readonly List<Appointment> _appointments;
public Person(string email, List<Appointment> appointments)
{
_email = email;
_appointments = appointments;
}
public string Email
{
get { return _email; }
}
public List<Appointment> Appointments
{
get { return _appointments; }
}
internal class Appointment
{
private readonly List<Time> _appointmentHoursList;
public Appointment(List<Time> appointmentHoursList)
{
_appointmentHoursList = appointmentHoursList;
}
public List<Time> AppointmentHoursList
{
get { return _appointmentHoursList; }
}
internal class Time
{
private readonly DateTime _beginningTime;
private readonly DateTime _endTime;
public Time(DateTime beginningTime, DateTime endTime)
{
_beginningTime = beginningTime;
_endTime = endTime;
}
public DateTime BeginningTime
{
get { return _beginningTime; }
}
public DateTime EndTime
{
get { return _endTime; }
}
}
}
}
以下解决方案使用 TimePeriodLibraryforNET。请阅读代码中的注释:
//define working hours - obligatory part!
TimePeriodCollection workinghours = new TimePeriodCollection();
for(int i = 7; i<12; i+=2)
workinghours.Add(new TimeRange(new DateTime(2020, 7, i, 9, 0, 0), new DateTime(2020, 7, i, 17, 0, 0)));
ITimePeriodCollection workingperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(workinghours);
//define user#1 appointments
TimePeriodCollection allappointments = new TimePeriodCollection();
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 0, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 0, 0), new DateTime(2020, 7, 11, 12, 0, 0)));
//define user#2 appointments
allappointments.Add(new TimeRange(new DateTime(2020, 7, 7, 16, 45, 0), new DateTime(2020, 7, 7, 17, 15, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 9, 9, 0, 0), new DateTime(2020, 7, 9, 12, 30, 0)));
allappointments.Add(new TimeRange(new DateTime(2020, 7, 11, 10, 30, 0), new DateTime(2020, 7, 11, 11, 45, 0)));
//combine periods
ITimePeriodCollection usersperiods = new TimePeriodCombiner<TimeRange>().CombinePeriods(allappointments);
//get gaps
TimePeriodCollection gaps = new TimePeriodCollection();
foreach (ITimePeriod basePeriod in workingperiods)
{
gaps.AddAll( new TimeGapCalculator<TimeRange>().GetGaps(usersperiods, basePeriod));
}
//enumerate gaps
foreach(ITimePeriod gap in gaps)
{
Console.WriteLine($"Gap: {gap}");
}
结果(基于示例数据):
Gap: 2020-07-07 09:00:00 - 16:45:00 | 0.07:45
Gap: 2020-07-09 12:30:00 - 17:00:00 | 0.04:30
Gap: 2020-07-11 09:00:00 - 10:00:00 | 0.01:00
Gap: 2020-07-11 12:00:00 - 17:00:00 | 0.05:00