Pobierz daty pierwszego i ostatniego dnia poprzedniego miesiąca w języku C #


140

Nie mogę wymyślić łatwego jednego lub dwóch wkładek, które dostałyby poprzednie miesiące pierwszego i ostatniego dnia.

Jestem LINQ-ifying ankietową aplikację internetową i wycisnęli nowe wymaganie w.

Ankieta musi obejmować wszystkie zgłoszenia serwisowe z poprzedniego miesiąca. Więc jeśli jest 15 kwietnia, potrzebuję wszystkich identyfikatorów żądań Marchii.

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

Po prostu nie mogę łatwo wymyślić dat bez przełącznika. Chyba że jestem ślepy i nie dostrzegam wewnętrznej metody robienia tego.

Odpowiedzi:


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

Ustaw je szeregowo, jeśli naprawdę potrzebujesz jednej lub dwóch linii.


2
IIRC DateTime.Dzisiejsze wywołanie jest dość drogie, więc lepiej najpierw zapisz wartość w zmiennej. I tak dobra odpowiedź :)
— Leandro López

2
@andleer, oto ładna biblioteka, która działa tak, jak wspomniałeś fluentdatetime.codeplex.com
— Matthew Lock,

@MatthewLock, link wydaje się być uszkodzony.
— Guillermo Gutiérrez


2
Chciałbym tylko zwrócić uwagę, że jeśli wpisy są przechowywane przy użyciu pełnej daty i godziny, to zapytanie może nie odzyskać żadnych, które rozpoczynają się po godzinie 00:00 ostatniego dnia miesiąca. Możesz rozwiązać ten problem, zmieniając ostatnią linię tak, aby czytała var last = month.AddTicks (-1);
— SixOThree

23

Sposób, w jaki robiłem to w przeszłości, to pierwszy dzień tego miesiąca

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

Następnie odejmij dzień, aby otrzymać koniec ostatniego miesiąca

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

Następnie odejmij miesiąc, aby otrzymać pierwszy dzień poprzedniego miesiąca

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);

4
+1, ale żeby być pedantycznym, lepiej oceniaj DateTime, dziś raz i przechowuj w zmiennej lokalnej. Jeśli Twój kod zacznie się wykonywać nanosekundę przed północą, dwa kolejne wywołania funkcji DateTime.Today mogą zwrócić różne wartości.
— Joe

Tak, dzięki, wszyscy się zgadzacie, nawet ten pedantyczny Naprawiono błąd.
— MikeW

cóż, niech kompilator będzie dla Ciebie mniej pedantyczny :)
— Maksym Gontar

1
przegłosowano, podobnie jak porównanie, return date.AddDays(-(date.Day-1))a return new DateTime(date.Year, date.Month, 1);wydajność pierwszych ponad 2000 iteracji jest lepsza (nowe 923 ms w porównaniu z 809 ms zwracaniem tego samego obiektu)
— Terry_Brown


9
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);

DateTime.Today.Days -> „System.DateTime” nie zawiera definicji „Days” ...
— andleer

5

Używam tego prostego, jednowierszowego:

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

Miej świadomość, że zachowuje czas.


1
Właśnie tego chciałem, zwięzłego wyrażenia, którego mógłbym użyć wewnątrz trójskładnika. Dzięki!
— Joe Ballard

4

Podejście wykorzystujące metody rozszerzające:

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

Zobacz ten link http://www.codeplex.com/fluentdatetime, aby uzyskać kilka inspirowanych rozszerzeń DateTime.


3

Kanoniczny przypadek użycia w handlu elektronicznym to daty ważności kart kredytowych, MM / rr. Odejmij jedną sekundę zamiast jednego dnia. W przeciwnym razie karta będzie wydawać się wygasła na cały ostatni dzień miesiąca wygaśnięcia.

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

1

Jeśli jest jakakolwiek szansa, że ​​Twoje daty nie są ścisłymi datami kalendarzowymi, powinieneś rozważyć skorzystanie z porównań wykluczeń z dat końcowych ... Dzięki temu nie przegapisz żadnych żądań utworzonych w dniu 31 stycznia.

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

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());

1
Co się stanie, jeśli DateTime.Now zwróci 2009-01-31 w pierwszym wywołaniu i 2009-02-01 w drugim?
— Amy B

1

Oto odpowiedź na odpowiedź Mike'a 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);
}

Możesz to tak nazwać:

dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.