在DayOfWeek列表中查找最近一周的日期
这可能是一个新手问题,但在这里。
我有一种方法,其中的DayOfWeek列表会附上一周中的不同日子(可能是星期三和星期六,星期日,星期一和星期五等)。
鉴于该列表,我需要将它与Datetime参数进行比较,找到Day Day参数在DayOfWeek列表中最接近的日期,并根据它在列表中的哪个Week Day将Date添加到DateTime参数。
例如,如果传入的DateTime参数是星期日,并且我的DayOfWeek列表包含星期三和星期六,则该参数需要移回到星期六,因为它在列表中最接近。
同样,如果我的列表包含星期日,星期一和星期六,并且传入的参数是星期四,那么参数将不得不移至星期六。
最后,如果参数与列表中的两个星期的日期等距(星期三传入,星期一和星期五在列表中或星期日传入,星期二和星期五在列表中),则参数需要向前移动到下一个最近的一周(第一个例子是星期五,第二个例子是星期二)。
这将是理想的(至少对我来说),将下一个最接近的一周的距离从传入的日期转换为一个int,这样我可以执行如下操作:
passedInDate = passedInDate.AddDays(dayOfWeekDistance);
return passedInDate;
但我愿意接受建议。
我已经尝试了LINQ语句,例如:
int dayOfWeekDistance = targetDayOfWeekList.Min(x => (x - passedInDate));
但无济于事。 必须有一些我错过的奇特的LINQ语句。
只是一个头向上,我无法工作的主要项目是从星期天返回到星期六,如果传入日期是星期日,并且列表中最近的星期几是星期六(同样,如果传入日期是星期一,最近一周是星期五,日期需要一直返回到星期五)。
请让我知道,如果我错过了什么,或者我只是没有道理。
欢迎所有帮助! 谢谢。
通过辅助函数,可以使用LINQ。
帮助函数使用效用函数计算一周中最近的一天来计算两个DOW之间的前向天数:
public int MinDOWDistance(DayOfWeek dow1, DayOfWeek dow2) {
int FwdDaysDiff(int idow1, int idow2) => idow2 - idow1 + ((idow1 > idow2) ? 7 : 0);
int fwd12 = FwdDaysDiff((int)dow1, (int)dow2);
int fwd21 = FwdDaysDiff((int)dow2, (int)dow1);
return fwd12 < fwd21 ? fwd12 : -fwd21;
}
然后,您可以在列表中找到最近的DOW,并返回使用Aggregate
with LINQ移动(和方向)的正确天数:
public int DaysToClosestDOW(DayOfWeek dow1, List<DayOfWeek> dowList) {
return dowList.Select(dow => {
var cdow = MinDOWDistance(dow1, dow);
return new { dow, dist = cdow, absdist = Math.Abs(cdow) };
})
.Aggregate((g1, g2) => (g1.absdist < g2.absdist) ? g1 : ((g1.absdist == g2.absdist) ? ((g1.dist > 0) ? g1 : g2) : g2)).dist;
}
它发生在我身上,我可以使用一个元组来从辅助函数返回absdist
,因为它已经知道它。 然后我可以在LINQ中使用Tuple
:
public (int dist, int absdist) MinDOWDistance(DayOfWeek dow1, DayOfWeek dow2) {
int FwdDaysDiff(int idow1, int idow2) => idow2 - idow1 + ((idow1 > idow2) ? 7 : 0);
int fwd12 = FwdDaysDiff((int)dow1, (int)dow2);
int fwd21 = FwdDaysDiff((int)dow2, (int)dow1);
if (fwd12 < fwd21)
return (fwd12, fwd12);
else
return (-fwd21, fwd21);
}
public int DaysToClosestDOW(DayOfWeek dow1, List<DayOfWeek> dowList) {
return dowList.Select(dow => MinDOWDistance(dow1, dow))
.Aggregate((g1, g2) => (g1.absdist < g2.absdist) ? g1 : ((g1.absdist == g2.absdist) ? ((g1.dist > 0) ? g1 : g2) : g2)).dist;
}
让问题分成几个小部分。
注意:以下所有方法都应该放在类似这样的类中
public static class DayOfWeekExtensions
{
}
首先,您希望Sunday
成为本周的最后一天,而在DayOfWeek
enum
它首先定义。 所以让我们来说明一个函数:
public static int GetIndex(this DayOfWeek source)
{
return source == DayOfWeek.Sunday ? 6 : (int)source - 1;
}
然后我们需要一个函数来计算两个DayOfWeek
值之间的距离(偏移量):
public static int OffsetTo(this DayOfWeek source, DayOfWeek target)
{
return source.GetIndex() - target.GetIndex();
}
我们还需要添加一个给定主键的函数,并且两个DayOfWeek
值选择两个值中最接近的值(应用您的优先级规则):
public static DayOfWeek Closest(this DayOfWeek pivot, DayOfWeek first, DayOfWeek second)
{
int comp = Math.Abs(first.OffsetTo(pivot)).CompareTo(Math.Abs(second.OffsetTo(pivot)));
return comp < 0 || (comp == 0 && first.GetIndex() > pivot.GetIndex()) ? first : second;
}
现在我们准备实施从序列中找到最近的日子的方法。 它可以用很多方式实现,这里是使用(finally!:) LINQ Aggregate
方法的实现:
public static DayOfWeek? Closest(this IEnumerable<DayOfWeek> source, DayOfWeek target)
{
if (!source.Any()) return null;
return source.Aggregate((first, second) => target.Closest(first, second));
}
最后,让我们添加一个计算最近距离的函数:
public static int ClosestDistance(this IEnumerable<DayOfWeek> source, DayOfWeek target)
{
return source.Closest(target)?.OffsetTo(target) ?? 0;
}
我们完成了。 我们只创建了一个简单的可重用实用程序类。
你的情况的用法是:
int dayOfWeekDistance = targetDayOfWeekList.ClosestDistance(passedInDate.DayOfWeek);
更新:事实证明,您的要求是不同的。
应用相同的原则,首先我们需要一个函数来计算一周中两天之间的前后距离的最小值,应用前向优先规则。
public static int MinDistanceTo(this DayOfWeek from, DayOfWeek to)
{
int dist = to - from;
return dist >= 4 ? dist - 7 : dist <= -4 ? dist + 7 : dist;
}
它的作用主要是将值从可能的转换-6..6
包容范围值在-3..3
包含的范围。
然后我们只需要一个函数,它将通过使用Select
+ Aggregate
(它也可以用Min
和自定义比较器实现)来实现有问题的方法。 它基本上比较两个绝对距离,并再次应用正向优先规则:
public static int MinDistanceTo(this DayOfWeek from, IEnumerable<DayOfWeek> to)
{
if (!to.Any()) return 0;
return to.Select(x => from.MinDistanceTo(x)).Aggregate((dist1, dist2) =>
{
if (dist1 == dist2) return dist1;
int comp = Math.Abs(dist1).CompareTo(Math.Abs(dist2));
return comp < 0 || (comp == 0 && dist1 > 0) ? dist1 : dist2;
});
}
用法如下:
int dayOfWeekDistance = passedInDate.DayOfWeek.MinDistanceTo(targetDayOfWeekList);
链接地址: http://www.djcxy.com/p/54893.html