2011-02-03 18 views
13

Quello che voglio fare è creare un semplice calendario e voglio trovare il primo giorno della prima settimana di un mese specifico. Il mio calendario è un lunedì -> calendario di domenica e il codice seguente funziona, ma come puoi vedere non è bello. Qualcuno ha un'idea migliore su come ottenere la prima data nel calendario.Ricerca del primo giorno del calendario

var now = new DateTime(Year, Month, 1); 
now = now.AddDays(1-(int)now.DayOfWeek); 
now = now.Day > 15 ? now : now.AddDays(-7); 

Il calendario finirà per assomigliare a questo:

| < |  Jan 2011  | > | 
------------------------------------ 
| Mo | Tu | We | Th | Fr | Sa | Su | 
|[27]| 28 | 29 | 30 | 31 | 01 | 02 | 
| 03 | 04 | 05 | 06 | 07 | 08 | 09 | 
| .. | .. | .. | .. | .. | .. | .. | 
| .. | .. | .. | .. | .. | .. | .. | 
| 31 | 01 | 02 | 03 | 04 | 05 | 06 | 

E in questa "immagine" è il [27] data che sto cercando di trovare.

Solution (Trovati i meglio/pulitore a ciclo quindi calcolare):

public DateTime FirstDay() 
    { 
     var date = new DateTime(Date.Year, Date.Month, 1); 
     while (true) 
     { 
      if (date.DayOfWeek == DayOfWeek.Monday) 
       return date; 
      date = date.AddDays(-1); 
     } 
     return date; 
    } 

    public DateTime LastDay() 
    { 
     var date = new DateTime(Date.Year, Date.Month, 
           DateTime.DaysInMonth(Date.Year, Date.Month)); 
     while (true) 
     { 
      if (date.DayOfWeek == DayOfWeek.Sunday) 
       return date; 
      date = date.AddDays(1); 
     } 
     return date; 
    } 

/BR Andreas

+4

+1, per l'arte ASCII. –

+0

+1 #wow, in realtà ho creato un calendario simile in un'app console con C nel mio college. –

risposta

9

Vorrei solo fare questo. E 'così facile da capire:

var firstDayOfMonth = new DateTime(year, month, 1); 
DateTime startOfCalendar = 
    FirstDayOfWeekOnOrBefore(
     firstDayOfMonth, 
     DayOfWeek.Monday 
    ); 

public static DateTime FirstDayOfWeekOnOrBefore(
    DateTime date, 
    DayOfWeek dayOfWeek 
) { 
    while(date.DayOfWeek != dayOfWeek) { 
     date = date.AddDays(-1); 
    } 
    return date; 
} 

Inoltre, se si desidera cambiare il calendario per iniziare su qualcosa di diverso Lunedi, è banale ora. Una soluzione che utilizza l'aritmetica modulo non sarebbe così mantenibile.

+0

perché è così complicato? esistono soluzioni molto più semplici – user492238

+0

@ user492238 IMO questo codice è più semplice della tua (e mia) soluzione. Il ciclo termina dopo un massimo di 7 iterazioni, quindi anche le prestazioni vanno bene. – CodesInChaos

4

È possibile utilizzare modulo per calcolare il numero di giorni di riempimento, senza un'istruzione condizionale:

DateTime firstOfMonth=new DateTime(year,month,1); 
var weekDay=firstOfMonth.DayOfWeek; 
int fillerDays=((int)weekDay+6)%7; 
DateTime firstDayInCalendar=firstOfMonth.AddDays(-fillerDays); 
+0

Bello. Non sapevo che fosse possibile trasmettere DayOfWeek a un int.L'ho sempre visto visualizzare la stringa del giorno: "Monday". –

+0

@DougS È un enum e puoi lanciare qualsiasi enum al tipo integrale sottostante. – CodesInChaos

+0

@ CodesInChaos: Buono a sapersi. Grazie! –

1

Si può provare questo assumendo primo giorno ur riferendosi a è Lunedi

DateTime dt = new DateTime(2011, 2, 2); 
Console.WriteLine(dt.AddDays((8 - (int)dt.DayOfWeek) % 7)); 
+0

Ma perché? Non è immediatamente comprensibile. C'è un codice più chiaro che può essere immediatamente compreso. Apprezzerai di averlo scritto in tre mesi, quando hai bisogno di mantenere qualcosa, o il cielo non voglia, di sistemare un brutto insetto perché è così poco chiaro. – jason

-1

UPDATE: A seguito di codice ha un bug! Usa l'aritmetica modulo, per compensare le circostanze, .NET inizia la settimana di domenica! Vedi altre soluzioni qui (senza quella con una funzione extra).

Se hai bisogno di trovare il "27" (vale a dire il primo giorno per la visualizzazione di un mese) è sufficiente utilizzare questo:

DateTime monthStart = new DateTime(year, month, 1); 
DateTime monthDisplayStart = monthStart.AddDays(-((int)monthStart.DayOfWeek - 1)); 
+0

per che cosa è il downvote? – user492238

+1

Non sono il down-voter, ma ho il sospetto che il tuo codice non funzioni per un possibile giorno della settimana perché .net vede domenica come primo giorno della settimana, e l'OP lunedì. – CodesInChaos

+0

Questo codice ha un bug, il suo significato non è immediatamente evidente e non è mantenibile. – jason

1

non mi piace while, perché sono costosi quando viene utilizzato con LINQ
speranza che qualcun altro può riutilizzare questo codice: (se siete negli Stati Uniti, poi basta rimuovere [+ 6)% 7)] in due linee)

/// <summary> 
    /// Expands the month. 
    /// | < |  Jan 2011  | > | 
    /// ------------------------------------ 
    /// | Mo | Tu | We | Th | Fr | Sa | Su | 
    /// |[27]| 28 | 29 | 30 | 31 | 01 | 02 | 
    /// | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 
    /// | .. | .. | .. | .. | .. | .. | .. | 
    /// | .. | .. | .. | .. | .. | .. | .. | 
    /// | 31 | 01 | 02 | 03 | 04 | 05 | 06 | 
    /// </summary> 
    /// <param name="start">Some day in the month of interest, the start date is updated to become the date of firstDayInCalendar</param> 
    /// <returns>The number of days to show. This value is either (28, 35 or 42)</returns> 
    public static int ExpandMonth(ref DateTime start) 
    { 
     DateTime first = new DateTime(start.Year, start.Month, 1); 
     DateTime last = new DateTime(start.Year, start.Month, DateTime.DaysInMonth(start.Year, start.Month)); 
     start = first.AddDays(-((int)first.DayOfWeek + 6) % 7); 
     last = last.AddDays(7 - ((int)last.DayOfWeek + 6) % 7); 
     return last.Subtract(start).Days; 
    } 

// Thomas

0

Mi sono trovato a doverlo fare abbastanza spesso, quindi ho creato il seguente metodo di estensione.

public static DateTime FirstDateOfCalendarMonth(this DateTime dt, DayOfWeek firstDayOfWeek = DayOfWeek.Sunday) 
{ 
    dt = new DateTime(dt.Year, dt.Month, 1); 
    while (dt.DayOfWeek != firstDayOfWeek){ 
    dt = dt.AddDays(-1); 
    } 
    return dt; 
} 

usare in questo modo

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(); 

Il valore predefinito è Domenica come primo DayOfWeek, ma è possibile passare qualunque DayOfWeek che ti piace, come questo:

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(DayOfWeek.Monday); 
Problemi correlati