2009-12-22 14 views
11

¿Hay una función de C# que me dará el último día del trimestre terminado más recientemente con una fecha?Cuarto más cercano completado

Por ejemplo,

var lastDayOfLastQuarter = SomeFunction(jan 3, 2010); 

fijaría lastDayOfLastQuarter = Dic 31 de, 2009

+0

Se necesitaría ser capaz de definir sus cuartos cuando comienza y termina. – Paddy

+2

Oh, ese es probablemente solo un caso especial del método 'DoMagic()' que milagrosamente resuelve lo que quieres en cualquier contexto :-). En serio, no existe tal método en la biblioteca de la clase base, pero seguramente puedes escribir el tuyo propio. – Joey

+0

Cuartos estándar –

Respuesta

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

Uso:

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

Este método tiene la ventaja de que si tiene una definición impar de cuartos (por ejemplo, el ejercicio es diferente que el año calendario) el método QuartersInYear es fácilmente modificado para manejar esto.

+2

+1 - Simple, extensible, fácil de verificar y comprender. Quiéralo. – LBushkin

+1

Oh, me encantaría saber por qué esto fue solo downvoted. – jason

+1

Tenga en cuenta que este método supondrá que el trimestre ha finalizado cuando pase en el último día, es decir, el nuevo DateTime (2012, 9, 30) devolverá "2012-09-30", aunque se podría argumentar que en la última fecha , el trimestre aún no ha terminado. Además, el nombre del método es un poco engañoso, ya que devolverá el último trimestre, no el más cercano, si eso es en el futuro. –

2

Prueba esto:
Los AddMonths(-(d.Month-1) % 3)) mueve el DateValue al día equivilent del primer mes del trimestre, y luego el AddDays (-day) retrocede al último día del mes anterior.

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

Esto falla para, digamos, 'Día = 1',' Mes = 12', 'Año = 2009'. – jason

+0

porque la propiedad mes es 1-12, (no 0-11 como yo pensaba), corregido ahora –

+0

De acuerdo, creo que eso funciona. Vázquez eliminado. Sin embargo, la desventaja de este método es que depende mucho de que los trimestres se definan como los últimos días del tercero, sexto, noveno y duodécimo meses del año. Si se utiliza una definición diferente, este método no se adapta fácilmente a eso (las empresas mueven las fechas de informes de sus estados financieros con más frecuencia de lo que se podría pensar). – jason

2

cuartos Suponiendo siempre terminan a intervalos de 3 meses se podía hacer:

Quizás no sea la mejor solución, pero muy fácil de leer y modificar en comparación con otras soluciones ofrecidas.

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

Muchos errores en este código: 1. puntos y comas faltantes en cada declaración; 2. el tipo de devolución debe ser DateTime i.s.o. vacío; 3. Si falta un caso predeterminado, con la configuración predeterminada del compilador, obtendrá "no todas las rutas de código devuelven un valor". –

+0

@ R.Schreurs, solucionó todas las advertencias, excepto la del compilador. ¿Qué es exactamente lo que sugeriría para una devolución que lógicamente nunca debería ejecutarse? –

+1

Lanzaría una excepción en tal caso: predeterminado: throw new ApplicationException (string.Format ("{0} no es un número válido para un trimestre.", Resultado)); El compilador estará contento, y su código es claro sobre lo que acepta como válido. Todavía falta 1 punto y coma ... solo por curiosidad, ¿por qué no escribe su código en VS.Net y lo compila antes de publicarlo aquí? Cualquiera que busque esta función estaría contento si solo pudiera copiarse y pegarse y no necesitara depuración. –

1

Aquí hay una función simple para darle el último día del trimestre actual (suponiendo que esté usando un calendario estándar).

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

Espero que ayude.

2

una función simple puede calcular los últimos días del mes más reciente:

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

Usted puede utilizar una instrucción simple interruptor para comprobar qué trimestre las caídas fecha dada y devolver el último día del trimestre.

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

prueba:

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