Obtenga las fechas del primer y último día del mes anterior en c #

140

No puedo pensar en una o dos líneas fáciles que tendrían los meses anteriores el primer día y el último día.

Estoy LINQ-ifying una aplicación web de encuestas, y exprimieron un nuevo requisito en.

La encuesta debe incluir todas las solicitudes de servicio del mes anterior. Entonces, si es el 15 de abril, necesito todos los ID de solicitud de Marches.

var RequestIds = (from r in rdc.request 
                  where r.dteCreated >= LastMonthsFirstDate && 
                  r.dteCreated <= LastMonthsLastDate 
                  select r.intRequestId);

Simplemente no puedo pensar en las fechas fácilmente sin un cambio. A menos que sea ciego y pase por alto un método interno para hacerlo.

Jeremy Boyd
fuente

Respuestas:

304
var today = DateTime.Today;
var month = new DateTime(today.Year, today.Month, 1);       
var first = month.AddMonths(-1);
var last = month.AddDays(-1);

En línea, si realmente necesita una o dos líneas.

andleer
fuente
2
IIRC DateTime.Today es una llamada bastante cara, por lo que es mejor que almacene el valor en una variable primero. Buena respuesta de todos modos :)
Leandro López
2
@andleer aquí hay una buena biblioteca que funciona como mencionaste fluentdatetime.codeplex.com
Matthew Lock
@MatthewLock, el enlace parece estar roto.
Guillermo Gutiérrez
1
@ guillegr123 ahora en github github.com/FluentDateTime/FluentDateTime y Nuget nuget.org/packages/FluentDateTime
Matthew Lock
2
Solo me gustaría señalar que si las entradas se almacenan usando una fecha y hora completa, esta consulta no podrá recuperar ninguna que comience después de las 12:00 a.m. del último día del mes. Puede resolver esto cambiando la última línea para leer var last = month.AddTicks (-1);
SixOThree
23

La forma en que lo hice en el pasado es obtener el primer día de este mes

dFirstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );

Luego reste un día para finalizar el mes pasado

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

Luego reste un mes para obtener el primer día del mes anterior

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
MikeW
fuente
44
+1, pero para ser pedante, es mejor evaluar DateTime. Hoy una vez y almacenar en una variable local. Si su código comienza a ejecutar un nanosegundo antes de la medianoche, dos llamadas consecutivas a DateTime.Today podrían devolver valores diferentes.
Joe
Sí, gracias, todos ustedes corrigen, incluso el pedante Corregió el error.
MikeW
así dejar que el compilador sea menos pedante que :)
Maksym Gontar
1
votó como estaba comparando return date.AddDays(-(date.Day-1))versus return new DateTime(date.Year, date.Month, 1);y el rendimiento de las primeras iteraciones de más de 2000 es mejor (923 ms en comparación con 809 ms devolviendo el mismo objeto)
Terry_Brown
9
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
Franci Penov
fuente
DateTime.Today.Days -> 'System.DateTime' no contiene una definición para 'Days' ...
andleer
5

Yo uso este simple one-liner:

public static DateTime GetLastDayOfPreviousMonth(this DateTime date)
{
    return date.AddDays(-date.Day);
}

Tenga en cuenta que retiene el tiempo.


fuente
1
Justo lo que quería, expresión concisa que podría usar dentro de un ternario. ¡Gracias!
Joe Ballard
4

Un enfoque que utiliza métodos de extensión:

class Program
{
    static void Main(string[] args)
    {
        DateTime t = DateTime.Now;

        DateTime p = t.PreviousMonthFirstDay();
        Console.WriteLine( p.ToShortDateString() );

        p = t.PreviousMonthLastDay();
        Console.WriteLine( p.ToShortDateString() );


        Console.ReadKey();
    }
}


public static class Helpers
{
    public static DateTime PreviousMonthFirstDay( this DateTime currentDate )
    {
        DateTime d = currentDate.PreviousMonthLastDay();

        return new DateTime( d.Year, d.Month, 1 );
    }

    public static DateTime PreviousMonthLastDay( this DateTime currentDate )
    {
        return new DateTime( currentDate.Year, currentDate.Month, 1 ).AddDays( -1 );
    }
}

Vea este enlace http://www.codeplex.com/fluentdatetime para algunas extensiones inspiradas de DateTime.

rp.
fuente
3

El caso de uso canónico en el comercio electrónico son las fechas de vencimiento de la tarjeta de crédito, MM / aa. Resta un segundo en lugar de un día. De lo contrario, la tarjeta aparecerá vencida durante todo el último día del mes de vencimiento.

DateTime expiration = DateTime.Parse("07/2013");
DateTime endOfTheMonthExpiration = new DateTime(
  expiration.Year, expiration.Month, 1).AddMonths(1).AddSeconds(-1);
MartinLeo
fuente
1

Si existe la posibilidad de que sus fechas y fechas no sean fechas estrictas del calendario, debería considerar usar comparaciones de exclusión de fecha final ... Esto evitará que se pierda cualquier solicitud creada durante la fecha del 31 de enero.

DateTime now = DateTime.Now;
DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
DateTime lastMonth = thisMonth.AddMonths(-1);

var RequestIds = rdc.request
  .Where(r => lastMonth <= r.dteCreated)
  .Where(r => r.dteCreated < thisMonth)
  .Select(r => r.intRequestId);
Amy B
fuente
1
DateTime now = DateTime.Now;
int prevMonth = now.AddMonths(-1).Month;
int year = now.AddMonths(-1).Year;
int daysInPrevMonth = DateTime.DaysInMonth(year, prevMonth);
DateTime firstDayPrevMonth = new DateTime(year, prevMonth, 1);
DateTime lastDayPrevMonth = new DateTime(year, prevMonth, daysInPrevMonth);
Console.WriteLine("{0} {1}", firstDayPrevMonth.ToShortDateString(),
  lastDayPrevMonth.ToShortDateString());
Maksym Gontar
fuente
1
¿Qué sucede si DateTime.Now produce 2009-01-31 en la primera llamada y 2009-02-01 en la segunda llamada?
Amy B
1

Esta es una versión de la respuesta de Mike W:

internal static DateTime GetPreviousMonth(bool returnLastDayOfMonth)
{
    DateTime firstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
    DateTime lastDayOfLastMonth = firstDayOfThisMonth.AddDays (-1);
    if (returnLastDayOfMonth) return lastDayOfLastMonth;
    return firstDayOfThisMonth.AddMonths(-1);
}

Puedes llamarlo así:

dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);
B. Clay Shannon
fuente