.NET – Restar objetos DateTime

Hoy es mi cumpleaños 😛 Felicítenme.

Ni al caso con el post, dirán. Pero en realidad sí tiene que ver. Ayer varios me estuvieron felicitando, pensando que ése día fue mi cumpleaños. Al final, uno me dijo que Hotmail decía que ayer cumplí años. No creía haber puesto mal la fecha, así que entré a Hotmail, a mi perfil, y vi que decía “Fecha de nacimiento: 23 de sept. de 1985 (26 años)”.

¿Cómo que 26 años, si todavía me faltaba un día? Saquen la cuenta: 2010 – 1985 = 25. No cuenta 2011 porque todavía no llegaba el 23. Pero bueno, ya era tarde y no me iba a preocupar por eso.

Hoy que llegué al trabajo, me resurgió la duda. Ya que el sitio de Hotmail está hecho en .NET (o al menos la extensión de las páginas web dice eso), hice una aplicación en .NET para hacer la prueba.

De entrada, nunca he restado objetos de tipo DateTime, así que no estaba muy seguro de cómo hacerlo. Me informé un poco y esto fue lo que hice:

DateTime dt1 = new DateTime(2011, 9, 22);
DateTime dt2 = new DateTime(1985, 9, 23);
// La resta de dos DateTimes resulta en un TimeSpan
TimeSpan ts = dt1 - dt2;
// No se puede convertir un TimeSpan a DateTime ¬¬
// Hay que agregarlo a un DateTime con fecha "vacía"
DateTime dt3 = new DateTime().Add(ts);

Como resultado de esto, dt3 me dio igual a 31 días, 12 meses y ¡26 años!

.NET resta el valor de la propiedad Ticks de ambos DateTimes para sacar el resultado, pero no sé por qué sale mal la fecha. Si usamos la calculadora de Windows (solo con Win Vestia o 7, menú Ver > Cálculo de fecha), y restamos esas dos fechas salen 30 días, 12 meses y 25 años, como debe ser. Son 30 días porque no cuenta el último día del año, que sería el 31 de diciembre.

Así que mi recomendación sería crear un método de extensión para la clase DateTime que contenga esto:

public static class ExtensionMethods(){
    public static DateTime SubtractDate(
        this DateTime currentDate,
        DateTime date)
    {
        DateTime newDate = currentDate;
        newDate = newDate.AddMilliseconds(-date.Millisecond);
        newDate = newDate.AddSeconds(-date.Second);
        newDate = newDate.AddMinute(-date.Minute);
        newDate = newDate.AddHours(-date.Hour);
        newDate = newDate.AddDays(-date.Days);
        newDate = newDate.AddMonths(-date.Month);
        newDate = newDate.AddYears(-date.Year);
        return newDate;
    }
}

Este cálculo sí da el resultado correcto. Si volteamos todas las operaciones (empezar por el año y terminar con los milisegundos), la fecha se va afectando y da otro resultado que no es correcto.

Anuncios

Autor: Israel Muñoz

Soy desarrollador de software, principalmente dedicado a desarrollo de aplicaciones web. Especializado en .NET full-stack, además de tecnologías front-end HTML, CSS y JavaScript. A ratos, profesor de materias de informática. Me gusta mucho todo lo que tiene que ver con las tecnologías nuevas para desarrollo web, y el diseño de sitios y aplicaciones.

2 comentarios en “.NET – Restar objetos DateTime”

  1. Saludos, al buscar operaciones con fechas llegué a este post pero veo algunas falencias….. en primer lugar en el ejemplo propuesto no deberia darte nunca 30 días, 12 meses y 25 años ya que al decir 12 meses este pasaría automáticamente a un año adicional.

    La respuesta correcta es: 25años 11 meses 29 días ya que al sumarle 1 dia a este resultado llegaríamos a los 26 años del ejercicio.

    Al final me cree mi propia funcion que hace el cálculo.

    Public Function fechas(ByVal fecha1 As String, ByVal fecha2 As String) As String

    Dim a1, a2, m1, m2, d1, d2, af, mf, df, diames As Integer
    Dim res As String
    d1 = CInt(fecha1.Substring(0, 2))
    d2 = CInt(fecha2.Substring(0, 2))
    m1 = CInt(fecha1.Substring(3, 2))
    m2 = CInt(fecha2.Substring(3, 2))
    a1 = CInt(fecha1.Substring(6, 4))
    a2 = CInt(fecha2.Substring(6, 4))

    If ((d2) < (d1)) Then
    diames = System.DateTime.DaysInMonth(a2, m2)
    d2 = d2 + diames
    m2 = (m2) – 1
    df = d2 – d1
    Else
    df = d2 – d1
    End If

    If (m2 < m1) Then
    m2 = m2 + 12
    a2 = a2 – 1
    mf = m2 – m1
    Else
    mf = m2 – m1
    End If

    af = a2 – a1
    res = CStr(af) + " AÑOS, " + CStr(mf) + " MESES, " + CStr(df) + " DIAS"
    mesfinal = mf
    diafinal = df
    Return res
    End Function

    1. No recordaba que tenía este post.
      De hecho, hace tiempo que descubrí unos fallos en esta función, pero no me acordé de ponerlo aquí.
      Muchas gracias por el aporte 🙂

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

w

Conectando a %s