corelibraries-devexpress-dot-xtrascheduler-dot-tools.md
Enables you to find available spare time intervals within the specified period.
Namespace : DevExpress.XtraScheduler.Tools
Assembly : DevExpress.XtraScheduler.v25.2.Core.Desktop.dll
NuGet Package : DevExpress.Scheduler.CoreDesktop
public class FreeTimeCalculator :
ITimeZoneHost
Public Class FreeTimeCalculator
Implements ITimeZoneHost
The FreeTimeCalculator class enables you to find free time slots within the specified time interval. It can be helpful when searching for time periods suitable for a new meeting arrangement. The time interval can be queried based on a specific resource.
The FreeTimeCalculator.CalculateFreeTime method finds all available spare time intervals within the specified period of time. To find the nearest free slot with the specified duration, use the FreeTimeCalculator.FindFreeTimeInterval method. The search technique calculates the time in use based on the appointments currently contained within the Scheduler Storage. You can restrict the search to filtered appointments via the FreeTimeCalculator.ApplyAppointmentFilters property.
To find the spare time periods in work time only, so that holidays, night shifts and lunch hours are excluded, handle the FreeTimeCalculator.IntervalFound event. It gives you the flexibility to decide whether a particular free time slot satisfies your requirements. Use the TimeIntervalCollectionEx collection methods to modify the time intervals as needed.
The following code sample illustrates the implementation of the method used to find a free time slot which has a specified duration, or is longer than that, before the end of the current work week.
The following code sample illustrates the implementation of the method used to find a free time slot which has a specified duration, or is longer than that, before the end of the current work week.
Note
A complete sample project is available at https://github.com/DevExpress-Examples/winforms-scheduler-find-free-time-intervals
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.Tools;
using System;
using System.Windows.Forms;
namespace FreeTimeIntervals
{
public partial class Form1 : Form {
TimeZoneHelper timeZoneHelper;
// Specify non-working time interval.
TimeOfDayInterval nonWorkingTime = new TimeOfDayInterval(TimeSpan.FromHours(18), TimeSpan.FromDays(1) + TimeSpan.FromHours(9));
internal TimeZoneHelper TimeZoneHelper { get { return timeZoneHelper; } }
internal TimeOfDayInterval NonWorkingTime { get { return nonWorkingTime; } set { nonWorkingTime = value; } }
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
// TODO: This line of code loads data into the 'xtraSchedulingDataSet1.Resources' table. You can move, or remove it, as needed.
this.resourcesTableAdapter.Fill(this.xtraSchedulingDataSet1.Resources);
// TODO: This line of code loads data into the 'xtraSchedulingDataSet.Appointments' table. You can move, or remove it, as needed.
this.appointmentsTableAdapter.Fill(this.xtraSchedulingDataSet.Appointments);
timeZoneHelper = new TimeZoneHelper(this.schedulerControl1.OptionsBehavior.ClientTimeZoneId);
}
private void button1_Click(object sender, EventArgs e) {
TimeSpan duration = ((DateTime)slotDuration.EditValue).TimeOfDay;
DateTime start = schedulerControl1.ActiveView.SelectedInterval.End;
DateTime startOfWeek = DevExpress.XtraScheduler.Native.DateTimeHelper.GetStartOfWeek(start);
TimeInterval interval = new TimeInterval(start, startOfWeek.AddDays(7));
TimeInterval freeTime = FindInterval(interval, duration);
string text;
if (TimeInterval.Equals(freeTime, TimeInterval.Empty))
text = "Not found";
else {
TimeInterval clientFreeInterval = TimeZoneHelper.ToClientTime(freeTime);
text = "Free time interval with duration " + clientFreeInterval.Duration.ToString() +
" is found! \n\r It starts on " + clientFreeInterval.Start.Date.ToShortDateString() +
" at " + clientFreeInterval.Start.TimeOfDay.ToString() + ".";
schedulerControl1.ActiveView.SetSelection(clientFreeInterval, ResourceEmpty.Resource);
}
MessageBox.Show(text, "Search Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private TimeInterval FindInterval(TimeInterval clientInterval, TimeSpan duration) {
FreeTimeCalculator calculator = new FreeTimeCalculator(schedulerControl1.Storage);
// Set a handler for the IntervalFound event.
calculator.IntervalFound += new IntervalFoundEventHandler(OnIntervalFound);
TimeInterval interval = TimeZoneHelper.FromClientTime(clientInterval);
// Call the method which raises the event.
return calculator.FindFreeTimeInterval(interval, duration, true);
}
private void OnIntervalFound(object sender, IntervalFoundEventArgs args) {
TimeIntervalCollectionEx freeIntervals = args.FreeIntervals;
DateTime start = freeIntervals.Start.Date.AddDays(-1);
DateTime end = freeIntervals.End;
while (start < end) {
RemoveNonWorkingTime(freeIntervals, start);
RemoveNonWorkingDay(freeIntervals, start);
start += TimeSpan.FromDays(1);
}
}
private void RemoveNonWorkingTime(TimeIntervalCollectionEx freeIntervals, DateTime date) {
DateTime clientDate = TimeZoneHelper.ToClientTime(date).Date;
TimeInterval clientNonWorkingTime = new TimeInterval(clientDate + NonWorkingTime.Start, clientDate + NonWorkingTime.End);
freeIntervals.Remove(TimeZoneHelper.FromClientTime(clientNonWorkingTime));
}
private void RemoveNonWorkingDay(TimeIntervalCollectionEx freeIntervals, DateTime date) {
DateTime clientDate = TimeZoneHelper.ToClientTime(date).Date;
bool isWorkDay = schedulerControl1.WorkDays.IsWorkDay(clientDate);
if (!isWorkDay) {
TimeInterval clientInterval = new TimeInterval(clientDate, TimeSpan.FromDays(1));
freeIntervals.Remove(TimeZoneHelper.FromClientTime(clientInterval));
}
}
private void OnApptChangedInsertedDeleted(object sender, PersistentObjectsEventArgs e) {
appointmentsTableAdapter.Update(xtraSchedulingDataSet);
xtraSchedulingDataSet.AcceptChanges();
}
}
}
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace FreeTimeIntervals
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
DevExpress.Skins.SkinManager.EnableFormSkins();
Application.Run(new Form1());
}
}
}
Imports DevExpress.XtraScheduler
Imports DevExpress.XtraScheduler.Tools
Imports System
Imports System.Windows.Forms
Namespace FreeTimeIntervals
Partial Public Class Form1
Inherits Form
Private timeZoneHelper_Renamed As TimeZoneHelper
' Specify non-working time interval.
Private nonWorkingTime_Renamed As New TimeOfDayInterval(TimeSpan.FromHours(18), TimeSpan.FromDays(1).Add(TimeSpan.FromHours(9)))
Friend ReadOnly Property TimeZoneHelper() As TimeZoneHelper
Get
Return timeZoneHelper_Renamed
End Get
End Property
Friend Property NonWorkingTime() As TimeOfDayInterval
Get
Return nonWorkingTime_Renamed
End Get
Set(ByVal value As TimeOfDayInterval)
nonWorkingTime_Renamed = value
End Set
End Property
Public Sub New()
InitializeComponent()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
' TODO: This line of code loads data into the 'xtraSchedulingDataSet1.Resources' table. You can move, or remove it, as needed.
Me.resourcesTableAdapter.Fill(Me.xtraSchedulingDataSet1.Resources)
' TODO: This line of code loads data into the 'xtraSchedulingDataSet.Appointments' table. You can move, or remove it, as needed.
Me.appointmentsTableAdapter.Fill(Me.xtraSchedulingDataSet.Appointments)
timeZoneHelper_Renamed = New TimeZoneHelper(Me.schedulerControl1.OptionsBehavior.ClientTimeZoneId)
End Sub
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles button1.Click
Dim duration As TimeSpan = CDate(slotDuration.EditValue).TimeOfDay
Dim start As Date = schedulerControl1.ActiveView.SelectedInterval.End
Dim startOfWeek As Date = DevExpress.XtraScheduler.Native.DateTimeHelper.GetStartOfWeek(start)
Dim interval As New TimeInterval(start, startOfWeek.AddDays(7))
Dim freeTime As TimeInterval = FindInterval(interval, duration)
Dim text_Renamed As String
If TimeInterval.Equals(freeTime, TimeInterval.Empty) Then
text_Renamed = "Not found"
Else
Dim clientFreeInterval As TimeInterval = TimeZoneHelper.ToClientTime(freeTime)
text_Renamed = "Free time interval with duration " & clientFreeInterval.Duration.ToString() & " is found! " & ControlChars.Lf & ControlChars.Cr & " It starts on " & clientFreeInterval.Start.Date.ToShortDateString() & " at " & clientFreeInterval.Start.TimeOfDay.ToString() & "."
schedulerControl1.ActiveView.SetSelection(clientFreeInterval, ResourceEmpty.Resource)
End If
MessageBox.Show(text_Renamed, "Search Result", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Private Function FindInterval(ByVal clientInterval As TimeInterval, ByVal duration As TimeSpan) As TimeInterval
Dim calculator As New FreeTimeCalculator(schedulerControl1.Storage)
' Set a handler for the IntervalFound event.
AddHandler calculator.IntervalFound, AddressOf OnIntervalFound
Dim interval As TimeInterval = TimeZoneHelper.FromClientTime(clientInterval)
' Call the method which raises the event.
Return calculator.FindFreeTimeInterval(interval, duration, True)
End Function
Private Sub OnIntervalFound(ByVal sender As Object, ByVal args As IntervalFoundEventArgs)
Dim freeIntervals As TimeIntervalCollectionEx = args.FreeIntervals
Dim start As Date = freeIntervals.Start.Date.AddDays(-1)
Dim [end] As Date = freeIntervals.End
Do While start < [end]
RemoveNonWorkingTime(freeIntervals, start)
RemoveNonWorkingDay(freeIntervals, start)
start = start.Add(TimeSpan.FromDays(1))
Loop
End Sub
Private Sub RemoveNonWorkingTime(ByVal freeIntervals As TimeIntervalCollectionEx, ByVal [date] As Date)
Dim clientDate As Date = TimeZoneHelper.ToClientTime([date]).Date
Dim clientNonWorkingTime As New TimeInterval(clientDate + NonWorkingTime.Start, clientDate + NonWorkingTime.End)
freeIntervals.Remove(TimeZoneHelper.FromClientTime(clientNonWorkingTime))
End Sub
Private Sub RemoveNonWorkingDay(ByVal freeIntervals As TimeIntervalCollectionEx, ByVal [date] As Date)
Dim clientDate As Date = TimeZoneHelper.ToClientTime([date]).Date
Dim isWorkDay As Boolean = schedulerControl1.WorkDays.IsWorkDay(clientDate)
If Not isWorkDay Then
Dim clientInterval As New TimeInterval(clientDate, TimeSpan.FromDays(1))
freeIntervals.Remove(TimeZoneHelper.FromClientTime(clientInterval))
End If
End Sub
Private Sub OnApptChangedInsertedDeleted(ByVal sender As Object, ByVal e As PersistentObjectsEventArgs) Handles schedulerStorage1.AppointmentsChanged, schedulerStorage1.AppointmentsInserted, schedulerStorage1.AppointmentsDeleted
appointmentsTableAdapter.Update(xtraSchedulingDataSet)
xtraSchedulingDataSet.AcceptChanges()
End Sub
End Class
End Namespace
Imports System
Imports System.Collections.Generic
Imports System.Windows.Forms
Namespace FreeTimeIntervals
Friend NotInheritable Class Program
Private Sub New()
End Sub
''' <summary>
''' The main entry point for the application.
''' </summary>
<STAThread> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
DevExpress.Skins.SkinManager.EnableFormSkins()
Application.Run(New Form1())
End Sub
End Class
End Namespace
Object FreeTimeCalculator
See Also