One of the goals this year is to have an average response time of 15 minutes for all helpdesk tickets, but we have one problem, no way to track or know if we’re getting closer.
During my initial research, the only thing I could find was code that couldn’t be customized through configuration files so it would be easier for management to configure later. Since the tool we wanted to get the reports from was Eventum, I originally wrote this in PHP, but it proved way to slow and so I converted it into a C# app to handle the calculations.
Besides the code below, you’ll need masks.xml, which holds the info about business hours.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace eventum_responsetime
{
class Program
{
//businesshours.exe -created "any date format DateTime can parse" -response "any date format DateTime can parse"
static void Main(string[] args)
{
System.DateTime base_unixtime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
long int_base_unixtime = base_unixtime.Ticks / 10000000;
if (args == null || args.Length == 0)
{
args = new string[] { "nothing" };
}
System.Collections.Hashtable hargs = new System.Collections.Hashtable();
hargs.Add("nothing", Array.Find(args, (delegate(string s) { if (s.ToLower() == "nothing") { return true; } return false; })));
hargs.Add("created", args[Array.FindIndex(args, (delegate(string s) { if (s.ToLower() == "-created") { return true; } return false; })) + 1]);
hargs.Add("response", args[Array.FindIndex(args, (delegate(string s) { if (s.ToLower() == "-response") { return true; } return false; })) + 1]);
//Load the masked times xml.
XmlDocument xmld = new XmlDocument();
xmld.Load("./masks.xml");
XmlNodeList masks = xmld.GetElementsByTagName("mask");
nonWorkRanges[] a = new nonWorkRanges[masks.Count];
long ticks = 0;
for(int i=0;i<a.Length;i++) {
XmlNode n = masks[i];
//Load up the masks
a[i] = new nonWorkRanges();
a[i].start.weekday = (n["start"].Attributes["weekday"] == null) ? 0 : int.Parse(n["start"].Attributes["weekday"].Value);
a[i].start.hour = (n["start"].Attributes["hour"]==null)? 0 : int.Parse(n["start"].Attributes["hour"].Value);
a[i].start.minute = (n["start"].Attributes["minute"]== null) ? 0 : int.Parse(n["start"].Attributes["minute"].Value);
a[i].start.second = (n["start"].Attributes["second"] == null) ? 0 : int.Parse(n["start"].Attributes["second"].Value);
a[i].end.weekday = (n["end"].Attributes["weekday"] == null) ? 0 : int.Parse(n["end"].Attributes["weekday"].Value);
a[i].end.hour = (n["end"].Attributes["hour"] == null) ? 0 : int.Parse(n["end"].Attributes["hour"].Value);
a[i].end.minute = (n["end"].Attributes["minute"] == null) ? 0 : int.Parse(n["end"].Attributes["minute"].Value);
a[i].end.second = (n["end"].Attributes["second"] == null) ? 0 : int.Parse(n["end"].Attributes["second"].Value);
ticks += a[i].ticks(DateTime.Parse(hargs["created"].ToString()), DateTime.Parse(hargs["response"].ToString()));
}
//Output how much business time elapsed.
Console.WriteLine(ticks.ToString());
}
}
abstract class mask {
public int weekday;
public int hour;
public int minute;
public int second;
public DateTime time;
}
class startMask : mask
{
}
class endMask : mask
{
}
class nonWorkRanges
{
public startMask start;
public endMask end;
public nonWorkRanges()
{
this.start = new startMask();
this.end = new endMask();
}
public long ticks(DateTime created, DateTime response)
{
if (start.weekday != null && end.weekday != null)
{
long ticks = 0;
int days = (response - created).Days + 1;
DateTime basetime = new DateTime(created.Year, created.Month, created.Day, 0, 0, 0);
for (int dayi = 0; dayi < days; dayi++)
{
DateTime day_start = new DateTime(basetime.Year, basetime.Month, basetime.Day, 0, 0, 0);
day_start.AddDays(dayi);
DateTime day_end = new DateTime(basetime.Year, basetime.Month, basetime.Day, 23, 59, 59);
day_end.AddDays(dayi);
int dow = (int)(day_start.DayOfWeek);
if (start.weekday < end.weekday && (dow < start.weekday || dow > end.weekday))
{
continue;
}
if (start.weekday > end.weekday && (dow > start.weekday || dow < end.weekday))
{
continue;
}
DateTime mask_start = new DateTime(day_start.Year, day_start.Month, day_start.Day, start.hour, start.minute, start.second);
mask_start = mask_start.AddDays(-dow).AddDays(start.weekday);
DateTime mask_end = new DateTime(day_start.Year, day_start.Month, day_start.Day, end.hour, end.minute, end.second);
mask_end = mask_end.AddDays(-dow).AddDays(end.weekday);
for (int i = 0; i < 86400; i++)
{
DateTime loc = day_start.AddSeconds(i);
//Simply to make reading the if block easier.
bool[] tf = new bool[] {
loc < created,
loc > response,
loc < mask_start,
loc > mask_end
};
if((!tf[0] && !tf[1]) && (!tf[2] && !tf[3]))
{
ticks++;
}
}
}
return ticks;
}
return 0;
}
}
}


[...] JoshErickson.org, it’s dot com! Threshold! Take us to the threshold! Skip to content HomeFlickrTwitterAboutLinkedIn « Time filtering for helpdesks [...]
[...] a clightly cleaned up and better version of my time filter project thing, businesshours.zip. Archive contains code, build batch file, and [...]