2009-02-02 3 views
18

Ho bisogno di ottenere un elenco di settimane per un dato mese, con lunedì come giorno di inizio.C# - Qual è il modo migliore per ottenere un elenco delle settimane in un mese, dato un giorno della settimana iniziale?

Così, per esempio, per il mese di febbraio 2009, questo metodo potrebbe tornare:

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

Dang, e ho avuto un bel modo di farlo in VB.NET. – ChrisA

+0

Stavo per fare questa domanda io stesso - +1 per avermelo chiesto! :) –

risposta

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

Intelligente! +1 per aver reso lo scopo del codice più chiaro con LINQ –

+0

questo mi ha appena salvato circa due ore! – roryok

+0

Ho adattato la tua soluzione e funziona alla grande! molto apprezzato, grazie. –

0

Basta cambiare la linea di risposta a ciò che mai è necessario fare con esso

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/>"); 
    } 
} 

Soluzione rapida : non credo che ci sia una funzione integrata per questo ....

+0

Se si utilizza questo approccio, è possibile sollevare prima la chiamata GetDaysInMonth, anziché ricalcolarla per ogni giorno (più 1). –

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

Piuttosto che essere intelligente con AddDays, è sufficiente creare un nuovo DateTime che sostituisce il giorno con 1. Non è più chiaro? – Larsenal

+0

Robert è lo schema con cui sono andato, ma ho rifattorizzato il suo codice in un metodo di estensione. Grazie! –

+0

@Larsenal - è un po 'più complicato di così - sostituire il giorno con uno ci darebbe il primo del mese, ma abbiamo anche bisogno del primo giorno del mese che è l'inizio di una nuova settimana, secondo il giorno in cui è specificato come l'inizio di una settimana. –

0

Qualcosa come il seguente pseudo-codice dovrebbe funzionare:

  • Determinare la data di inizio del mese (uso il mese e l'anno da una data e impostare il giorno a 1
  • determinare la data di fine del mese (data di inizio + 1 mese)
  • Determinare la prima data che è un lunedi (questa è la prima voce dell'elenco)
  • Aggiungi 7 giorni di tempo per trovare la data successiva e ripetere fino a quando si legge o passare alla fine del mese
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); 
1

Che ne dici di questo?

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

Ecco una soluzione (in modo efficace una linea) utilizzando C# 3.0/LINQ, nel caso in cui si è interessati:

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

vedo che hai la risposta, ma ho voluto condividere con voi un classe di helper che ho creato per uno dei miei progetti. E 'lontano per essere una classe comprehansive, ma potrebbe aiutare ...

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

questo funziona splendidamente! Tutto quello che devi fare è ottenere il primo giorno del mese in cui desideri ottenere le settimane e poi questo ti darà il primo giorno di ogni settimana. È necessario per ottenere 5 settimane (non 4) in modo che l'Enumerable.Range conta su 5 invece di 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

Ecco quello che ho fatto, utilizzando il codice di Chaowlert come base di partenza. In sostanza ho modificato che è necessario verificare se si aggiungono i giorni in per overflow al mese successivo, quindi non aggiungo 4 giorni (dal lunedì al venerdì), ma in realtà il minimo tra 4 e il numero di giorni rimanenti nel mese . Inoltre, controllo se il giorno corrente è un fine settimana, altrimenti aggiungo giorni fino al giorno della settimana. Il mio scopo è di stampare le settimane in un mese, dal lunedì al venerdì

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))); 
} 
Problemi correlati