Graf Zahl von montags in einem bestimmten Zeitraum
Frage
Bei einem Datumsbereich, muss ich wissen, wie viele montags (oder dienstags, mittwochs, etc.) sind in diesem Bereich.
Zur Zeit arbeite ich in C #.
Lösung
Versuchen Sie folgendes:
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;
}
Andere Tipps
Da Sie C # verwenden, wenn Sie C # 3.0 verwenden, können Sie LINQ verwenden.
Angenommen, Sie haben einen Array / Liste / IQueryable etc, die Ihre Termine als Datum- Typen enthalten:
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}
hinzugefügt:
Nicht sicher, ob Sie sie gemeint Gruppierung und Zählen sie, aber hier ist, wie das auch in LINQ tun:
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());
}
Es ist der Spaß an verschiedenen Algorithmus zu suchen, Tag der Woche zu berechnen und @Gabe Hollombe des Zeige über das Thema WP war eine großartige Idee (und ich erinnere mich Umsetzung
Hier ist ein Pseudo-Code: Wo Beachten Sie, dass dieser Algorithmus nimmt der Datumsbereich inklusive ist. Wenn Übersetzen von C # ist für den Leser als Übung. DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
DifferenceInDays
kehrt End - Start
in Tagen und DayOfWeek
gibt den Tag der Woche als Integer. Es spielt keine Rolle, welche Mapping DayOfWeek
verwendet, solange es nimmt zu und passt sich mit DayImLookingFor
. End
nicht Teil des Bereichs sein sollte, werden Sie den Algorithmus leicht anpassen.
Eine bestimmte Sprache und daher Datumsformat?
Wenn Daten als eine Anzahl von Tagen dargestellt werden, dann ist die Differenz zwischen zwei Werten plus eins (Tag) und Division durch 7, ist der größte Teil der Antwort. Wenn beide Enddaten der betreffenden Tag sind, hinzufügen.
Editiert: korrigiert 'Modulo-7' 'Division durch 7' - danke. Und das ist Integer-Division.
Ich habe über einen etwas einfacheren Weg kommen, um dieses Problem mit Linq zu lösen.
public static int NumberOfFridays(DateTime start, DateTime end)
{
return start.GetDaysInBetween(end, inclusive: true).Count(d => d.DayOfWeek == DayOfWeek.Friday);
}
Ich hoffe, das hilft.
Fügen Sie die kleinstmögliche Zahl am ersten Tag ein Montag zu machen. Subtrahieren Sie die kleinstmögliche Zahl den letzten Tag einen Montag zu machen. Berechnen Sie die Differenz in Tagen und dividieren durch 7.
konvertieren, die Daten zu Julian Tageszahl, dann ein wenig Mathematik tun. Seit Montag Null sind mod 7, könnten Sie die Berechnung wie folgt tun:
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
Ich habe das gleiche Bedürfnis heute hatte. Ich begann mit dem cjm Funktion, da ich nicht verstehen, die JonB Funktion und da die Cyberherbalist Funktion nicht linear ist.
Ich hatte zu beheben,
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
Mit der zwischen Funktion, die true zurück, wenn von Anfang an Tag startet, treffen wir auf die dayImLookingFor ersten vor dem EndDay.
Ich habe die zwischen Funktion durch die Berechnung der Anzahl der Tage von StartDay zu den beiden anderen Tagen durchgeführt:
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;
}
}
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;
}
Dies wird eine Sammlung von ganzen Zahlen zurückkehren zeigt, wie viele Male jeden Tag der Woche in einem bestimmten Zeitraum stattfindet
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;
}
oder eine leichte Variation, die Sie tun FirstDate.TotalDaysOfWeeks (SecondDate) und gibt einen Dictionary
läßt 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;
}
Ich hatte ein ähnliches Problem für einen Bericht. Ich brauchte die Anzahl der Arbeitstage zwischen zwei Daten. Ich hätte durch die Tage, radelte und gezählt, aber meine diskrete Mathematik Training ließ mich nicht. Hier ist eine Funktion, die ich in VBA geschrieben, die Anzahl der Arbeitstage zwischen zwei Daten zu erhalten. Ich bin sicher, .net hat eine ähnliche Funktion WeekDay.
1
2 ' WorkDays
3 ' returns the number of working days between two dates
4 Public Function WorkDays(ByVal dtBegin As Date, ByVal dtEnd As Date) As Long
5
6 Dim dtFirstSunday As Date
7 Dim dtLastSaturday As Date
8 Dim lngWorkDays As Long
9
10 ' get first sunday in range
11 dtFirstSunday = dtBegin + ((8 - Weekday(dtBegin)) Mod 7)
12
13 ' get last saturday in range
14 dtLastSaturday = dtEnd - (Weekday(dtEnd) Mod 7)
15
16 ' get work days between first sunday and last saturday
17 lngWorkDays = (((dtLastSaturday - dtFirstSunday) + 1) / 7) * 5
18
19 ' if first sunday is not begin date
20 If dtFirstSunday <> dtBegin Then
21
22 ' assume first sunday is after begin date
23 ' add workdays from begin date to first sunday
24 lngWorkDays = lngWorkDays + (7 - Weekday(dtBegin))
25
26 End If
27
28 ' if last saturday is not end date
29 If dtLastSaturday <> dtEnd Then
30
31 ' assume last saturday is before end date
32 ' add workdays from last saturday to end date
33 lngWorkDays = lngWorkDays + (Weekday(dtEnd) - 1)
34
35 End If
36
37 ' return working days
38 WorkDays = lngWorkDays
39
40 End Function
private System.Int32 CountDaysOfWeek(System.DayOfWeek dayOfWeek, System.DateTime date1, System.DateTime date2)
{
System.DateTime EndDate;
System.DateTime StartDate;
if (date1 > date2)
{
StartDate = date2;
EndDate = date1;
}
else
{
StartDate = date1;
EndDate = date2;
}
while (StartDate.DayOfWeek != dayOfWeek)
StartDate = StartDate.AddDays(1);
return EndDate.Subtract(StartDate).Days / 7 + 1;
}
Vier Jahre später, ich dachte, dass ich einen Test durchführen würde:
[TestMethod]
public void ShouldFindFridaysInTimeSpan()
{
//reference: http://stackoverflow.com/questions/248273/count-number-of-mondays-in-a-given-date-range
var spanOfSixtyDays = new TimeSpan(60, 0, 0, 0);
var setOfDates = new List<DateTime>(spanOfSixtyDays.Days);
var now = DateTime.Now;
for(int i = 0; i < spanOfSixtyDays.Days; i++)
{
setOfDates.Add(now.AddDays(i));
}
Assert.IsTrue(setOfDates.Count == 60,
"The expected number of days is not here.");
var fridays = setOfDates.Where(i => i.DayOfWeek == DayOfWeek.Friday);
Assert.IsTrue(fridays.Count() > 0,
"The expected Friday days are not here.");
Assert.IsTrue(fridays.First() == setOfDates.First(i => i.DayOfWeek == DayOfWeek.Friday),
"The expected first Friday day is not here.");
Assert.IsTrue(fridays.Last() == setOfDates.Last(i => i.DayOfWeek == DayOfWeek.Friday),
"The expected last Friday day is not here.");
}
Meine Verwendung von TimeSpan
ein bisschen übertrieben --- eigentlich wollte ich TimeSpan
direkt abgefragt werden.