bibigeek.com  Tu blog de Programación Geek: Java, php, J2EE... y mucho más

Archive for the ‘ Fechas Java ’ Category

Buenas,
Ya estoy de nuevo otra vez. Siento el retraso, no es que haya abandonado el blog :P , he estado super liado con cursos en la empresa y la verdad que no me ha permitido dedicarme mucho al blog.

Hoy vamos hablar de nuevo sobre las fechas en Java, es un tema tan amplio que pienso que aun me quedan múchisimos posts para escribir sobre el tema.
Veamos, este Post en concreto, tiene mucho que ver con el anterior que escribí sobre fechas: como utilizar correctamente las fechas en Java. ¿Por qué? Porque es realmente importante utilizar las herramientas que proporciona Java para las fechas, ya que a veces cuyas herramientas tienen en cuenta factores que nosotros no podemos controlar, como ejemplo podéis leer el Post del link anterior y lo comprobaréis con vuestros ojos.
Hoy voy a explicar una cosa que me he dejado en todos los Posts de Java que he escrito anteriormente, y que omití (perdonadme):

¿Qué herramienta utilizar para restar dos fechas en Java? ¿Qué utilizar para obtener la diferencia entre dos fechas en java?

Yo recomiendo, plenamente, utilizar el GregorianCalendar. Es lo que comentaba antes, hay que utilizar las herramientas de Java destinadas a la solución/manejo del tema a tratar, en este caso las Fechas.

¿Por qué no utilizar la clase Date? Si miráis minuciosamente la API de la clase Date, podréis comprobar que muchos de los métodos están siendo Deprecated y SUN están dando más relevancia las clases Calendar, Gregorian Calendar, etc.

Con eso no quiero decir que funcione mejor o peor una Clase u otra, pero desde mi punto de vista siempre hay que utilizar las clases idóneas. Reitero, MI PUNTO DE VISTA.

¿Cómo restar dos fechas en Java? ¿Cómo obtener la diferencia entre dos fechas en Java?

Necesitamos los siguientes datos para calcular la resta:

  1. Tener dos objetos GregorianCalendar o Date (ya sea obtenidos con string, con Calendar, etc…)
  2. Efectuar operaciones matemáticas simples (como mucho una multiplicación) sin que intervengan los milisegundos :P

A este punto voy a dividirlo en dos subpuntos: restar fechas del mismo año o restar fechas de distinto año. Empecemos:

Restar dos Fechas en Java que son del mismo año


/*CREAMOS EL GREGORIAN CALENDAR DE LAS DOS FECHAS*/
GregorianCalendar t1 = new GregorianCalendar(2009,9,23);
GregorianCalendar t2 = new GregorianCalendar(2009,9,28);

/*RESTAR FECHAS*/
int dias =  t2.get(Calendar.DAY_OF_YEAR) - t1.get(Calendar.DAY_OF_YEAR);

/*IMPRESION POR PANTALLA*/
System.out.println("Valor de días es: " + dias);

Están fácil como esto, RESTAR y PUNTO. Salida por pantalla es:


Valor de días es: 5

Se puede dar el caso de que necesitemos crear los dos objetos GregorianCalendar dados dos objetos Date. El código quedaría así:


        /* CREAMOS LOS OBJETOS GREGORIAN CALENDAR PARA EFECTUAR LA RESTA */
        GregorianCalendar date1 = new GregorianCalendar();
        date1.setTime(dateIni); //dateIni es el objeto Date

        GregorianCalendar date2 = new GregorianCalendar();
        date2.setTime(dateFin); //dateFin es el objeto Date

¿Qué problemas puede conllevar esto?
Pues el problema está cuando cogemos dos fechas de distinto año, el problema que puede darse es que el número no sea el correcto o el que esperamos. Veamos como es la salida por pantalla de la resta de las fechas: 2009/12/25 y 2010/01/02 (teóricamente deberían ser 8 días):


Valor de días es: -357 //( si le restásemos 365 días que tiene el año daría 8) 

Restar dos Fechas en Java de diferente año

Gracias al comentario anterior, y buscando en san Google se me ocurrió la brillante idea (que buscando, buscando, también lo encontré en un foro inglés :-( ) de hacer lo siguiente:


        /*CREAMOS EL GREGORIAN CALENDAR DE LAS DOS FECHAS*/
        GregorianCalendar date1 = new GregorianCalendar(2009,11,25);
        GregorianCalendar date2 = new GregorianCalendar(2010,0,2);

        /* COMPROBAMOS SI ESTAMOS EN EL MISMO ANYO */
        if (date1.get(Calendar.YEAR) == date2.get(Calendar.YEAR)) {
            System.out.println( "Valor de Resta simple: " +String.valueOf(date2.get(Calendar.DAY_OF_YEAR) - date1.get(Calendar.DAY_OF_YEAR)));
        } else {
            /* SI ESTAMOS EN DISTINTO ANYO COMPROBAMOS QUE EL ANYO DEL DATEINI NO SEA BISIESTO
             * SI ES BISIESTO SON 366 DIAS EL ANYO
             * SINO SON 365
             */
            int diasAnyo = date1.isLeapYear(date1.get(Calendar.YEAR)) ? 366 : 365;

            /* CALCULAMOS EL RANGO DE ANYOS */
            int rangoAnyos = date2.get(Calendar.YEAR) - date1.get(Calendar.YEAR);

            /* CALCULAMOS EL RANGO DE DIAS QUE HAY */
            int rango = (rangoAnyos * diasAnyo) + (date2.get(Calendar.DAY_OF_YEAR) - date1.get(Calendar.DAY_OF_YEAR));

        }
        System.out.println("Valor de rangoDias:" + (date2.get(Calendar.DAY_OF_YEAR) - date1.get(Calendar.DAY_OF_YEAR)));
        System.out.println("Valor de rangoAnyos: " + nAnyos);
        System.out.println("Valor de rango: " + rango);

El resultado importante es el de rango, resultado por pantalla es:


Valor de rangoAnyos: -357
Valor de nAnyos: 1
Valor de diasCorrectos: 8

Fijáos que he tenido que controlar la opción del AÑO BISIESTO… que también se tiene que controlar. Si volvéis a mirar el código lo he solucionado con esta simple operacion:


int diasAnyo = date1.isLeapYear(date1.get(Calendar.YEAR)) ? 366 : 365;

También deseo remarcar que he realizado un IF para controlar si la resta se hace con fechas del mismo año o si son diferentes años

Cómo restar con la clase Date (MI OPINIÓN INCORRECTO)

Utilizando los milisegundos es problemático… desde mi punto de vista, INCORRECTO. Problemas con cambios de hora,…


        Date actual = new Date();
        Date fecha =null;
        String dateFrom = "20091023";
        SimpleDateFormat day= new SimpleDateFormat("yyyyMMdd");
        try {
            fecha = day.parse(dateFrom);
        } catch (ParseException ex) {
            ex.getMessage();
            ex.printStackTrace();
        }
        long diferencia= ( fecha.getTime() - actual.getTime() );

        System.out.println("Valor de diferencia: " + diferencia/(1000*60*60*24));

¿Es una opción viable? SÍ, menos cuando hay cambios de hora por el medio. Debemos ir con precaución y repito: mejor utilizar las clases Java preparadas para el problema en cuestión.

Espero que os haya servido de algo, al menos para solucionar algún problema o ayudaros a entender un poco más las fechas en Java.

ACTUALIZACIÓN

Actualizo este post por el mero echo que aNieto2K me ha sugerido que pusiera estadísticas :P . Lo sé Andrés, tengo que currarmelo más jejeje.

[More]

Gracias que en el trabajo surgen siempre algunas que otras problemáticas, vimos un mal USO de las Fechas utilizando Java en un Servicio concreto. Voy a exponerlo aquí y cómo se ha solucionado.

Repaso de la Clase Date para las Fechas en Java (no es la mejor práctica)

En muchas páginas de Internet, y en algunos que otros libros de referencia, a la hora de crear una fecha se utiliza la Clase Date.
Pero poco a poco, han ido apareciendo nuevas clases para el manejo de Fechas en Java (así cómo se explicó en Posts Anteriores: Parsear Fechas, Utilizar Calendar y operaciones con Gregorian Calendar),  y muchos de los métodos de la clase Date se han ido poniendo como “Deprecated”.

Veamos un repaso de la clase Date:
Repaso 1. Coger el instante actual:


/* FECHA DE ESTE MISMO MOMENTO */
Date fecha = new Date();
System.out.println("Fecha actual: " + fecha);
/* FECHA DE ESTE MISMO MOMENTO */
Date fecha = new Date();
System.out.println("Fecha actual: " + fecha);

La salida por pantalla es el siguiente:


Fecha actual: Mon Sep 28 13:25:15 CEST 2009

Nos tenemos que fijar en una serie de puntos relevantes:

  1. Prueba realizada el 28 de Septiembre del 2009
  2. Y la hora en la cual se construido el objeto Date es a las 13:25:15

Fijaos en la hora, es muy importante… ya que está cogiendo la hora real del momento de la ejecución del constructor.

Repaso 2. Crear un objeto Date dado un String con el día concreto:


/* FECHA DE ESTE MISMO MOMENTO */
Date fecha = new Date();
System.out.println("Fecha actual: " + fecha);

/* CREAMOS LA FECHA (TIPO DATE) Y NOS PASAN UNA DIA CONCRETO (SIN HORA) */
String fechaString = "28092009";

/* FORMATO DE ENTRADA DE LA FECHA - DESPUES RECUPERAMOS EL TIPO DATE */
SimpleDateFormat day= new SimpleDateFormat("ddMMyyyy");
/*INSTACIAMOS UN OBJETO DE TIPO DATE A NULL*/
Date fechaDate = null;
try {
/*CONTRUIMOS UN OBJETO DATE DADO UN STRING DE ENTRADA*/
fechaDate = day.parse(fechaString);
System.out.println("Fecha Dado un String: " + fechaDate);
} catch (ParseException ex) {
ex.printStackTrace();
}

La salida por pantalla es:


Fecha Dado un String: Mon Sep 28 00:00:00 CEST 2009

Vemos algunas diferencias entre la salida anterior y ésta ¿verdad? La hora, exactamente. El día es el mismo, la hora por defecto, si no se la indicamos, el constructor la define como si fueran las 00:00:00.

MAL USO de las Fechas en Java

Si queremos operar con las fechas y la clase Date, será necesario operar en un “lenguaje común” los milisegundos. Para ello necesitamos conocer que:

  • La clase Date tiene un método llamado getTime(), que retorna los milisegundos del objeto Date
  • Tenemos que realizar una multiplicación (Factor de Conversion) para obtener los milisegundos dado el número de días
  • Este factor de conversión se hace como: días * 24 * 60 * 60 * 1000

Veamos un ejemplo de SUMA:
[More]

Ahora si, finalmente explicaré la Clase GregorianCalendar. Tenemos que remontarnos al POST anterior sobre las fechas en Java, el II en concreto, para hacer un poco de memoria. Vamos hacernos las siguientes preguntas:

¿De dónde viene la clase GregorianCalendar y qué representa?

La clase Gregorian Calendar no es más que una subclase de Calendar, la cual tiene implementada el Calendario más utilizado en casi todo el mundo, el Gregoriano. Pulsa aquí para ver la Historia del Calendario Gregoriano.

¿Función de la clase GregorianCalendar?¿Objetivo?

La función principal es la de implementar las características del Calendario Gregoriano, tener en cuenta que no en todo el mundo se está utilizando el mismo Tipo de Calendario (acordaros de lo que dije en el otro POST). El objetivo principal es el de poder operar con las fechas (sumarle dos días, restar etc…) sin tener la preocupación de posibles desbordamientos o tener que recalcular el valor del mes, año…

¿Por qué razón hay que utilizarla?

Por el mero hecho de ser una Clase probada y que con ella estamos utilizando el Calendario utilizado en casi todo el mundo!!!!! Y como no, estamos asegurándonos que las operaciones que realizamos están totalmente controladas y serán correctas.

Como la clase GregorianCalendar hereda de la clase Abstracta Calendar, tenemos los mismos métodos que la clase Calendar, no puedo asegurarlo, pero seguro que nos podremos encontrar con algunos métodos sobreescritos (permitido en Java por se un lenguaje Orientado a Objetos). Veamos algunos ejemplos de código:

Obtener la fecha con GregorianCalendar:


GregorianCalendar gregorian = new GregorianCalendar();
System.out.println("Valor de Gregorian obteniendo un objeto DATE: " + gregorian.getTime());

Sumar con GregorianCalendar:


gregorian.add(GregorianCalendar.DATE, 5); //Sumamos 5 Dias
gregorian.add(GregorianCalendar.MINUTE, 15); //Le sumamos 15 minutos a la actual
System.out.println("Modificada la fecha Gregorian: " + gregorian.getTime());

Restar con GregorianCalendar:


gregorian.add(GregorianCalendar.DATE, -2); //Sumamos 5 Dias
gregorian.add(GregorianCalendar.MINUTE, -25); //Le sumamos 15 minutos a la actual
System.out.println("Modificada la fecha Gregorian: " + gregorian.getTime());

Resultado:


Valor de Gregorian obteniendo un objeto DATE: Wed Apr 01 23:33:43 CEST 2009
Modificada la fecha Gregorian: Mon Apr 06 23:48:43 CEST 2009
Modificada la fecha Gregorian: Sat Apr 04 23:23:43 CEST 2009

Espero que este Post también os haya servido de algo, ya que mi intención es esa, ayudaros y ayudarme a mi mismo a ser mejor.
Saludos!!!!

Segunda parte de las fechas en Java…

calendario

Esta vez voy a explicar un poco el funcionamiento de la clase Calendar y GregorianCalendar, y del porque utilizar estas clases (ya tuvimos importantes problemas en el trabajo…os el problema y la solución en otro POST). Utilizaremos la API (Calendar y GregorianCalendar). Explicaré más detenidamente las clases anteriores y las diferencias con la clase Date:

La clase Date, un poco más allá…

[More]

Mi primer POST, que bien suena ¿verdad?… va para Kuanale y Nieto, a ver si aprendéis JAVA :p

Java y las fechas, las fechas y java…Los programadores Java, al menos en mi caso, tenemos algunos que otros problemas con las fechas en Java. En el trabajo hemos tenido graves problemas con ellas, y más, como es en el Sector Turístico. Si no os queda algo claro de lo que expondré no dudéis en contactar conmigo y os ayudaré de mucho gusto, o en el caso que no estéis de acuerdo conmigo también, se agradecerá vuestra colaboración…

Formateo de Fechas en Java

[More]