c# - 检查块时间存在
问题描述
我需要一些帮助来正确检查工人是否离开街区超过 15 分钟。我在工人的工作时间内对他进行不同的检查,并检查他在时间段内的存在。这是我对代码的尝试,该代码目前不适用于:块类(我在其中获取块的开始和结束)
public class Block
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
带有阻止列表的示例,两个阻止(早上和下午)这是列表中的时间的样子
List<Block> blocks = new List<Block>();
[0] = End{12/30/1899 11:45:00 AM}
[0] = Start{12/30/1899 8:30:00 AM}
[1] = End{12/30/1899 5:00:00 PM}
[1] = Start{12/30/1899 1:15:00 PM}
现在,我在数据库中以这种形式获得了工人的到达和离开:
List<Presence> presence = new List<Presence>();
time received in the presence list:
arrival departure
1899-12-30 08:03:00.000; 1899-12-30 09:21:00.000
1899-12-30 09:36:00.000; 1899-12-30 10:34:00.000
1899-12-30 10:45:00.000; 1899-12-30 12:05:00.000
1899-12-30 13:03:00.000; 1899-12-30 14:24:00.000
1899-12-30 14:34:00.000; 1899-12-30 16:14:00.000
1899-12-30 16:27:00.000; 1899-12-30 18:02:00.000
因此,对于每个街区,我需要检查工人是否缺席> 15 分钟。我该如何检查?
这是我当前的代码。
public class Block
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
public class Presence
{
public DateTime Arrival { get; set; }
public DateTime Departure { get; set; }
public TimeSpan FlightTime => Arrival - Departure;
}
public static class PresenceExtensions
{
public static TimeSpan GetTotalFlightTime(this IEnumerable<Presence> presences)
{
return new TimeSpan(presences.Sum(r => r.FlightTime.Ticks));
}
}
public static class BlockExtensions
{
public static Dictionary<Block, IEnumerable<Presence>> FilterPresences(this IEnumerable<Block> blocks, IEnumerable<Presence> presences)
{
Dictionary<Block, IEnumerable<Presence>> result = new Dictionary<Block, IEnumerable<Presence>>();
foreach (Block block in blocks)
{
result.Add(block, presences.Where(p => p.Arrival <= block.End && p.Departure >= block.Start));
}
return result;
}
}
用法:
List<Block> blocks = new List<Block>();
List<Presence> presences = new List<Presence>();
Dictionary<Block, IEnumerable<Presence>> filteredList = blocks.FilterPresences(presences);
foreach (KeyValuePair<Block, IEnumerable<Presence>> pair in filteredList)
{
if (pair.Value.GetTotalFlightTime() > 15){
Console.WriteLine("The worker is out of the block for more than 15 min")}
}
我的一位同事向我建议了 检测重叠时段的算法,但我无法计算这段时间之间的数量,我真的需要解决这个问题,我这几天一直有这个问题。请理解。
我用他的例子尝试了这段代码,但没有找到正确的解决方案。
if(presences.Any(x=>blocks.Any(b=> x.Arrival < b.End && b.Start < x.Departure)))
{
errors.Add("The worker is out of the block for more than 15 min");
hasErrors = true;
}
当应该报告消息以取消阻止> 15 分钟时,我还设置了不同的选项。封锁时间:
第一节:08:30-11:45 第二节:13:15-17:00
工人的工作地点:
1. (first Day) 07:00-12:00 | 13:00-16:55 // all right
2. (second Day) 08:40-11:39 | 13:00-16:55 // missed in the first block> 15 min
3. (third Day) 08:30-09:00, 09:10-10:00, 10:15-12: 01 | 13:00-16: 55 // missed in the first block> 15 min
4. (fourt Day) 08:00-14:00 // Missed in the second block> 15 min
5. (fifth Day) 12:00-17:00 // Missed in first block> 15 min
public class Presence
{
public Presence(DateTime Arrival, DateTime Departure) { this.Arrival = Arrival; this.Departure = Departure; }
public DateTime Arrival { get; set; }
public DateTime Departure { get; set; }
public DateTime Date { get; set; } //added
public TimeSpan FlightTime;
public int UserID {get; set;} //added
}
Date Arrival Departure
2020-12-23 00:00:00.000 1899-12-30 08:30:00.000 1899-12-30 10:15:00.000
2020-12-23 00:00:00.000 1899-12-30 10:20:00.000 1899-12-30 12:20:00.000
2020-12-23 00:00:00.000 1899-12-30 13:25:00.000 1899-12-30 15:00:00.000
2020-12-23 00:00:00.000 1899-12-30 15:05:00.000 1899-12-30 17:00:00.000
2020-12-23 00:00:00.000 1899-12-30 17:05:00.000 1899-12-30 18:30:00.000
从数据库 prtsc
例如@Rufus 它看起来不错,几乎在所有地方都向我展示了当消息丢失超过 15 分钟时它应该如何查找消息,只有一个地方没有显示:工人工作:来自
new Presence {
Arrival = DateTime.Parse("1899-12-30 12:53:00.000"),
Departure = DateTime.Parse("1899-12-30 15:07:00.000") },
那天只有一个街区,它来自
new Block { Start = DateTime.Parse("12/30/1899 08:00:00 AM"),
End = DateTime.Parse("12/30/1899 16:30:00 PM"), },
解决方案
代码存在一些问题。
首先,FlightTime
计算将始终返回一个负数,因为它是从日期中减去Departure
日期Arrival
。Departure
如果日期来自 onePresence
并且Arrival
日期来自 next ,这可能是有意义的Presence
,但它不适用于单个Presence
.
接下来,与上述相关,GetTotalFlightTime
只是返回FlightTime
for each的总和Presence
,而不是检查a 中连续存在之间Block
的时间。
为了解决这个问题,我在Block
类中添加了一个方法,该方法接受 aList<Presence>
并返回缺席分钟数。此方法过滤掉任何Presence
不与块重叠的项目(就像您的扩展方法所做的那样),然后通过查看连续存在之间的时间跨度来计算“缺席时间”。它还检查第一个是否在块开始后Presence
到达,如果是,则添加该时间:
public class Block
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public double MinutesAbsent(IEnumerable<Presence> presences)
{
// Given a list of presences, select only those that overlap this block
var relevantPresences = Presence.CombineOverlapping(
presences?.Where(p => p?.OverlapsWith(this) == true))?
.OrderBy(p => p.Arrival)
.ToList();
// If there aren't any relevant presences, return the total minutes for this block
if (relevantPresences == null || relevantPresences.Count == 0)
return (End - Start).TotalMinutes;
// Get any absent minutes at the start of the block by determining
// if the first presence arrived after the block's start. If it did,
// begin with the difference between the block's Start and the
// first presence's Arrival.
var minutesAbsent = relevantPresences.First().Arrival > Start
? (relevantPresences.First().Arrival - Start).TotalMinutes
: 0;
// Then add the number of minutes between each presence's
// Departure and the next presence's Arrival
for (var i = 0; i < relevantPresences.Count - 1; i++)
{
minutesAbsent += (relevantPresences[i + 1].Arrival -
relevantPresences[i].Departure).TotalMinutes;
}
// Finally, add any minutes after the last presence
// if it departed before the end of the block
if (relevantPresences.Last().Departure < End)
minutesAbsent += (End - relevantPresences.Last().Departure).TotalMinutes;
return minutesAbsent;
}
}
public class Presence
{
public DateTime Arrival { get; set; }
public DateTime Departure { get; set; }
public TimeSpan FlightTime => Arrival - Departure;
public Presence(){ }
public Presence(DateTime arrival, DateTime departure)
{
Arrival = arrival;
Departure = departure;
}
public bool OverlapsWith(Block block)
{
return Arrival < block?.End && Departure > block.Start;
}
public static IEnumerable<Presence> CombineOverlapping(IEnumerable<Presence> presences)
{
var items = presences?.ToList()
.Where(p => p != null)
.OrderBy(presence => presence.Arrival)
.ToList();
if (items?.Any() != true) return items;
var combined = new List<Presence>();
var current = items.First();
for (var i = 1; i < items.Count; i++)
{
if (items[i].Arrival <= current.Departure)
{
if (items[i].Departure > current.Departure)
{
current.Departure = items[i].Departure;
}
}
else
{
combined.Add(current);
current = items[i];
}
}
combined.Add(current);
return combined;
}
public override string ToString()
{
return $"{Arrival} - {Departure}";
}
}
在使用中,它看起来像:
static void Main()
{
var blocks = GetSampleBlockData();
var presences = GetSamplePresenceData();
for(var i = 0; i < blocks.Count; i++)
{
var minutesAbsent = blocks[i].MinutesAbsent(presences);
if (minutesAbsent > 15)
{
Console.WriteLine("Error: User was absent for "+
$"{minutesAbsent} minutes in block # {i + 1}");
}
}
GetKeyFromUser("\nPress any key to exit...");
}
输出
为了完整起见,以下是生成示例数据的方法:
private static List<Block> GetSampleBlockData()
{
return new List<Block>
{
new Block
{
Start = DateTime.Parse("12/30/1899 8:30:00 AM"),
End = DateTime.Parse("12/30/1899 11:45:00 AM"),
},
new Block
{
Start = DateTime.Parse("12/30/1899 1:15:00 PM"),
End = DateTime.Parse("12/30/1899 5:00:00 PM"),
},
};
}
private static List<Presence> GetSamplePresenceData()
{
return new List<Presence>
{
new Presence
{
Arrival = DateTime.Parse("1899-12-30 08:03:00.000"),
Departure = DateTime.Parse("1899-12-30 09:21:00.000")
},
new Presence
{
Arrival = DateTime.Parse("1899-12-30 09:36:00.000"),
Departure = DateTime.Parse("1899-12-30 10:34:00.000")
},
new Presence
{
Arrival = DateTime.Parse("1899-12-30 10:45:00.000"),
Departure = DateTime.Parse("1899-12-30 12:05:00.000")
},
new Presence
{
Arrival = DateTime.Parse("1899-12-30 13:03:00.000"),
Departure = DateTime.Parse("1899-12-30 14:24:00.000")
},
new Presence
{
Arrival = DateTime.Parse("1899-12-30 14:34:00.000"),
Departure = DateTime.Parse("1899-12-30 16:14:00.000")
},
new Presence
{
Arrival = DateTime.Parse("1899-12-30 16:27:00.000"),
Departure = DateTime.Parse("1899-12-30 18:02:00.000")
},
};
}
推荐阅读
- nagios - 如果主机处于脱机状态,主机服务检查完全没有警告/警报
- java - 将数据从 excel 移动到 access 时出错
- apache-nifi - 如何清除 Nifi 1.9.2 中的所有队列?
- javascript - Javascript将空格替换为破折号,破折号前后的空格除外
- xamarin.forms - 在 xamarin.forms 中单击包含多个本地通知时,推送通知始终返回相同的 id
- python - 如何从列表中读取图像
- clips - 将规则导入 CLIPS 并评估其性能
- django - Django:测试时如何忽略函数中的部分代码
- node.js - Nodejs 10:为什么 DynamoDB 函数多次成功
- django - 根据其他字段设置新字段的值