2011-02-03 18 views
13

Lo que quiero hacer es crear un calendario simple, y quiero encontrar el primer día de la primera semana de un mes específico. Mi calendario es de lunes a domingo y el siguiente código funciona, pero como pueden ver, no es tan agradable. Alguien tiene una mejor idea sobre cómo obtener la primera fecha en el calendario.Encontrar el primer día del calendario

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

El calendario va a terminar con este aspecto:

| < |  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 | 

Y en esta "imagen" que es la [27] fecha en la que yo estoy tratando de encontrar.

Solución (encontrado que es mejor/más limpio para recorrer luego calcular):

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, por el arte ASCII. –

+0

+1 #wow, De hecho hice un Calendario similar en una aplicación de consola con C en mi Colegio. –

Respuesta

9

Me gustaría hacer esto. Es tan fácil de entender:

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; 
} 

Además, si desea cambiar su calendario para empezar en algo distinto al lunes, es trivial ahora. Una solución que use modulo aritmético no sería tan fácil de mantener.

+0

¿Por qué es esto tan complicado? soluciones mucho más simples existen – user492238

+0

@ user492238 IMO este código es más simple que su (y mi) solución. El ciclo termina después de un máximo de 7 iteraciones, por lo que el rendimiento también es bueno. – CodesInChaos

4

Puede utilizar módulo para calcular el número de días de relleno sin una sentencia condicional:

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

Agradable. No sabía que era posible convertir DayOfWeek en int.Siempre lo he visto mostrar la cadena del día: "Lunes". –

+0

@DougS Es una enumeración, y puede convertir cualquier enumeración en el tipo integral subyacente. – CodesInChaos

+0

@ CodesInChaos: es bueno saberlo. ¡Gracias! –

1

Puede probar esto suponiendo primer día ur refiriéndose a es el lunes

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

¿Pero por qué? No es inmediatamente comprensible. Hay un código más claro que puede captarse de inmediato. Apreciará escribirlo en tres meses cuando necesite mantener algo, o no lo permita, solucione una desagradable falla porque no está claro. – jason

-1

ACTUALIZACIÓN: Después de código tiene un error! Usa la aritmética de módulo para compensar las circunstancias. ¡NET comienza la semana del domingo! Vea otras soluciones aquí (sin la que tiene una función adicional).

Si necesita encontrar el "27" (es decir, el primer día de la presentación de un mes) y pegue el siguiente:

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

¿Cuál es el voto negativo? – user492238

+1

No soy el votante atrasado, pero sospecho que su código no funciona para un posible día de la semana porque .net ve el domingo como el primer día de la semana y el lunes por la tarde. – CodesInChaos

+0

Este código tiene un error, su significado no es inmediatamente obvio, y no es mantenible. – jason

1

que no me gustan los bucles while, porque son caros cuando se utiliza con LINQ
esperanza alguien puede volver a utilizar este código: (si se encuentra en los EE.UU., a continuación, basta con retirar [+ 6)% 7)] en dos líneas)

/// <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

Me encontré a mí mismo necesitando hacer esto con bastante frecuencia, así que creé el siguiente método de extensión.

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; 
} 

utilizar de esta manera

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(); 

Por defecto es el domingo como el primer DayOfWeek, pero puede pasar que lo DayOfWeek que le gustan, así:

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(DayOfWeek.Monday); 
Cuestiones relacionadas