2009-12-22 12 views
11

Esiste una funzione C# che mi darà l'ultimo giorno del Trimestre più recente data una data?Quartiere completato più vicino

Per esempio,

var lastDayOfLastQuarter = SomeFunction(jan 3, 2010); 

avrebbe fissato lastDayOfLastQuarter = 31 dic 2009

+0

Avresti bisogno di essere in grado di definire quando i quarti di inizio e fine. – Paddy

+2

Oh, quello è probabilmente solo un caso speciale del metodo 'DoMagic()' che risolve miracolosamente quello che vuoi in qualsiasi contesto :-). Seriamente, non esiste un metodo simile nella libreria di classi base, ma puoi sicuramente scriverne uno tuo. – Joey

+0

Quarti standard –

risposta

26
public static DateTime NearestQuarterEnd(this DateTime date) { 
    IEnumerable<DateTime> candidates = 
     QuartersInYear(date.Year).Union(QuartersInYear(date.Year - 1)); 
    return candidates.Where(d => d < date.Date).OrderBy(d => d).Last(); 
} 

static IEnumerable<DateTime> QuartersInYear(int year) { 
    return new List<DateTime>() { 
     new DateTime(year, 3, 31), 
     new DateTime(year, 6, 30), 
     new DateTime(year, 9, 30), 
     new DateTime(year, 12, 31), 
    }; 
} 

Usage:

DateTime date = new DateTime(2010, 1, 3); 
DateTime quarterEnd = date.NearestQuarterEnd(); 

Questo metodo ha il vantaggio nel senso che se si dispone di una definizione di dispari di quarti (ad esempio, l'anno fiscale è diverso rispetto all'anno solare), il metodo QuartersInYear è facilmente modificato per gestire questo.

+2

+1 - Semplice, estensibile, facile da verificare e comprendere. Lo adoro. – LBushkin

+1

Oh, mi piacerebbe sapere perché questo è stato appena downvoted. – jason

+1

Attenzione che questo metodo supporrà che il trimestre sia terminato quando si passa l'ultimo giorno, ovvero, il nuovo DateTime (2012, 9, 30) restituirà "2012-09-30", anche se si potrebbe obiettare che nell'ultima data , il trimestre non è ancora finito. Inoltre, il nome del metodo è leggermente fuorviante, poiché restituirà l'ultimo trimestre, non il più vicino se questo è in futuro. –

2

Prova questo:
I AddMonths(-(d.Month-1) % 3)) mosse DATEVALUE al giorno equivilent del primo mese del trimestre, e poi lo AddDays (-day) si sposta indietro fino all'ultimo giorno del mese precedente.

DateTime d = Datetime.Now; 
    DateTime lastDayOfLastQuarter = d.AddMonths(-((d.Month-1)%3)).AddDays(-d.Day); 
+0

Ciò non riesce, ad esempio, per "Giorno = 1", "Mese = 12", "Anno = 2009". – jason

+0

perché la proprietà del mese è 1-12, (non 0-11 come pensavo), corretta ora –

+0

Ok, penso che funzioni. Rimuovi downvot. Tuttavia, lo svantaggio di questo metodo è che dipende in larga misura dai trimestri definiti come gli ultimi giorni del terzo, sesto, nono e dodicesimo mese dell'anno. Se si utilizza una definizione diversa, questo metodo non è facilmente adattabile (le aziende trasferiscono le proprie date di rendicontazione finanziaria più spesso di quanto si possa pensare). – jason

2

Assumendo quarti finiscono sempre ad intervalli di 3 mesi che si potrebbe fare:

Forse non la soluzione migliore, ma molto facile da leggere e modificare rispetto ad altre soluzioni offerte.

public DateTime LastDayOfLastQuarter(DateTime date) 
{ 
    int result = (int)(date.Month/3) 

    switch (result) 
    { 
     // January - March 
     case 0: 
      return new DateTime(date.Year - 1, 12, 31); 
     // April - June 
     case 1: 
      return new DateTime(date.Year, 3, 31); 
     // July - September 
     case 2: 
      return new DateTime(date.Year, 6, 30); 
     // October - December 
     case 3: 
      return new DateTime(date.Year, 9, 30); 
    } 
} 
+1

Molti errori in questo codice: 1. mancanza di punti e virgola in ciascuna istruzione; 2. tipo di reso dovrebbe essere DateTime i.s.o. vuoto; 3. Manca un caso predefinito, con le impostazioni predefinite del compilatore, si otterrà "non tutti i percorsi di codice restituiscono un valore". –

+0

@ R.Schreurs, corretto tutto tranne l'avviso del compilatore per ya. Cosa suggeriresti esattamente per un ritorno che non dovrebbe mai essere eseguito logicamente? –

+1

In questo caso avrei generato un'eccezione: default: lanciare una nuova ApplicationException (string.Format ("{0} non è un numero valido per un quarto.", Risultato)); Il compilatore sarà felice e il tuo codice è chiaro su ciò che accetta come valido. Manca ancora 1 punto e virgola ... solo per curiosità, perché non scrivi il tuo codice in VS.Net e lo compili solo prima di postarlo qui? Chiunque cerchi questa funzione sarebbe felice se potesse essere semplicemente copiato e incollato e non necessiti di debugging. –

1

Ecco una semplice funzione per darvi l'ultimo giorno del trimestre in corso (supponendo che si sta utilizzando un calendario standard).

DateTime LastDayOfQuarter(DateTime today) 
{ 
    int quarter = (today.Month-1)/3; 
    int lastMonthInQuarter = (quarter +1) * 3; 
    int lastDayInMonth = DateTime.DaysInMonth(today.Year, lastMonthInQuarter); 
    return new DateTime(today.Year, lastMonthInQuarter, lastDayInMonth); 
} 

Spero che questo aiuti.

2

Una funzione semplice in grado di calcolare gli ultimi giorni del mese più recentemente completato:

public static DateTime LastQuarter(DateTime date) 
{ 
    return new DateTime(date.Year, date.Month - ((date.Month - 1) % 3), 1).AddDays(-1); 
} 
0

è possibile utilizzare una semplice istruzione switch per controllare che il quartiere dei dati cascate di data e restituire l'ultimo giorno del trimestre.

1
Func<int, int> q = (i) => { return ((i - 1)/3) + 1; }; 

prova:

Enumerable.Range(1, 12).Select(i => q(i));