2009-02-26 8 views
118

Je ne peux pas penser à un doublage simple qui pourrait obtenir les mois précédents premier jour et dernier jour.Obtenir les dates du premier et du dernier jour du mois précédent en C#

Je suis LINQ-ification une application web de l'enquête, et ils serrais une nouvelle exigence.

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

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

Je ne peux pas penser aux dates facilement sans un commutateur. Sauf si je suis aveugle et néglige une méthode interne de le faire.

Répondre

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

En ligne si vous avez vraiment besoin d'une ou deux lignes.

+2

IIRC DateTime.Today est un appel assez cher, vous devez donc d'abord stocker la valeur dans une variable. Bonne réponse de toute façon :) –

+1

Comment cela fonctionnera-t-il le 1er janvier? –

+8

Fonctionne bien avec Jan 1er, juste testé ... –

21

La façon dont je l'ai fait dans le passé est d'obtenir d'abord le premier jour de ce mois-ci

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

Puis soustrayez par jour pour obtenir la fin du mois dernier

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1); 

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

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

net 2.0, Today.Days ne fonctionne pas. –

+0

DateTime.Today.Day tu veux dire –

+3

+1, mais pour être pédant, tu ferais mieux d'évaluer DateTime.Today une fois et de le 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

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

DateTime.Today.Days -> 'System.DateTime' ne contient pas de définition pour 'Days' ... – andleer

+1

DateTime .Today.Day vous voulez dire –

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

Que se passe-t-il si DateTime.Now cède le 2009-01-31 lors du premier appel et le 2009-02-01 lors du deuxième appel? –

+0

Ce sera la fin de l'édition de DateTime.Now :). Merci. –

0

S'il y a une chance que vos datetimes ne sont pas strictes dates du calendrier, vous devriez envisager d'utiliser des comparaisons d'exclusion enddate ... Cela vous évitera de manquer toutes les demandes créées au cours de 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); 
4

Une approche en 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 certaines extensions DateTime inspirées.

1

EDIT: Ce n'est pas la façon de le faire!
Si aujourd'hui.Month - 1 = 0, comme en janvier, cela va générer une exception. C'est clairement un cas où être intelligent vous met en difficulté!

Un peu plus simple que le 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); 

Enregistre une création DateTime supplémentaire.

2

Le cas d'utilisation canonique dans le commerce électronique est la date d'expiration de carte de crédit, MM/yy. Soustrayez une seconde au lieu d'un jour. Sinon, la carte apparaîtra expirée 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); 
3

J'utilise cette simple-liner:

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

Sachez qu'il conserve le temps.

+0

Juste ce que je voulais, expression concise que je pourrais utiliser à l'intérieur d'un ternaire. Merci! –

1

Ceci est une prise sur 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 comme ceci:

dateTimePickerFrom.Value = GetPreviousMonth(false); 
dateTimePickerTo.Value = GetPreviousMonth(true); 
Questions connexes