2009-02-26 15 views
118

Nie mogę wymyślić łatwego jednego lub dwóch linerów, które dostaną poprzednie miesiące pierwszego dnia i ostatniego dnia.Zdobądź daty pierwszego i ostatniego dnia poprzedniego miesiąca w C#

Jestem LINQ-ifying ankietę internetową aplikację, i wyciska nowy wymóg.

Badanie musi obejmować wszystkich zgłoszeń serwisowych za poprzedni miesiąc. Więc jeśli jest 15 kwietnia, potrzebuję wszystkich identyfikatorów zapytań marszowych.

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

Po prostu nie mogę wymyślić daty łatwo bez przełącznika. O ile nie jestem ślepy i nie widzę wewnętrznej metody robienia tego.

Odpowiedz

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

In-line je, jeśli naprawdę potrzebujesz jednej lub dwóch linii.

+2

IIRC DateTime.Today to dość kosztowne połączenie, więc lepiej najpierw zapisać wartość w zmiennej. Dobra odpowiedź i tak :) –

+1

Jak to będzie działać 1 stycznia? –

+8

Działa dobrze z 1 stycznia, po prostu przetestowany ... –

21

Sposób robiłem to w przeszłości jest najpierw dostać pierwszy dzień tego miesiąca

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

odejmujemy dziennie, aby uzyskać koniec ubiegłego miesiąca

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1); 

Następnie odjąć miesiąc dostać pierwszego dnia poprzedniego miesiąca

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1); 
+0

netto 2,0, Today.Days nie działa. –

+0

DateTime.Today.Day masz na myśli –

+3

+1, ale aby być pedantycznym, lepiej oceniaj DateTime.Today raz i przechowuj w zmiennej lokalnej. Jeśli twój kod zacznie wykonywać nanosekundę przed północą, dwa kolejne połączenia z DateTime.Today mogą zwrócić różne wartości. – Joe

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

DateTime.Today.Days -> 'System.DateTime" nie zawiera definicji "Dni" ... – andleer

+1

DateTime .Today.Day masz na myśli –

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 zrobić, jeśli DateTime.Now rentowności 2009-01-31 w pierwszym wywołaniu i 2009-02-01 w drugim wywołaniu? –

+0

To będzie koniec edycji DateTime.Now :). dzięki. –

0

Jeśli jest jakaś szansa, że ​​datetimes nie są ściśle określone terminy kalendarza, należy rozważyć użycie endDate porównań wykluczeń ... To uniemożliwi brakuje jakichkolwiek żądań utworzonych podczas dnia sty 31

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

podejście wykorzystujące metody rozszerzeń:

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 dla niektórych zainspirowanych rozszerzeń DateTime.

1

2 EDYCJA: To nie jest sposób, aby to zrobić!
Jeśli dzisiaj.Miesiąc - 1 = 0, jak w Jan, spowoduje to wyjątek. Jest to wyraźnie przypadek, gdy bycie sprytnym wpędza cię w kłopoty!

Nieco prostsza niż accepted answer:

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

Zapisuje dodatkowy tworzenie DateTime.

2

kanoniczny przypadek użycia w e-commerce jest karta kredytowa daty ważności, mm/rr. Odejmij jedną sekundę zamiast jednego dnia. W przeciwnym razie karta będzie wydawać się nieważna przez 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); 
3

I w ten prosty jednego-liner:

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

zdawać sobie sprawę, że zachowuje czas.

+0

Właśnie tego chciałem, zwięzłą ekspresję mogłem użyć wewnątrz trójskładnikowego. Dzięki! –

1

Jest to spojrzenie na odpowiedź Mike W za:

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żna nazwać tak:

dateTimePickerFrom.Value = GetPreviousMonth(false); 
dateTimePickerTo.Value = GetPreviousMonth(true); 
Powiązane problemy