给定一个日期范围,我需要知道在该范围内有多少个星期一(或星期二、星期三等)。
我目前在使用C#进行工作。
试试这个:
static int CountDays(DayOfWeek day, DateTime start, DateTime end)
{
TimeSpan ts = end - start; // Total duration
int count = (int)Math.Floor(ts.TotalDays / 7); // Number of whole weeks
int remainder = (int)(ts.TotalDays % 7); // Number of remaining days
int sinceLastDay = (int)(end.DayOfWeek - day); // Number of days since last [day]
if (sinceLastDay < 0) sinceLastDay += 7; // Adjust for negative days since last [day]
// If the days in excess of an even week are greater than or equal to the number days since the last [day], then count this one, too.
if (remainder >= sinceLastDay) count++;
return count;
}
如果你正在使用C#,且版本为C#3.0,则可以使用LINQ。
假设你有一个包含日期类型DateTime的数组/列表/IQueryable等:
DateTime[] dates = { new DateTime(2008,10,6), new DateTime(2008,10,7)}; //etc....
var mondays = dates.Where(d => d.DayOfWeek == DayOfWeek.Monday); // = {10/6/2008}
新增:
不确定您是否想对它们进行分组并计数,但以下是如何在LINQ中完成此操作的方法:
var datesgrouped = from d in dates
group d by d.DayOfWeek into grouped
select new { WeekDay = grouped.Key, Days = grouped };
foreach (var g in datesgrouped)
{
Console.Write (String.Format("{0} : {1}", g.WeekDay,g.Days.Count());
}
研究不同算法来计算星期几是非常有趣的,@Gabe Hollombe提供的关于这个主题的WP链接是一个好主意(我还记得大约二十年前在COBOL中实现过Zeller's Congruence),但这更像是在给人一个时钟的设计图而不是回答他们所问的时间。
C#代码:
private int CountMondays(DateTime startDate, DateTime endDate)
{
int mondayCount = 0;
for (DateTime dt = startDate; dt < endDate; dt = dt.AddDays(1.0))
{
if (dt.DayOfWeek == DayOfWeek.Monday)
{
mondayCount++;
}
}
return mondayCount;
}
当然,这并不评估“星期一”结束日期,因此如果需要,请使for循环进行评估。
dt < endDate.AddDays(1.0)
以下是一些伪代码:
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
DifferenceInDays
返回 End - Start
的天数差,DayOfWeek
返回星期几的整数表示。 DayOfWeek
使用的映射不是很重要,只要它是递增的,并且与 DayImLookingFor
匹配即可。End
不应该是范围的一部分,则需要稍微调整算法。有特定的语言和日期格式吗?
如果日期表示为天数计数,则两个值之间的差加一(天),再除以7,就是大部分答案。如果两个结束日期都是所询问的那一天,则再加一。
编辑:更正“模7”为“除以7” - 谢谢。这是整数除法。
public List<DateTime> GetSelectedDaysInPeriod(DateTime startDate, DateTime endDate, List<DayOfWeek> daysToCheck)
{
var selectedDates = new List<DateTime>();
if (startDate >= endDate)
return selectedDates; //No days to return
if (daysToCheck == null || daysToCheck.Count == 0)
return selectedDates; //No days to select
try
{
//Get the total number of days between the two dates
var totalDays = (int)endDate.Subtract(startDate).TotalDays;
//So.. we're creating a list of all dates between the two dates:
var allDatesQry = from d in Enumerable.Range(1, totalDays)
select new DateTime(
startDate.AddDays(d).Year,
startDate.AddDays(d).Month,
startDate.AddDays(d).Day);
//And extracting those weekdays we explicitly wanted to return
var selectedDatesQry = from d in allDatesQry
where daysToCheck.Contains(d.DayOfWeek)
select d;
//Copying the IEnumerable to a List
selectedDates = selectedDatesQry.ToList();
}
catch (Exception ex)
{
//Log error
//...
//And re-throw
throw;
}
return selectedDates;
}
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
到
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayImLookingFor is between Start.Day and End.Day
使用between函数,如果从开始日期开始,我们在结束日期之前首先遇到了dayImLookingFor,则返回true。
我通过计算从startDay到另外两个日期的天数来完成between函数:
private int CountDays(DateTime start, DateTime end, DayOfWeek selectedDay)
{
if (start.Date > end.Date)
{
return 0;
}
int totalDays = (int)end.Date.Subtract(start.Date).TotalDays;
DayOfWeek startDay = start.DayOfWeek;
DayOfWeek endDay = end.DayOfWeek;
///look if endDay appears before or after the selectedDay when we start from startDay.
int startToEnd = (int)endDay - (int)startDay;
if (startToEnd < 0)
{
startToEnd += 7;
}
int startToSelected = (int)selectedDay - (int)startDay;
if (startToSelected < 0)
{
startToSelected += 7;
}
bool isSelectedBetweenStartAndEnd = startToEnd >= startToSelected;
if (isSelectedBetweenStartAndEnd)
{
return totalDays / 7 + 1;
}
else
{
return totalDays / 7;
}
}
这将返回一个整数集合,显示日期范围内每个星期几出现的次数
int[] CountDays(DateTime firstDate, DateTime lastDate)
{
var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
var weeks = (int)Math.Floor(totalDays / 7);
var result = Enumerable.Repeat<int>(weeks, 7).ToArray();
if (totalDays % 7 != 0)
{
int firstDayOfWeek = (int)firstDate.DayOfWeek;
int lastDayOfWeek = (int)lastDate.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
result[dayOfWeek % 7]++;
}
return result;
}
或者稍作改动,允许您执行FirstDate.TotalDaysOfWeeks(SecondDate)并返回一个字典
public static Dictionary<DayOfWeek, int> TotalDaysOfWeeks(this DateTime firstDate, DateTime lastDate)
{
var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
var weeks = (int)Math.Floor(totalDays / 7);
var resultArray = Enumerable.Repeat<int>(weeks, 7).ToArray();
if (totalDays % 7 != 0)
{
int firstDayOfWeek = (int)firstDate.DayOfWeek;
int lastDayOfWeek = (int)lastDate.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
resultArray[dayOfWeek % 7]++;
}
var result = new Dictionary<DayOfWeek, int>();
for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
result[(DayOfWeek)dayOfWeek] = resultArray[dayOfWeek];
return result;
}
加上最小的数使第一天成为星期一。减去最小的数使最后一天成为星期一。计算天数差并除以7。
将日期转换为儒略日数,然后进行一些数学计算。由于星期一是模7的零,因此您可以像这样进行计算:
JD1=JulianDayOf(the_first_date)
JD2=JulianDayOf(the_second_date)
Round JD1 up to nearest multiple of 7
Round JD2 up to nearest multiple of 7
d = JD2-JD1
nMondays = (JD2-JD1+7)/7 # integer divide