2009-02-02 4 views
18

Ich brauche eine Liste von Wochen für einen bestimmten Monat, mit Montag als Starttag.C# - Was ist der beste Weg, um eine Liste der Wochen in einem Monat zu erhalten, die an einem Starttag liegen?

So zum Beispiel, für den Monat Februar 2009 würde diese Methode zurück:

2/2/2009 
2/9/2009 
2/16/2009 
2/23/2009 
+0

Dang, und ich hatte eine wirklich gute Möglichkeit, dies in VB.NET zu tun. – ChrisA

+0

Ich wollte diese Frage selbst stellen - +1, dass ich sie gefragt habe! :) –

Antwort

25
// Get the weeks in a month 

DateTime date = DateTime.Today; 
// first generate all dates in the month of 'date' 
var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n)); 
// then filter the only the start of weeks 
var weekends = from d in dates 
       where d.DayOfWeek == DayOfWeek.Monday 
       select d; 
+0

Clever! +1, um den Zweck des Codes mit LINQ –

+0

klarer zu machen, das hat mich gerade zwei Stunden gerettet! – roryok

+0

Ich habe Ihre Lösung angepasst und funktioniert super! sehr geschätzt, danke. –

0

einfach die Antwortlinie ändern, was jemals brauchen Sie damit

protected void PrintDay(int year, int month, DayOfWeek dayName) 
{ 
    CultureInfo ci = new CultureInfo("en-US"); 
    for (int i = 1 ; i <= ci.Calendar.GetDaysInMonth (year, month); i++) 
    { 
    if (new DateTime (year, month, i).DayOfWeek == dayName) 
     Response.Write (i.ToString() + "<br/>"); 
    } 
} 

Schnell Lösung zu tun : ich glaube nicht, dass es eine integrierte Funktion für sie gibt ....

+0

Wenn Sie diesen Ansatz verwenden, möchten Sie möglicherweise zuerst den Aufruf GetDaysInMonth aufheben, anstatt ihn dann für jeden Tag (plus 1) neu zu berechnen. –

10
public static List<DateTime> GetWeeks(
    this DateTime month, DayOfWeek startOfWeek) 
{ 
    var firstOfMonth = new DateTime(month.Year, month.Month, 1); 
    var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7; 
    var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd); 

    var current = firstStartOfWeek; 
    var weeks = new List<DateTime>(); 
    while (current.Month == month.Month) 
    { 
     weeks.Add(current); 
     current = current.AddDays(7); 
    } 

    return weeks; 
} 
+0

Anstatt clever mit AddDays zu sein, muss man einfach eine neue DateTime erstellen, die den Tag durch 1 ersetzt. Ist das nicht klarer? – Larsenal

+0

Robert ist das Muster, mit dem ich ging, aber ich habe seinen Code in eine Erweiterungsmethode umgestaltet. Vielen Dank! –

+0

@ Larsenal - es ist ein wenig komplizierter als das - Ersetzen des Tages mit einem würde uns den ersten des Monats geben, aber wir brauchen auch den ersten Tag im Monat, der der Beginn einer neuen Woche ist, je nach dem Tag wird als Beginn einer Woche angegeben. –

0

Etwas wie die folgender Pseudo-Code sollte funktionieren:

  • Bestimmen Sie den Starttermin des Monats (Nutzung Monat und Jahr von einem Datum und stellen Sie den Tag 1
  • das Enddatum des Monats ermitteln (Datum + 1 Monat beginnen)
  • das erste Datum bestimmen, dass ein Montag (dies Ihr erster Eintrag in der Liste ist)
  • 7 Tage in den nächsten Termin und wiederholen zu finden, bis Sie die Monatsende
1
int year = 2009; 
int month = 2; 
DateTime startDate = new DateTime(year, month, 1); 
DateTime endDate = startDate.AddMonths(1); 
while (startDate.DayOfWeek != DayOfWeek.Monday) 
    startDate = startDate.AddDays(1); 
for (DateTime result = startDate; result < endDate; result = result.AddDays(7)) 
    DoWhatYouWant(result); 
lesen oder übergeben
1

Wie wäre es damit?

public IEnumerable<DateTime> GetWeeks(DateTime date, DayOfWeek startDay) 
    { 
    var list = new List<DateTime>(); 
    DateTime first = new DateTime(date.Year, date.Month, 1); 

    for (var i = first; i < first.AddMonths(1); i = i.AddDays(1)) 
    { 
     if (i.DayOfWeek == startDay) 
      list.Add(i); 
    } 

    return list; 
    } 
3

Hier ist eine Lösung (effektiv eine Zeile) mit C# 3.0/LINQ, falls Sie sich interessieren:

var month = new DateTime(2009, 2, 1); 
var weeks = Enumerable.Range(0, 4).Select(n => month.AddDays(n * 7 - (int)month.DayOfWeek + 1)).TakeWhile(monday => monday.Month == month.Month); 
0

Ich sehe Sie Ihre Antwort bekam, aber ich wollte mit Ihnen teilen ein Helferklasse, die ich für eines meiner Projekte erstellt habe. Es ist weit eine comprehansive Klasse zu sein, aber vielleicht helfen ...

public static class WeekHelper { 

#region Public Methods 
public static DateTime GetWeekStart(DateTime date) { 
    DateTime weekStart; 
    int monday = 1; 
    int crtDay = (int)date.DayOfWeek; 
    if (date.DayOfWeek == DayOfWeek.Sunday) 
     crtDay = 7; 
    int difference = crtDay - monday; 
    weekStart = date.AddDays(-difference); 
    return weekStart; 
} 
public static DateTime GetWeekStop(DateTime date) { 
    DateTime weekStart; 
    int sunday = 7; 
    int crtDay = (int)date.DayOfWeek; 
    if (date.DayOfWeek == DayOfWeek.Sunday) 
     crtDay = 7; 
    int difference = sunday - crtDay; 
    weekStart = date.AddDays(difference); 
    return weekStart; 
} 
public static void GetWeekInterval(int year, int weekNo, 
    out DateTime weekStart, out DateTime weekStop) { 
    GetFirstWeekOfYear(year, out weekStart, out weekStop); 
    if (weekNo == 1) 
     return; 
    weekNo--; 
    int daysToAdd = weekNo * 7; 
    DateTime dt = weekStart.AddDays(daysToAdd); 
    GetWeekInterval(dt, out weekStart, out weekStop); 
} 
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime toDate) { 
    //gets week series from beginning of the year 
    DateTime dtStartYear = new DateTime(toDate.Year, 1, 1); 
    List<KeyValuePair<DateTime, DateTime>> list = GetWeekSeries(dtStartYear, toDate); 
    if (list.Count > 0) { 
     KeyValuePair<DateTime, DateTime> week = list[0]; 
     list[0] = new KeyValuePair<DateTime, DateTime>(dtStartYear, week.Value); 
    } 
    return list; 
} 
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime fromDate, DateTime toDate) { 
    if (fromDate > toDate) 
     return null; 
    List<KeyValuePair<DateTime, DateTime>> list = new List<KeyValuePair<DateTime, DateTime>>(100); 
    DateTime weekStart, weekStop; 
    toDate = GetWeekStop(toDate); 
    while (fromDate <= toDate) { 
     GetWeekInterval(fromDate, out weekStart, out weekStop); 
     list.Add(new KeyValuePair<DateTime, DateTime>(weekStart, weekStop)); 
     fromDate = fromDate.AddDays(7); 
    } 
    return list; 
} 
public static void GetFirstWeekOfYear(int year, out DateTime weekStart, out DateTime weekStop) { 
    DateTime date = new DateTime(year, 1, 1); 
    GetWeekInterval(date, out weekStart, out weekStop); 
} 
public static void GetWeekInterval(DateTime date, 
    out DateTime dtWeekStart, out DateTime dtWeekStop) { 
    dtWeekStart = GetWeekStart(date); 
    dtWeekStop = GetWeekStop(date); 
} 
#endregion Public Methods 

}

0

Dies funktioniert wunderbar! Alles, was Sie tun müssen, ist den ersten Tag des Monats zu bekommen, für den Sie die Wochen bekommen möchten, und dann erhalten Sie den ersten Tag jeder Woche. Sie müssen 5 Wochen bekommen (nicht 4), so dass die Enumerable.Range 5 auszählt statt 4.

var date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); 
var weeks = from n in Enumerable.Range(0, 5) 
    select date.AddDays(7 * n + (-1 * (int)date.DayOfWeek)); 
0

Hier ist, was ich tat, Chaowlert den Code als Ausgangsbasis verwenden. Grundsätzlich habe ich geändert, dass Sie überprüfen müssen, ob die Tage in den Überläufen zum nächsten Monat hinzufügen, also füge ich nicht 4 Tage (Montag bis Freitag) hinzu, sondern tatsächlich das Minimum zwischen 4 und der Anzahl der verbleibenden Tage im Monat . Außerdem überprüfe ich, ob der aktuelle Tag ein Wochenende ist, ansonsten addiere Tage, bis es ein Wochentag ist. Mein Zweck ist, die Wochen in einem Monat, von Montag bis Freitag zu drucken

DateTime fechaInicio = new DateTime(año, mes, 1); 
DateTime fechaFin = fechaInicio.AddMonths(1); 
int diasHastaFinMes = 0; 
while (esFinDeSemana(fechaInicio)) 
    fechaInicio = fechaInicio.AddDays(1); 
for (DateTime fecha = fechaInicio; fecha < fechaFin; fecha = fecha.AddDays(7)) 
{ 
    diasHastaFinMes = DateTime.DaysInMonth(fecha.Year, fecha.Month) - fecha.Day; 
    printWeeks(fecha, fecha.AddDays(Math.Min(4, diasHastaFinMes))); 
}