Obtenez les dates du premier et du dernier jour du mois précédent en c #

140

Je ne peux pas penser à un simple ou deux doublures qui obtiendraient le premier et le dernier jour des mois précédents.

Je suis en train de LINQ-ifying une application Web d'enquête, et ils ont inséré une nouvelle exigence.

L'enquête doit inclure toutes les demandes de service du mois précédent. Donc, si c'est le 15 avril, j'ai besoin de tous les identifiants de demande de Marches.

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

Je ne peux pas penser facilement aux dates sans interrupteur. À moins que je ne sois aveugle et que je néglige une méthode interne pour le faire.

Jeremy Boyd
la source

Réponses:

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

Mettez-les en ligne si vous avez vraiment besoin d'une ou deux lignes.

Andleer
la source
2
IIRC DateTime.Today est un appel assez coûteux, vous feriez donc mieux de stocker d'abord la valeur dans une variable. Bonne réponse quand même :)
Leandro López
2
@andleer voici une belle bibliothèque qui fonctionne comme vous l'avez mentionné fluentdatetime.codeplex.com
Matthew Lock
@MatthewLock, le lien semble rompu.
Guillermo Gutiérrez
1
@ guillegr123 maintenant sur github github.com/FluentDateTime/FluentDateTime et Nuget nuget.org/packages/FluentDateTime
Matthew Lock
2
Je voudrais simplement souligner que si les entrées sont stockées en utilisant une date / heure complète, cette requête peut ne pas récupérer celles qui commencent après 12h00 le dernier jour du mois. Vous pouvez résoudre ce problème en remplaçant la dernière ligne par var last = month.AddTicks (-1);
SixOThree
23

La façon dont j'ai fait cela dans le passé est d'abord d'obtenir le premier jour de ce mois

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

Puis soustrayez un jour pour obtenir la fin du mois dernier

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

Puis soustrayez un mois pour obtenir le premier jour du mois précédent

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
MikeW
la source
4
+1, mais pour être pédant, il vaut mieux évaluer une fois DateTime.Today et stocker dans une variable locale. Si votre code commence à s'exécuter une nanoseconde avant minuit, deux appels consécutifs à DateTime.Today peuvent renvoyer des valeurs différentes.
Joe le
Oui, merci, vous corrigez tous, même le pédant Correction de l'erreur.
MikeW
eh bien laissez le compilateur être moins pédant avec vous :)
Maksym Gontar
1
voté comme comparé return date.AddDays(-(date.Day-1))par rapport à return new DateTime(date.Year, date.Month, 1);et les performances des premières itérations sur 2000 sont meilleures (923 ms de nouveautés contre 809 ms retournant le même objet)
Terry_Brown
9
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
Franci Penov
la source
DateTime.Today.Days -> 'System.DateTime' ne contient pas de définition pour 'Days' ...
andleer
5

J'utilise ce simple one-liner:

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

Soyez conscient, qu'il retient le temps.


la source
1
Juste ce que je voulais, une expression concise que je pourrais utiliser dans un ternaire. Merci!
Joe Ballard
4

Une approche utilisant des méthodes d'extension:

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

Voir ce lien http://www.codeplex.com/fluentdatetime pour quelques extensions DateTime inspirées.

rp.
la source
3

Le cas d'utilisation canonique dans le commerce électronique est la date d'expiration des cartes de crédit, MM / aa. Soustrayez une seconde au lieu d'un jour. Sinon, la carte apparaîtra expirée pendant tout le dernier jour du mois d'expiration.

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

S'il y a une chance que vos datetimes ne soient pas des dates de calendrier strictes, vous devriez envisager d'utiliser des comparaisons d'exclusion de date de fin ... Cela vous évitera de manquer les demandes créées à la date du 31 janvier.

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
la source
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
la source
1
Et si DateTime.Now cédait le 31/01/2009 au premier appel et le 01/02/2009 au deuxième appel?
Amy B
1

Voici une interprétation de la réponse 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);
}

Vous pouvez l'appeler ainsi:

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