Rufen Sie den ersten und letzten Tag des Vormonats in c # ab

140

Ich kann mir keinen einfachen Ein- oder Zwei-Liner vorstellen, der den ersten Tag und den letzten Tag der vergangenen Monate erreichen würde.

Ich bin LINQ-ifying eine Umfrage-Web-App, und sie drückten eine neue Anforderung in.

Die Umfrage muss alle Serviceanfragen des Vormonats enthalten. Wenn es also der 15. April ist, brauche ich alle Marches-Anforderungs-IDs.

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

Ich kann mir die Daten ohne Wechsel einfach nicht vorstellen. Es sei denn, ich bin blind und übersehen eine interne Methode.

Jeremy Boyd
quelle

Antworten:

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

Inline, wenn Sie wirklich ein oder zwei Zeilen benötigen.

andleer
quelle
2
IIRC DateTime.Today ist ein ziemlich teurer Aufruf, daher sollten Sie den Wert zuerst in einer Variablen speichern. Trotzdem gute Antwort :)
Leandro López
2
@andleer hier ist eine schöne Bibliothek, die so funktioniert, wie Sie es erwähnt haben fluentdatetime.codeplex.com
Matthew Lock
@MatthewLock, der Link scheint unterbrochen zu sein.
Guillermo Gutiérrez
1
@ guillegr123 jetzt bei github github.com/FluentDateTime/FluentDateTime und Nuget nuget.org/packages/FluentDateTime
Matthew Lock
2
Ich möchte nur darauf hinweisen, dass bei der Speicherung von Einträgen, die unter Verwendung einer vollständigen Datums- / Uhrzeitangabe gespeichert sind, möglicherweise keine Abfragen abgerufen werden, die am letzten Tag des Monats nach 12:00 Uhr beginnen. Sie können dies lösen, indem Sie die letzte Zeile in var last = month.AddTicks (-1) ändern.
SixOThree
23

Die Art und Weise, wie ich das in der Vergangenheit gemacht habe, ist, zuerst den ersten Tag dieses Monats zu bekommen

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

Subtrahieren Sie dann einen Tag, um das Ende des letzten Monats zu erreichen

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

Subtrahieren Sie dann einen Monat, um den ersten Tag des Vormonats zu erhalten

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
MikeW
quelle
4
+1, aber um pedantisch zu sein, sollten Sie DateTime.Today einmal auswerten und in einer lokalen Variablen speichern. Wenn Ihr Code vor Mitternacht eine Nanosekunde ausführt, können zwei aufeinanderfolgende Aufrufe von DateTime.Today unterschiedliche Werte zurückgeben.
Joe
Ja, danke, Sie alle haben Recht, auch der pedantische. Der Fehler wurde behoben.
MikeW
Nun,
1
upvoted wie verglich im return date.AddDays(-(date.Day-1))Vergleich return new DateTime(date.Year, date.Month, 1);und die Leistung der ersten über 2000 Iterationen ist besser (923ms Newing das gleiche Objekt im Vergleich zu 809ms bis Rückkehr)
Terry_Brown
9
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
Franci Penov
quelle
DateTime.Today.Days -> 'System.DateTime' enthält keine Definition für 'Days' ...
andleer
5

Ich benutze diesen einfachen Einzeiler:

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

Seien Sie sich bewusst, dass es die Zeit behält.


quelle
1
Genau das, was ich wollte, ein prägnanter Ausdruck, den ich in einem Ternär verwenden konnte. Vielen Dank!
Joe Ballard
4

Ein Ansatz mit Erweiterungsmethoden:

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

Unter diesem Link http://www.codeplex.com/fluentdatetime finden Sie einige inspirierte DateTime-Erweiterungen.

rp.
quelle
3

Der kanonische Anwendungsfall im E-Commerce ist das Ablaufdatum der Kreditkarte (MM / JJ). Subtrahieren Sie eine Sekunde statt eines Tages. Andernfalls erscheint die Karte für den gesamten letzten Tag des Ablaufmonats abgelaufen.

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

Wenn die Möglichkeit besteht, dass Ihre Datumsangaben keine strengen Kalenderdaten sind, sollten Sie Enddatum-Ausschlussvergleiche in Betracht ziehen. Dadurch wird verhindert, dass Sie Anfragen verpassen, die am 31. Januar erstellt wurden.

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.
quelle
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
quelle
1
Was ist, wenn DateTime.Now beim ersten Anruf 2009-01-31 und beim zweiten Anruf 2009-02-01 liefert?
Amy B
1

Dies ist eine Interpretation der Antwort von 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);
}

Sie können es so nennen:

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