これはLINQでの私の試みです。
私はあなたのWorkRecord
がこのようなものだと仮定します。
public class WorkRecord
{
public readonly String name;
public readonly DateTime StarTime;
public readonly DateTime EndTime;
public WorkRecord(string name, DateTime starTime, DateTime endTime)
{
this.name = name;
StarTime = starTime;
EndTime = endTime;
}
public WorkRecord(string name, string starTime, string endTime)
{
this.name = name;
StarTime = DateTime.ParseExact(starTime, "HH:mm", null);
EndTime = DateTime.ParseExact(endTime, "HH:mm", null);
}
}
すでに1日前にフィルタリングされているかどうかは不明です。私は一日の集計結果を表し
public class DayStats
{
public readonly int[] TotalMinutes = new int[24];
public void AddWorkRecord(WorkRecord record)
{
// Note: this method doesn't handle case when EndTime is next day
// handle "middle" hours, they are all full
for (int hour = record.StarTime.Hour + 1; hour < record.EndTime.Hour; hour++)
{
TotalMinutes[hour] += 60;
}
// handle first and last hours that might be not full
if (record.StarTime.Hour == record.EndTime.Hour)
{
TotalMinutes[record.StarTime.Hour] += record.EndTime.Minute - record.StarTime.Minute;
}
else
{
TotalMinutes[record.StarTime.Hour] += 60 - record.StarTime.Minute;
TotalMinutes[record.EndTime.Hour] += record.EndTime.Minute;
}
}
public string AsPrettyString()
{
return string.Join("\n", TotalMinutes
.Select((totalMinutes, hour) => string.Format("{0}-{1} {2}", hour, hour + 1, totalMinutes)));
}
}
public class TimeCardAggregate
{
private readonly Dictionary<DateTime, DayStats> _days = new Dictionary<DateTime, DayStats>();
public void AddWorkRecord(WorkRecord record)
{
// Note: this method doesn't handle case when EndTime is next day
var date = record.StarTime.Date;
DayStats dayStats;
if (!_days.TryGetValue(date, out dayStats))
{
dayStats = new DayStats();
_days.Add(date, dayStats);
}
dayStats.AddWorkRecord(record);
}
public List<KeyValuePair<DateTime, DayStats>> GetTimecard()
{
return _days.ToList().OrderBy(kv => kv.Key).ToList();
}
}
DayStats
(それでも単純化)の両方のケースをカバーしようとするでしょう。 TimeCardAggregate
は数日間の結果です。ほとんどの作業は、Aggregate
LINQメソッドから使用できる両方のクラスのヘルパーメソッドAddWorkRecord
によって行われます。あなたがそれらを使用する方法を参照してください。
static void Main(string[] args)
{
List<WorkRecord> records = new List<WorkRecord>
{
new WorkRecord("Cindy", "07:00", "11:15"),
new WorkRecord("Jim", "08:22", "12:30"),
new WorkRecord("Jim", "12:12", "15:30"),
new WorkRecord("Cindy", "12:55", "17:00")
};
var dayStats = records.Aggregate(new DayStats(), (ds, wr) =>
{
ds.AddWorkRecord(wr);
return ds;
});
Console.WriteLine(dayStats.AsPrettyString());
List<WorkRecord> recordsForTwoDays = new List<WorkRecord>();
recordsForTwoDays.AddRange(records);
// just copy the data for the next day
recordsForTwoDays.AddRange(records.Select(wr => new WorkRecord(wr.name, wr.StarTime.AddDays(1), wr.StarTime.AddDays(1))));
var timecard = recordsForTwoDays.Aggregate(new TimeCardAggregate(), (ds, wr) =>
{
ds.AddWorkRecord(wr);
return ds;
});
Console.WriteLine("\n\n");
Console.WriteLine(string.Join("\n-------------\n", timecard.GetTimecard().Select(kv =>
{
return kv.Key.ToShortDateString() + ":\n" + dayStats.AsPrettyString();
})));
}
も注意し、AddWorkRecord
の両方の実装はナイーブであり、誰かが一晩働いたケースを処理し、数日間にわたって記録産卵を持っていないこと。しかし、それを修正することは非常に難しいことではありません。