using System;
using System.Collections.Generic;
using System.Linq;
namespace TimeClock
{
class Program
{
static void Main()
{
var blockStart = new TimeSpan(0, 6, 0, 0);
var blockEnd = new TimeSpan(0, 17, 0, 0);
var listOfTimeLogs = new List<TimeLog>
{
new TimeLog {EntryDateTime = new DateTime(2016,05,20,6,0,0),EntryType = EntryTypes.In},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,10,0,0),EntryType = EntryTypes.Out},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,10,15,0),EntryType = EntryTypes.In},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,12,0,0),EntryType = EntryTypes.Out},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,12,30,0),EntryType = EntryTypes.In},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,15,0,0),EntryType = EntryTypes.Out},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,15,15,0),EntryType = EntryTypes.In},
new TimeLog {EntryDateTime = new DateTime(2016,05,20,18,00,0),EntryType = EntryTypes.Out}
};
// You are going to have have for / for each unless you use Linq
// fist I would count clock in's versus the out's
var totalIn = listOfTimeLogs.Count(e => e.EntryType == EntryTypes.In);
var totalOut = listOfTimeLogs.Count() - totalIn;
// check if we have in the number of time entries
if (totalIn > totalOut)
{
Console.WriteLine("Employee didn't clock out");
}
// as I was coding this sample program, i thought of another way to store the time
// I would store them in blocks - we have to loop
var timeBlocks = new List<TimeBlock>();
for (var x = 0; x < listOfTimeLogs.Count; x += 2)
{
// create a new WORKING block based on the in/out time entries
timeBlocks.Add(new TimeBlock
{
BlockType = BlockTypes.Working,
In = listOfTimeLogs[x],
Out = listOfTimeLogs[x + 1]
});
// create a BREAK block based on gaps
// check if the next entry in a clock in
var breakOut = x + 2;
if (breakOut < listOfTimeLogs.Count)
{
var breakIn = x + 1;
// create a new BREAK block
timeBlocks.Add(new TimeBlock
{
BlockType = BlockTypes.Break,
In = listOfTimeLogs[breakIn],
Out = listOfTimeLogs[breakOut]
});
}
}
var breakCount = 0;
// here is a loop for displaying detail
foreach (var block in timeBlocks)
{
var lineTitle = block.BlockType.ToString();
// this is me trying to be fancy
if (block.BlockType == BlockTypes.Break)
{
if (block.IsBreak())
{
lineTitle = $"Break #{++breakCount}";
}
else
{
lineTitle = "Lunch";
}
}
Console.WriteLine($" {lineTitle,-10} {block} === Length: {block.Duration.ToString(@"hh\:mm")}");
}
// calculating total time for each block type
var workingTime = timeBlocks.Where(b => b.BlockType == BlockTypes.Working)
.Aggregate(new TimeSpan(0), (p, v) => p.Add(v.Duration));
var breakTime = timeBlocks.Where(b => b.BlockType == BlockTypes.Break)
.Aggregate(new TimeSpan(0), (p, v) => p.Add(v.Duration));
Console.WriteLine($"\nTotal Working Hours: {workingTime.ToString(@"hh\:mm")}");
Console.WriteLine($" Total Break Time: {breakTime.ToString(@"hh\:mm")}");
Console.ReadLine();
}
}
public enum EntryTypes
{
In,
Out
}
public enum BlockTypes
{
Working,
Break
}
public class TimeBlock
{
public BlockTypes BlockType;
public TimeLog In;
public TimeLog Out;
public TimeSpan Duration
{
get
{
// TODO: Need error checking
return Out.EntryDateTime.Subtract(In.EntryDateTime);
}
}
public override string ToString()
{
return $"In: {In.EntryDateTime:HH:mm} - Out: {Out.EntryDateTime:HH:mm}";
}
}
// a little extension class
public static class Extensions
{
public static bool IsBreak(this TimeBlock block)
{
// if the length of the break period is less than 19 minutes
// we will consider it a break, the person could have clock IN late
return block.Duration.TotalMinutes < 19 ? true : false;
}
}
public class TimeLog
{
public DateTime EntryDateTime;
public EntryTypes EntryType;
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkxpbnE7CgpuYW1lc3BhY2UgVGltZUNsb2NrCnsKICAgIGNsYXNzIFByb2dyYW0KICAgIHsKICAgICAgICBzdGF0aWMgdm9pZCBNYWluKCkKICAgICAgICB7CiAgICAgICAgICAgIHZhciBibG9ja1N0YXJ0ID0gbmV3IFRpbWVTcGFuKDAsIDYsIDAsIDApOwogICAgICAgICAgICB2YXIgYmxvY2tFbmQgPSBuZXcgVGltZVNwYW4oMCwgMTcsIDAsIDApOwoKICAgICAgICAgICAgdmFyIGxpc3RPZlRpbWVMb2dzID0gbmV3IExpc3Q8VGltZUxvZz4KICAgICAgICAgICAgewogICAgICAgICAgICAgICAgbmV3IFRpbWVMb2cge0VudHJ5RGF0ZVRpbWUgPSBuZXcgRGF0ZVRpbWUoMjAxNiwwNSwyMCw2LDAsMCksRW50cnlUeXBlID0gRW50cnlUeXBlcy5Jbn0sCiAgICAgICAgICAgICAgICBuZXcgVGltZUxvZyB7RW50cnlEYXRlVGltZSA9IG5ldyBEYXRlVGltZSgyMDE2LDA1LDIwLDEwLDAsMCksRW50cnlUeXBlID0gRW50cnlUeXBlcy5PdXR9LAogICAgICAgICAgICAgICAgbmV3IFRpbWVMb2cge0VudHJ5RGF0ZVRpbWUgPSBuZXcgRGF0ZVRpbWUoMjAxNiwwNSwyMCwxMCwxNSwwKSxFbnRyeVR5cGUgPSBFbnRyeVR5cGVzLklufSwKICAgICAgICAgICAgICAgIG5ldyBUaW1lTG9nIHtFbnRyeURhdGVUaW1lID0gbmV3IERhdGVUaW1lKDIwMTYsMDUsMjAsMTIsMCwwKSxFbnRyeVR5cGUgPSBFbnRyeVR5cGVzLk91dH0sCiAgICAgICAgICAgICAgICBuZXcgVGltZUxvZyB7RW50cnlEYXRlVGltZSA9IG5ldyBEYXRlVGltZSgyMDE2LDA1LDIwLDEyLDMwLDApLEVudHJ5VHlwZSA9IEVudHJ5VHlwZXMuSW59LAogICAgICAgICAgICAgICAgbmV3IFRpbWVMb2cge0VudHJ5RGF0ZVRpbWUgPSBuZXcgRGF0ZVRpbWUoMjAxNiwwNSwyMCwxNSwwLDApLEVudHJ5VHlwZSA9IEVudHJ5VHlwZXMuT3V0fSwKICAgICAgICAgICAgICAgIG5ldyBUaW1lTG9nIHtFbnRyeURhdGVUaW1lID0gbmV3IERhdGVUaW1lKDIwMTYsMDUsMjAsMTUsMTUsMCksRW50cnlUeXBlID0gRW50cnlUeXBlcy5Jbn0sCiAgICAgICAgICAgICAgICBuZXcgVGltZUxvZyB7RW50cnlEYXRlVGltZSA9IG5ldyBEYXRlVGltZSgyMDE2LDA1LDIwLDE4LDAwLDApLEVudHJ5VHlwZSA9IEVudHJ5VHlwZXMuT3V0fQogICAgICAgICAgICB9OwoKCiAgICAgICAgICAgIC8vIFlvdSBhcmUgZ29pbmcgdG8gaGF2ZSBoYXZlIGZvciAvIGZvciBlYWNoIHVubGVzcyB5b3UgdXNlIExpbnEKCiAgICAgICAgICAgIC8vIGZpc3QgSSB3b3VsZCBjb3VudCBjbG9jayBpbidzIHZlcnN1cyB0aGUgb3V0J3MKICAgICAgICAgICAgdmFyIHRvdGFsSW4gPSBsaXN0T2ZUaW1lTG9ncy5Db3VudChlID0+IGUuRW50cnlUeXBlID09IEVudHJ5VHlwZXMuSW4pOwogICAgICAgICAgICB2YXIgdG90YWxPdXQgPSBsaXN0T2ZUaW1lTG9ncy5Db3VudCgpIC0gdG90YWxJbjsKCiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHdlIGhhdmUgaW4gdGhlIG51bWJlciBvZiB0aW1lIGVudHJpZXMKICAgICAgICAgICAgaWYgKHRvdGFsSW4gPiB0b3RhbE91dCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIkVtcGxveWVlIGRpZG4ndCBjbG9jayBvdXQiKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gYXMgSSB3YXMgY29kaW5nIHRoaXMgc2FtcGxlIHByb2dyYW0sIGkgdGhvdWdodCBvZiBhbm90aGVyIHdheSB0byBzdG9yZSB0aGUgdGltZQogICAgICAgICAgICAvLyBJIHdvdWxkIHN0b3JlIHRoZW0gaW4gYmxvY2tzIC0gd2UgaGF2ZSB0byBsb29wCiAgICAgICAgICAgIHZhciB0aW1lQmxvY2tzID0gbmV3IExpc3Q8VGltZUJsb2NrPigpOwogICAgICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGxpc3RPZlRpbWVMb2dzLkNvdW50OyB4ICs9IDIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSBhIG5ldyBXT1JLSU5HIGJsb2NrIGJhc2VkIG9uIHRoZSBpbi9vdXQgdGltZSBlbnRyaWVzCiAgICAgICAgICAgICAgICB0aW1lQmxvY2tzLkFkZChuZXcgVGltZUJsb2NrCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgQmxvY2tUeXBlID0gQmxvY2tUeXBlcy5Xb3JraW5nLAogICAgICAgICAgICAgICAgICAgIEluID0gbGlzdE9mVGltZUxvZ3NbeF0sCiAgICAgICAgICAgICAgICAgICAgT3V0ID0gbGlzdE9mVGltZUxvZ3NbeCArIDFdCiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgYSBCUkVBSyBibG9jayBiYXNlZCBvbiBnYXBzCiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgbmV4dCBlbnRyeSBpbiBhIGNsb2NrIGluCiAgICAgICAgICAgICAgICB2YXIgYnJlYWtPdXQgPSB4ICsgMjsKICAgICAgICAgICAgICAgIGlmIChicmVha091dCA8IGxpc3RPZlRpbWVMb2dzLkNvdW50KQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHZhciBicmVha0luID0geCArIDE7CiAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIGEgbmV3IEJSRUFLIGJsb2NrCiAgICAgICAgICAgICAgICAgICAgdGltZUJsb2Nrcy5BZGQobmV3IFRpbWVCbG9jawogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgQmxvY2tUeXBlID0gQmxvY2tUeXBlcy5CcmVhaywKICAgICAgICAgICAgICAgICAgICAgICAgSW4gPSBsaXN0T2ZUaW1lTG9nc1ticmVha0luXSwKICAgICAgICAgICAgICAgICAgICAgICAgT3V0ID0gbGlzdE9mVGltZUxvZ3NbYnJlYWtPdXRdCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZhciBicmVha0NvdW50ID0gMDsKICAgICAgICAgICAgLy8gaGVyZSBpcyBhIGxvb3AgZm9yIGRpc3BsYXlpbmcgZGV0YWlsCiAgICAgICAgICAgIGZvcmVhY2ggKHZhciBibG9jayBpbiB0aW1lQmxvY2tzKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB2YXIgbGluZVRpdGxlID0gYmxvY2suQmxvY2tUeXBlLlRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIG1lIHRyeWluZyB0byBiZSBmYW5jeQogICAgICAgICAgICAgICAgaWYgKGJsb2NrLkJsb2NrVHlwZSA9PSBCbG9ja1R5cGVzLkJyZWFrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChibG9jay5Jc0JyZWFrKCkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBsaW5lVGl0bGUgPSAkIkJyZWFrICN7KyticmVha0NvdW50fSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVUaXRsZSA9ICJMdW5jaCI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoJCIge2xpbmVUaXRsZSwtMTB9IHtibG9ja30gID09PSAgTGVuZ3RoOiB7YmxvY2suRHVyYXRpb24uVG9TdHJpbmcoQCJoaFw6bW0iKX0iKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gY2FsY3VsYXRpbmcgdG90YWwgdGltZSBmb3IgZWFjaCBibG9jayB0eXBlCiAgICAgICAgICAgIHZhciB3b3JraW5nVGltZSA9IHRpbWVCbG9ja3MuV2hlcmUoYiA9PiBiLkJsb2NrVHlwZSA9PSBCbG9ja1R5cGVzLldvcmtpbmcpCiAgICAgICAgICAgICAgICAgICAgLkFnZ3JlZ2F0ZShuZXcgVGltZVNwYW4oMCksIChwLCB2KSA9PiBwLkFkZCh2LkR1cmF0aW9uKSk7CgogICAgICAgICAgICB2YXIgYnJlYWtUaW1lID0gdGltZUJsb2Nrcy5XaGVyZShiID0+IGIuQmxvY2tUeXBlID09IEJsb2NrVHlwZXMuQnJlYWspCiAgICAgICAgICAgICAgICAgICAgLkFnZ3JlZ2F0ZShuZXcgVGltZVNwYW4oMCksIChwLCB2KSA9PiBwLkFkZCh2LkR1cmF0aW9uKSk7CgoKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoJCJcblRvdGFsIFdvcmtpbmcgSG91cnM6IHt3b3JraW5nVGltZS5Ub1N0cmluZyhAImhoXDptbSIpfSIpOwogICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZSgkIiAgIFRvdGFsIEJyZWFrIFRpbWU6IHticmVha1RpbWUuVG9TdHJpbmcoQCJoaFw6bW0iKX0iKTsKCiAgICAgICAgICAgIENvbnNvbGUuUmVhZExpbmUoKTsKICAgICAgICB9CiAgICB9CiAgICAKICAgIHB1YmxpYyBlbnVtIEVudHJ5VHlwZXMKICAgIHsKICAgICAgICBJbiwKICAgICAgICBPdXQKICAgIH0KICAgIAogICAgcHVibGljIGVudW0gQmxvY2tUeXBlcwogICAgewogICAgICAgIFdvcmtpbmcsCiAgICAgICAgQnJlYWsKICAgIH0KCiAgICBwdWJsaWMgY2xhc3MgVGltZUJsb2NrCiAgICB7CiAgICAgICAgcHVibGljIEJsb2NrVHlwZXMgQmxvY2tUeXBlOwogICAgICAgIHB1YmxpYyBUaW1lTG9nIEluOwogICAgICAgIHB1YmxpYyBUaW1lTG9nIE91dDsKCiAgICAgICAgcHVibGljIFRpbWVTcGFuIER1cmF0aW9uCiAgICAgICAgewogICAgICAgICAgICBnZXQKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gVE9ETzogTmVlZCBlcnJvciBjaGVja2luZwogICAgICAgICAgICAgICAgcmV0dXJuIE91dC5FbnRyeURhdGVUaW1lLlN1YnRyYWN0KEluLkVudHJ5RGF0ZVRpbWUpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgb3ZlcnJpZGUgc3RyaW5nIFRvU3RyaW5nKCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAkIkluOiB7SW4uRW50cnlEYXRlVGltZTpISDptbX0gLSBPdXQ6IHtPdXQuRW50cnlEYXRlVGltZTpISDptbX0iOwogICAgICAgIH0KCiAgICB9CgogICAgLy8gYSBsaXR0bGUgZXh0ZW5zaW9uIGNsYXNzCiAgICBwdWJsaWMgc3RhdGljIGNsYXNzIEV4dGVuc2lvbnMKICAgIHsKICAgICAgICBwdWJsaWMgc3RhdGljIGJvb2wgSXNCcmVhayh0aGlzIFRpbWVCbG9jayBibG9jaykKICAgICAgICB7CiAgICAgICAgICAgIC8vIGlmIHRoZSBsZW5ndGggb2YgdGhlIGJyZWFrIHBlcmlvZCBpcyBsZXNzIHRoYW4gMTkgbWludXRlcwogICAgICAgICAgICAvLyB3ZSB3aWxsIGNvbnNpZGVyIGl0IGEgYnJlYWssIHRoZSBwZXJzb24gY291bGQgaGF2ZSBjbG9jayBJTiBsYXRlCiAgICAgICAgICAgIHJldHVybiBibG9jay5EdXJhdGlvbi5Ub3RhbE1pbnV0ZXMgPCAxOSA/IHRydWUgOiBmYWxzZTsKCiAgICAgICAgfQoKICAgIH0KICAgIAogICAgcHVibGljIGNsYXNzIFRpbWVMb2cKICAgIHsKICAgICAgICBwdWJsaWMgRGF0ZVRpbWUgRW50cnlEYXRlVGltZTsKICAgICAgICBwdWJsaWMgRW50cnlUeXBlcyBFbnRyeVR5cGU7CiAgICB9Cn0K