c# - Diferencia en meses entre dos fechas.
.net vb.net (30)
¿Cómo calcular la diferencia en meses entre dos fechas en C #?
¿Existe el método DateDiff()
de VB en C #? Necesito encontrar la diferencia en meses entre dos fechas que están separadas por años. La documentación dice que puedo usar TimeSpan
como:
TimeSpan ts = date1 - date2;
Pero esto me da datos en días. No quiero dividir este número entre 30 porque no todos los meses son 30 días y, dado que los dos valores de los operandos están bastante separados, me temo que dividir entre 30 podría darme un valor incorrecto.
¿Alguna sugerencia?
Aquí está mi contribución para obtener la diferencia en los meses que he encontrado que son exactos:
namespace System
{
public static class DateTimeExtensions
{
public static Int32 DiffMonths( this DateTime start, DateTime end )
{
Int32 months = 0;
DateTime tmp = start;
while ( tmp < end )
{
months++;
tmp = tmp.AddMonths( 1 );
}
return months;
}
}
}
Uso:
Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) );
Puede crear otro método llamado DiffYears y aplicar exactamente la misma lógica que la anterior y AddYears en lugar de AddMonths en el bucle while.
Aquí hay una solución integral para devolver un DateTimeSpan
, similar a un TimeSpan
, excepto que incluye todos los componentes de fecha además de los componentes de tiempo.
Uso:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = DateTimeSpan.CompareDates(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
Salidas:
Años: 1
Meses: 5
Dias: 27
Horas: 1
Minutos: 36
Segundos: 50
Milisegundos: 0
Para mayor comodidad, he agrupado la lógica en la estructura DateTimeSpan
, pero puede mover el método CompareDates
donde lo considere oportuno. También tenga en cuenta, no importa qué fecha viene antes de la otra.
public struct DateTimeSpan
{
private readonly int years;
private readonly int months;
private readonly int days;
private readonly int hours;
private readonly int minutes;
private readonly int seconds;
private readonly int milliseconds;
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.milliseconds = milliseconds;
}
public int Years { get { return years; } }
public int Months { get { return months; } }
public int Days { get { return days; } }
public int Hours { get { return hours; } }
public int Minutes { get { return minutes; } }
public int Seconds { get { return seconds; } }
public int Milliseconds { get { return milliseconds; } }
enum Phase { Years, Months, Days, Done }
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
int officialDay = current.Day;
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
current = current.AddDays(officialDay - current.Day);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
Aquí hay una solución mucho más concisa usando VB.Net DateDiff por año, mes y día solamente. También puede cargar la biblioteca DateDiff en C #.
date1 debe ser <= date2
VB.NET
Dim date1 = Now.AddDays(-2000)
Dim date2 = Now
Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0)
Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0)
Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day))
DO#
DateTime date1 = Now.AddDays(-2000);
DateTime date2 = Now;
int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0;
int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0;
int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day);
Aquí hay una solución simple que funciona al menos para mí. Probablemente no sea el más rápido, ya que utiliza la característica AddMonth de DateTime en un bucle:
public static int GetMonthsDiff(DateTime start, DateTime end)
{
if (start > end)
return GetMonthsDiff(end, start);
int months = 0;
do
{
start = start.AddMonths(1);
if (start > end)
return months;
months++;
}
while (true);
}
Comprobé el uso de este método en VB.NET a través de MSDN y parece que tiene muchos usos. No hay tal método incorporado en C #. (Incluso no es una buena idea) puedes llamar a VB en C #.
- Agregue
Microsoft.VisualBasic.dll
a su proyecto como referencia - use
Microsoft.VisualBasic.DateAndTime.DateDiff
en su código
En mi caso, es necesario calcular el mes completo desde la fecha de inicio hasta el día anterior a este día del mes siguiente o de principio a fin de mes.
Ej: del 1/1/2018 al 31/1/2018 es un mes completo
Ej2: del 5/1/2018 al 4/2/2018 es un mes completo
Así que basado en esto aquí está mi solución:
public static DateTime GetMonthEnd(DateTime StartDate, int MonthsCount = 1)
{
return StartDate.AddMonths(MonthsCount).AddDays(-1);
}
public static Tuple<int, int> CalcPeriod(DateTime StartDate, DateTime EndDate)
{
int MonthsCount = 0;
Tuple<int, int> Period;
while (true)
{
if (GetMonthEnd(StartDate) > EndDate)
break;
else
{
MonthsCount += 1;
StartDate = StartDate.AddMonths(1);
}
}
int RemainingDays = (EndDate - StartDate).Days + 1;
Period = new Tuple<int, int>(MonthsCount, RemainingDays);
return Period;
}
Uso:
Tuple<int, int> Period = CalcPeriod(FromDate, ToDate);
Nota: en mi caso, fue necesario calcular los días restantes después de los meses completos, por lo que si no es su caso, podría ignorar el resultado de los días o incluso cambiar el método de retorno de tupla a entero.
Escribí una función para lograr esto, porque las otras formas no funcionaban para mí.
public string getEndDate (DateTime startDate,decimal monthCount)
{
int y = startDate.Year;
int m = startDate.Month;
for (decimal i = monthCount; i > 1; i--)
{
m++;
if (m == 12)
{ y++;
m = 1;
}
}
return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString());
}
Esto es de mi propia biblioteca, devolverá la diferencia de meses entre dos fechas.
public static int MonthDiff(DateTime d1, DateTime d2)
{
int retVal = 0;
// Calculate the number of years represented and multiply by 12
// Substract the month number from the total
// Substract the difference of the second month and 12 from the total
retVal = (d1.Year - d2.Year) * 12;
retVal = retVal - d1.Month;
retVal = retVal - (12 - d2.Month);
return retVal;
}
Esto es en respuesta a la respuesta de Kirk Woll. Todavía no tengo suficientes puntos de reputación para responder a un comentario ...
Me gustó la solución de Kirk y la iba a copiar y usar de forma desvergonzada en mi código, pero cuando lo revisé me di cuenta de que es demasiado complicado. Cambio innecesario y bucle, y un constructor público que no tiene sentido utilizar.
Aquí está mi reescritura:
public class DateTimeSpan {
private DateTime _date1;
private DateTime _date2;
private int _years;
private int _months;
private int _days;
private int _hours;
private int _minutes;
private int _seconds;
private int _milliseconds;
public int Years { get { return _years; } }
public int Months { get { return _months; } }
public int Days { get { return _days; } }
public int Hours { get { return _hours; } }
public int Minutes { get { return _minutes; } }
public int Seconds { get { return _seconds; } }
public int Milliseconds { get { return _milliseconds; } }
public DateTimeSpan(DateTime date1, DateTime date2) {
_date1 = (date1 > date2) ? date1 : date2;
_date2 = (date2 < date1) ? date2 : date1;
_years = _date1.Year - _date2.Year;
_months = (_years * 12) + _date1.Month - _date2.Month;
TimeSpan t = (_date2 - _date1);
_days = t.Days;
_hours = t.Hours;
_minutes = t.Minutes;
_seconds = t.Seconds;
_milliseconds = t.Milliseconds;
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
return new DateTimeSpan(date1, date2);
}
}
Usage1, más o menos lo mismo:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = new DateTimeSpan(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
Usage2, similar:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years);
Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months);
Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days);
Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours);
Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes);
Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds);
Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds);
}
Esto funcionó para lo que lo necesitaba. El día del mes no importaba en mi caso porque siempre es el último día del mes.
public static int MonthDiff(DateTime d1, DateTime d2){
int retVal = 0;
if (d1.Month<d2.Month)
{
retVal = (d1.Month + 12) - d2.Month;
retVal += ((d1.Year - 1) - d2.Year)*12;
}
else
{
retVal = d1.Month - d2.Month;
retVal += (d1.Year - d2.Year)*12;
}
//// Calculate the number of years represented and multiply by 12
//// Substract the month number from the total
//// Substract the difference of the second month and 12 from the total
//retVal = (d1.Year - d2.Year) * 12;
//retVal = retVal - d1.Month;
//retVal = retVal - (12 - d2.Month);
return retVal;
}
Hay 3 casos: mismo año, año anterior y otros años.
Si el día del mes no importa ...
public int GetTotalNumberOfMonths(DateTime start, DateTime end)
{
// work with dates in the right order
if (start > end)
{
var swapper = start;
start = end;
end = swapper;
}
switch (end.Year - start.Year)
{
case 0: // Same year
return end.Month - start.Month;
case 1: // last year
return (12 - start.Month) + end.Month;
default:
return 12 * (3 - (end.Year - start.Year)) + (12 - start.Month) + end.Month;
}
}
La forma más precisa es esta diferencia de retorno en meses por fracción:
private double ReturnDiffereceBetweenTwoDatesInMonths(DateTime startDateTime, DateTime endDateTime)
{
double result = 0;
double days = 0;
DateTime currentDateTime = startDateTime;
while (endDateTime > currentDateTime.AddMonths(1))
{
result ++;
currentDateTime = currentDateTime.AddMonths(1);
}
if (endDateTime > currentDateTime)
{
days = endDateTime.Subtract(currentDateTime).TotalDays;
}
return result + days/endDateTime.GetMonthDays;
}
Mi comprensión de la diferencia total de meses entre 2 fechas tiene una parte integral y una parte fraccionaria (la fecha es importante).
La parte integral es la diferencia de meses completos.
La parte fraccionaria, para mí, es la diferencia del% del día (a los días completos del mes) entre los meses iniciales y finales.
public static class DateTimeExtensions
{
public static double TotalMonthsDifference(this DateTime from, DateTime to)
{
//Compute full months difference between dates
var fullMonthsDiff = (to.Year - from.Year)*12 + to.Month - from.Month;
//Compute difference between the % of day to full days of each month
var fractionMonthsDiff = ((double)(to.Day-1) / (DateTime.DaysInMonth(to.Year, to.Month)-1)) -
((double)(from.Day-1)/ (DateTime.DaysInMonth(from.Year, from.Month)-1));
return fullMonthsDiff + fractionMonthsDiff;
}
}
Con esta extensión, esos son los resultados:
2/29/2000 TotalMonthsDifference 2/28/2001 => 12
2/28/2000 TotalMonthsDifference 2/28/2001 => 12.035714285714286
01/01/2000 TotalMonthsDifference 01/16/2000 => 0.5
01/31/2000 TotalMonthsDifference 01/01/2000 => -1.0
01/31/2000 TotalMonthsDifference 02/29/2000 => 1.0
01/31/2000 TotalMonthsDifference 02/28/2000 => 0.9642857142857143
01/31/2001 TotalMonthsDifference 02/28/2001 => 1.0
Para obtener la diferencia en meses (tanto inicio como final incluido), independientemente de las fechas:
DateTime start = new DateTime(2013, 1, 1);
DateTime end = new DateTime(2014, 2, 1);
var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
Podrías hacerlo
if ( date1.AddMonths(x) > date2 )
Puede usar la clase DateDiff de la biblioteca de períodos de tiempo para .NET :
// ----------------------------------------------------------------------
public void DateDiffSample()
{
DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
DateDiff dateDiff = new DateDiff( date1, date2 );
// differences
Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
// > DateDiff.Months: 16
// elapsed
Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
// > DateDiff.ElapsedMonths: 4
// description
Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) );
// > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs
} // DateDiffSample
Puedes tener una función como esta.
Por ejemplo, del 2012/12/27 al 2012/12/29 se convierte en 3 días. Del mismo modo, desde el 2012/12/15 al 2013/01/15 se convierte en 2 meses, porque hasta el 2013/01/14 es 1 mes. a partir del día 15 comienza el 2º mes.
Puede eliminar el "=" en la segunda condición if, si no desea incluir ambos días en el cálculo. Es decir, desde el 2012/12/15 al 2013/01/15 es de 1 mes.
public int GetMonths(DateTime startDate, DateTime endDate)
{
if (startDate > endDate)
{
throw new Exception("Start Date is greater than the End Date");
}
int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month);
if (endDate.Day >= startDate.Day)
{
months++;
}
return months;
}
Puedes usar la siguiente extensión: Código
public static class Ext
{
#region Public Methods
public static int GetAge(this DateTime @this)
{
var today = DateTime.Today;
return ((((today.Year - @this.Year) * 100) + (today.Month - @this.Month)) * 100 + today.Day - @this.Day) / 10000;
}
public static int DiffMonths(this DateTime @from, DateTime @to)
{
return (((((@to.Year - @from.Year) * 12) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 100);
}
public static int DiffYears(this DateTime @from, DateTime @to)
{
return ((((@to.Year - @from.Year) * 100) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 10000;
}
#endregion Public Methods
}
Implementación!
int Age;
int years;
int Months;
//Replace your own date
var d1 = new DateTime(2000, 10, 22);
var d2 = new DateTime(2003, 10, 20);
//Age
Age = d1.GetAge();
Age = d2.GetAge();
//positive
years = d1.DiffYears(d2);
Months = d1.DiffMonths(d2);
//negative
years = d2.DiffYears(d1);
Months = d2.DiffMonths(d1);
//Or
Months = Ext.DiffMonths(d1, d2);
years = Ext.DiffYears(d1, d2);
Si desea el número exacto de meses completos, siempre positivo (2000-01-15, 2000-02-14 devuelve 0), considerando que un mes completo es cuando llega al mismo día del mes siguiente (algo como el cálculo de la edad)
public static int GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
return monthDiff - 1;
}
else
{
return monthDiff;
}
}
Motivo de edición: el código antiguo no era correcto en algunos casos como:
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
Test cases I used to test the function:
var tests = new[]
{
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
};
Solo necesitaba algo simple para atender, por ejemplo, fechas de empleo en las que solo se ingresa el mes / año, por lo que se buscan años distintos y meses trabajados. Esto es lo que uso, aquí solo por utilidad
public static YearsMonths YearMonthDiff(DateTime startDate, DateTime endDate) {
int monthDiff = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month) + 1;
int years = (int)Math.Floor((decimal) (monthDiff / 12));
int months = monthDiff % 12;
return new YearsMonths {
TotalMonths = monthDiff,
Years = years,
Months = months
};
}
Suponiendo que el día del mes es irrelevante (es decir, la diferencia entre 2011.1.1 y 2010.12.31 es 1), con fecha1> fecha2 que da un valor positivo y fecha2> fecha1 un valor negativo
((date1.Year - date2.Year) * 12) + date1.Month - date2.Month
O, suponiendo que desee un número aproximado de "meses promedio" entre las dos fechas, lo siguiente debería funcionar para todas las diferencias de fecha, pero muy grandes.
date1.Subtract(date2).Days / (365.25 / 12)
Tenga en cuenta que si utilizara la última solución, entonces las pruebas unitarias deben indicar el rango de fechas más amplio con el que está diseñada su aplicación para trabajar y validar los resultados del cálculo en consecuencia.
Actualización (gracias a Gary )
Si utiliza el método de "meses promedio", un número un poco más preciso para usar para el "número promedio de días por año" es 365.2425 .
Use el tiempo Noda :
LocalDate start = new LocalDate(2013, 1, 5);
LocalDate end = new LocalDate(2014, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months); // 16
(fuente de ejemplo)
Así es como abordamos esto:
public static int MonthDiff(DateTime date1, DateTime date2)
{
if (date1.Month < date2.Month)
{
return (date2.Year - date1.Year) * 12 + date2.Month - date1.Month;
}
else
{
return (date2.Year - date1.Year - 1) * 12 + date2.Month - date1.Month + 12;
}
}
Estructura de Kirks expandida con ToString (formato) y Duración (largo ms)
public struct DateTimeSpan
{
private readonly int years;
private readonly int months;
private readonly int days;
private readonly int hours;
private readonly int minutes;
private readonly int seconds;
private readonly int milliseconds;
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.milliseconds = milliseconds;
}
public int Years { get { return years; } }
public int Months { get { return months; } }
public int Days { get { return days; } }
public int Hours { get { return hours; } }
public int Minutes { get { return minutes; } }
public int Seconds { get { return seconds; } }
public int Milliseconds { get { return milliseconds; } }
enum Phase { Years, Months, Days, Done }
public string ToString(string format)
{
format = format.Replace("YYYY", Years.ToString());
format = format.Replace("MM", Months.ToString());
format = format.Replace("DD", Days.ToString());
format = format.Replace("hh", Hours.ToString());
format = format.Replace("mm", Minutes.ToString());
format = format.Replace("ss", Seconds.ToString());
format = format.Replace("ms", Milliseconds.ToString());
return format;
}
public static DateTimeSpan Duration(long ms)
{
DateTime dt = new DateTime();
return CompareDates(dt, dt.AddMilliseconds(ms));
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
No hay muchas respuestas claras sobre esto porque siempre estás asumiendo cosas.
Esta solución calcula entre dos fechas los meses entre el supuesto de que desea guardar el día del mes para la comparación, (lo que significa que el día del mes se considera en el cálculo)
Por ejemplo, si tiene una fecha del 30 de enero de 2012, el 29 de febrero de 2012 no será un mes, pero el 01 de marzo de 2013 sí lo será.
Ha sido probado bastante a fondo, probablemente lo limpiará más tarde a medida que lo usemos, pero aquí:
private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
{
int intReturn = 0;
bool sameMonth = false;
if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
intReturn--;
int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn''t have that many days
int daysinMonth = 0; //used to caputre how many days are in the month
while (dtOther.Date > dtThis.Date) //while Other date is still under the other
{
dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month
if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
{
if (daysinMonth < dayOfMonth) // uses day in month max if can''t set back to day of month
dtThis.AddDays(daysinMonth - dtThis.Day);
else
dtThis.AddDays(dayOfMonth - dtThis.Day);
}
if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
{
if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
intReturn++;
sameMonth = true; //sets this to cancel out of the normal counting of month
}
if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn''t reach the same month (or if i started in the same month, one month ahead, add a month)
intReturn++;
}
return intReturn; //return month
}
Ser capaz de calcular la diferencia entre 2 fechas en meses es algo perfectamente lógico, y es necesario en muchas aplicaciones comerciales. Los diversos programadores que han proporcionado comentarios como: ¿cuál es la diferencia en meses entre "1 de mayo de 2010" y "16 de junio de 2010", cuál es la diferencia en meses entre el 31 de diciembre de 2010 y el 1 de enero de 2011? Los fundamentos de las aplicaciones empresariales.
Aquí está la respuesta a los 2 comentarios anteriores: el número de meses entre el 1 de mayo de 2010 y el 16 de junio de 2010 es de 1 mes, el número de meses entre el 31 de diciembre de 2010 y el 1 de enero de 2011 es de 0. Es Sería muy tonto calcularlos como 1,5 meses y 1 segundo, como han sugerido los codificadores anteriores.
Las personas que han trabajado en tarjetas de crédito, procesamiento de hipotecas, procesamiento de impuestos, procesamiento de alquileres, cálculos de intereses mensuales y una amplia variedad de otras soluciones empresariales estarían de acuerdo.
El problema es que tal función no está incluida en C # o VB.NET para esa materia. Datediff solo tiene en cuenta los años o el componente del mes, por lo que en realidad es inútil.
Aquí hay algunos ejemplos de la vida real de donde necesita y puede calcular correctamente los meses:
Usted vivió en un alquiler a corto plazo del 18 de febrero al 23 de agosto. ¿Cuántos meses te quedaste allí? La respuesta es simple - 6 meses.
Usted tiene una cuenta bancaria donde los intereses se calculan y se pagan al final de cada mes. Usted deposita dinero el 10 de junio y lo saca 29 de octubre (el mismo año). ¿En cuántos meses obtienes interés? Muy simple respuesta- 4 meses (nuevamente los días extra no importan)
En las aplicaciones de negocios, la mayoría de las veces, cuando necesita calcular meses, es porque necesita saber meses "completos" en función de cómo los humanos calculan el tiempo; No se basa en algunos pensamientos abstractos / irrelevantes.
var dt1 = (DateTime.Now.Year * 12) + DateTime.Now.Month;
var dt2 = (DateTime.Now.AddMonths(-13).Year * 12) + DateTime.Now.AddMonths(-13).Month;
Console.WriteLine(dt1);
Console.WriteLine(dt2);
Console.WriteLine((dt1 - dt2));
Public Class ClassDateOperation
Private prop_DifferenceInDay As Integer
Private prop_DifferenceInMonth As Integer
Private prop_DifferenceInYear As Integer
Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation
Dim differenceInDay As Integer
Dim differenceInMonth As Integer
Dim differenceInYear As Integer
Dim myDate As Date
DateEnd = DateEnd.AddDays(1)
differenceInYear = DateEnd.Year - DateStart.Year
If DateStart.Month <= DateEnd.Month Then
differenceInMonth = DateEnd.Month - DateStart.Month
Else
differenceInYear -= 1
differenceInMonth = (12 - DateStart.Month) + DateEnd.Month
End If
If DateStart.Day <= DateEnd.Day Then
differenceInDay = DateEnd.Day - DateStart.Day
Else
myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1)
If differenceInMonth <> 0 Then
differenceInMonth -= 1
Else
differenceInMonth = 11
differenceInYear -= 1
End If
differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day
End If
prop_DifferenceInDay = differenceInDay
prop_DifferenceInMonth = differenceInMonth
prop_DifferenceInYear = differenceInYear
Return Me
End Function
Public ReadOnly Property DifferenceInDay() As Integer
Get
Return prop_DifferenceInDay
End Get
End Property
Public ReadOnly Property DifferenceInMonth As Integer
Get
Return prop_DifferenceInMonth
End Get
End Property
Public ReadOnly Property DifferenceInYear As Integer
Get
Return prop_DifferenceInYear
End Get
End Property
End Class
int nMonths = 0;
if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;
else
nMonths = (12 - FDate.Month) + TDate.Month;
public static int PayableMonthsInDuration(DateTime StartDate, DateTime EndDate)
{
int sy = StartDate.Year; int sm = StartDate.Month; int count = 0;
do
{
count++;if ((sy == EndDate.Year) && (sm >= EndDate.Month)) { break; }
sm++;if (sm == 13) { sm = 1; sy++; }
} while ((EndDate.Year >= sy) || (EndDate.Month >= sm));
return (count);
}
Esta solución es para el cálculo de alquiler / suscripción, donde la diferencia no significa ser una resta, se supone que es el lapso dentro de esas dos fechas.