2009-06-11 9 views
14

Solo me pregunta si conoce alguna solución elegante para lo siguiente.Cálculos de fin de mes

Si tengo 30 junio de 2009 y agrego un mes quiero que se vaya hasta el 31 de julio de 2009, no 30 de julio de 2009.

Esta lógica se basa en el hecho de que los 30 de junio de 2009 fue el final del mes de junio y cuando agregue un mes quiero ir al final del mes siguiente.

Pero si yo con 29 junio de 2009 y añado un mes que debe ir hasta el 29 de julio de 2009.

Nota Tengo que ser capaz de añadir cualquier número de meses y tengo que tener en cuenta años bisiestos.

También sé que la lógica aquí es cuestionable, pero es un requisito comercial que funciona con los contratos de fin de mes que van a llegar a fin de mes durante un mes en el futuro.

He pensado en varias soluciones pero ninguna que sea muy elegante. Por lo tanto, estaba pensando que alguien podría tener una mejor manera.

Saludos Anthony

+1

Te estás contradiciendo. "Si tengo el 30 de junio de 2009 y agrego un mes, no quiero que vaya al 31 de julio de 2009 ... cuando agregue un mes quiero ir al final del próximo mes". ¿Quiere decir que quiere que se vaya hasta el final del mes? –

+0

ya me acabo de dar cuenta de que ... :) –

+0

¿Cuáles son sus soluciones poco elegantes? –

Respuesta

32

Para comprobar si una fecha es el final del mes, comprobar si el día siguiente es el primer día de algunos meses. su algoritmo debería ser "Si el día no es fin de mes, agregue 1 mes. Si es fin de mes, agregue un día, agregue un mes, reste un día".

bool IsEndOfMonth(DateTime date) { 
     return date.AddDays(1).Day == 1; 
    } 
    DateTime AddMonthSpecial(DateTime date) { 
     if (IsEndOfMonth(date)) 
      return date.AddDays(1).AddMonths(1).AddDays(-1); 
     else 
      return date.AddMonths(1); 
    } 
+0

¿Qué tal el 31 de diciembre de 2009 + 2 meses? Debería ser el 28 de febrero de 2010 ... –

+0

lo siento, cometí un error en la explicación "agregar un día, agregar un mes, restar un mes" debe ser "agregar día, agregar mes, restar día". Arreglé esa última oración. – Jimmy

+1

su ejemplo todavía funciona porque agrega 2 meses al 1 de enero de 2010, obteniendo 1 mar 2010, luego restando 1 día para obtener "1 día antes del próximo mes", que es equivalente a "último día del mes" – Jimmy

1

¿Se puede llegar comenzando el primer día del mes anterior y volviendo un día?

0
  1. Pruebe para ver si la fecha anterior es "fin de mes".
    1. Agregue un día a la fecha y vea si el número de mes cambia.
  2. Añadir un mes
  3. Si la fecha de edad era de "fin de mes"
    1. Establecer el día de mes a 1
    2. Añadir otro mes
    3. restar un día
+0

public int Día { obtener; } ms-help: //MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/899d9772-e792-052a-2c0b-8a28aea0d5b9.htm – sesame

0

Mi enfoque a este problema comenzaría con una rutina at determina si un día determinado es el último día del mes (teniendo en cuenta el año bisiesto, ¡por supuesto, los feratários!)

También necesitará una rutina que le proporcione el último día de un mes, dado un día en ese mes.

Luego, si encuentra un día que ES el último día, agregue un día y use la segunda rutina para obtener el último día de ESE mes. Use un ciclo por varios meses.

0

Puede implementar un EndOfMonth() e isEndOfMonth().

lo que el código sería, más o menos,

if isEndOfMonth(this.Date()) 
    endDate = (startmonth + addedMonths).EndOfMonth() 
else 
    endDate = startDate + addedMonths 

Un poco simplista, pero usted consigue la idea.

Hay por supuesto una gran cantidad de ideas aquí por la lógica de EndOfMonth y isEndOfMonth

2
DateTime exampleDate = DateTime.Parse("12/31/2009"); 
bool isLastDayOfMonth = (exampleDate.AddDays(1).Month != exampleDate.Month); 

if (isLastDayOfMonth) 
    Console.WriteLine(exampleDate.AddDays(1).AddMonths(1).AddDays(-1)); 
else 
    Console.WriteLine(new DateTime(exampleDate.Year, exampleDate.Month, 1).AddMonths(2).AddDays(-1)); 

EDIT: He leído tu pregunta de nuevo. Deberá poner un cheque para ver si es el último día del mes.

Lo siento, ojalá hubiera leído la pregunta claramente de lo que se necesita.
Espero que esto sea lo suficientemente bueno como para darle una idea de lo que se necesita.

0

Aquí es una sencilla solución # .NET C que cuenta los años bisiestos, etc:

static DateTime ContractDue(DateTime start, int months) 
{ 
    if (start.Month == start.AddDays(1).Month) 
    { // Same month, just add the months 
      return start.AddMonths(months); 
    } 
    // Last day of month... add a day, add the months, then go back one day 
    return start.AddDays(1).AddMonths(months).AddDays(-1); 
} 
-1

Si sólo necesita EndOfMonth o AddNMonth simple, entonces usted tiene su respuesta ya.

De lo contrario, para tener una solución genérica completa, necesitaría una implementación del patrón de recurrencia, como puede ver en la interfaz de usuario del Outlook Meeting interface. No estoy sugiriendo que use la implementación de Outlook, pero debe haber algunos componentes .NET que pueda comprar. O impleméntelo usted mismo, pero no lo subestime y lo pruebe todo: es un componente muy difícil de implementar.

0

Se puede usar el método DateTime.DaysInMonth() algo como lo siguiente:

DateTime workingMonth = new DateTime(2009, 06, 30).AddDays(1); 
int nextMonthDays = DateTime.DaysInMonth(workingMonth.Year, workingMonth.Month); 
DateTime newMonth = new DateTime(workingMonth.Year, workingMonth.Month, nextMonthDays); 
0

¿sería entonces la función de complemento de encontrar si estoy en el inicio de un mes? DateTime.Now.AddDays(-1).Month == DateTime.Now.AddMonths(-1).Month