¿Por qué el constructor Date está en desuso y qué uso en su lugar?

6 minutos de lectura

Avatar de usuario de Svish
svish

Vengo del mundo de C#, por lo que aún no tengo mucha experiencia con Java. Eclipse me acaba de decir que Date estaba en desuso:

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

¿Por qué? ¿Y qué (especialmente en casos como el anterior) debería usarse en su lugar?

  • Estoy experimentando una curva de aprendizaje similar, también pasando de C# a Java. La otra cosa que me molestó es que el mes del año es un sistema basado en 0 (0 a 11 donde enero = 0 y diciembre = 11) pero los días del mes están basados ​​en 1 (1 a 31). ¡Cuidado con eso!

    -Paul Sasik

    15 de abril de 2011 a las 13:36


  • @Paul Sasik, sí, pero hay una constante Calendar. JANUARY, por ejemplo, y una para cada mes

    – Diogo

    15 de abril de 2011 a las 14:07

  • @PaulSasik jajaja. Sí, estúpido Java. Tuve que cambiar de C# a Java y Dios mío, el dolor y la miseria.

    – cbmeeks

    22 de marzo de 2013 a las 13:56

  • posible duplicado de ¿Por qué la mayoría de los métodos java.util.Date quedaron en desuso?

    – Tomás

    26 de noviembre de 2013 a las 8:00

  • Los comentarios sarcásticos “lol” sobre Java de la gente de C# hicieron a mí reírse porque .Net obtuvo su biblioteca de fecha y hora decente (Hora de Noda) desde un puerto de la excelente biblioteca Java Joda-Tiempo.

    – Basil Bourque

    6 de febrero de 2014 a las 8:48


Avatar de usuario de BuffaloBuffalo
BúfaloBúfalo

El java.util.Date La clase en realidad no está en desuso, solo ese constructor, junto con un par de otros constructores/métodos están en desuso. Estaba en desuso porque ese tipo de uso no funciona bien con la internacionalización. El Calendar En su lugar, se debe usar la clase:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

Eche un vistazo a la fecha Javadoc:

http://download.oracle.com/javase/6/docs/api/java/util/Date.html

  • Esta debería ser la mejor respuesta. Gracias.

    – jordaniac89

    28 de mayo de 2015 a las 2:02

  • Al decir “no funciona bien con la internacionalización”, ¿quiere decir que para la fecha, no puede asignarle una zona horaria? Gracias

    – Sumergirse en

    1 de diciembre de 2015 a las 5:55


  • ¿Qué hizo Date fue analizar una cadena, por lo que ahora tenemos que subcadenar una cadena que contiene el año, el mes y el día? Parece una gran cantidad de problemas adicionales para algo que, en la mayoría de los casos, no necesita una lógica y métodos tan complejos que se le agreguen.

    – G_V

    6 de marzo de 2017 a las 8:39

  • Solo para agregar, esto tendrá en cuenta la zona horaria predeterminada. Si queremos especificar cualquier otra zona horaria, podemos usar Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(<timezone id>));

    – Vikas Prasad

    17/03/2017 a las 16:45


  • “La clase Calendario debería usarse en su lugar” – Para Java 8 y posteriores, el java.time.* las clases son la mejor opción… si está cambiando su código.

    – Esteban C.

    30 de mayo de 2018 a las 6:15


Avatar de usuario de Basil Bourque
albahaca bourque

tl; dr

LocalDate.of( 1985 , 1 , 1 )

…o…

LocalDate.of( 1985 , Month.JANUARY , 1 )

Detalles

El java.util.Date, java.util.Calendary java.text.SimpleDateFormat las clases se apresuraron demasiado cuando Java se lanzó y evolucionó por primera vez. Las clases no estaban bien diseñadas o implementadas. Se intentaron mejoras, por lo tanto, las obsolescencias que ha encontrado. Lamentablemente, los intentos de mejora fracasaron en gran medida. Debería evitar estas clases en total. Son suplantados en Java 8 por nuevas clases.

Problemas en su código

Un java.util.Date tiene una porción de fecha y hora. Ignoraste la porción de tiempo en tu código. Entonces, la clase Fecha tomará el comienzo del día según lo define la zona horaria predeterminada de su JVM y aplicará esa hora al objeto Fecha. Por lo tanto, los resultados de su código variarán según la máquina que se ejecute o la zona horaria configurada. Probablemente no sea lo que quieres.

Si solo desea la fecha, sin la parte de la hora, como para una fecha de nacimiento, es posible que no desee utilizar un Date objeto. Es posible que desee almacenar solo una cadena de la fecha, en ISO 8601 formato de YYYY-MM-DD. O usa un LocalDate objeto de Joda-Time (ver más abajo).

Joda-Tiempo

Lo primero que debe aprender en Java: Evite las clases java.util.Date y java.util.Calendar notoriamente problemáticas incluido con Java.

Como se señaló correctamente en la respuesta del usuario 3277382, use cualquiera Joda-Tiempo o el nuevo paquete java.time.* en Java 8.

Código de ejemplo en Joda-Time 2.3

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

Volcar a la consola…

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

Cuando se ejecuta…

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

java.tiempo

En este caso el código de java.tiempo es casi idéntico al de Joda-Tiempo.

Obtenemos una zona horaria (ZoneId), y construya un objeto de fecha y hora asignado a esa zona horaria (ZonedDateTime). Luego usando el Objetos inmutables patrón, creamos nuevas fechas y horas basadas en el mismo instante del objeto anterior (recuento de nanosegundos desde época) pero se le asignó otra zona horaria. Por último obtenemos un LocalDate que no tiene hora del día ni zona horaria, aunque tenga en cuenta que la zona horaria se aplica al determinar esa fecha (un nuevo día amanece antes en Oslo que en Nueva York Por ejemplo).

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

Acerca de java.tiempo

El java.tiempo framework está integrado en Java 8 y versiones posteriores. Estas clases suplantan a las viejas y problemáticas legado clases de fecha y hora como java.util.Date, Calendar& SimpleDateFormat.

Para obtener más información, consulte la Tutorial de oráculo. Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310.

El Joda-Tiempo proyecto, ahora en modo de mantenimientoaconseja la migración a la java.tiempo clases

puedes intercambiar java.tiempo objetos directamente con su base de datos. Usar una controlador JDBC conforme con JDBC 4.2 o después. No hay necesidad de cuerdas, no hay necesidad de java.sql.* clases Compatibilidad con Hibernate 5 y JPA 2.2 java.tiempo.

¿Dónde obtener las clases java.time?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11y posteriores: parte de la API de Java estándar con una implementación integrada.
    • Java 9 trajo algunas características y correcciones menores.
  • Java SE 6 y Java SE 7
    • La mayoría de java.tiempo la funcionalidad está adaptada a Java 6 y 7 en ThreeTen-Backport.
  • Androide
    • Las versiones posteriores de Android (26+) incluyen implementaciones del java.tiempo clases
    • Para versiones anteriores de Android (API desazucarado para proporcionar un subconjunto de los java.tiempo funcionalidad no integrada originalmente en Android.
      • Si el desazucarado no te ofrece lo que necesitas, el TresDiezABP el proyecto se adapta ThreeTen-Backport (mencionado anteriormente) a Android. Ver Cómo usar ThreeTenABP….

Tabla de qué biblioteca java.time usar con qué versión de Java o Android

  • Apoyos para mencionar realmente la causa raíz y brindar cobertura de todas las alternativas disponibles.

    – mabi

    11 de abril de 2016 a las 13:52

  • Esta es la respuesta correcta y debe evitarse la clase Calendario. ThreeTen es la mejor opción

    – hormiga2009

    16 de noviembre de 2019 a las 14:21


  • @Basil Bourque Usted menciona versiones posteriores de implementaciones de paquetes de Android de clases java.time. ¿Puedes ser más específico sobre qué versiones? Estoy tratando de reemplazar el código antiguo de fecha y calendario para una aplicación de Android y no estoy seguro de por dónde empezar.

    – AJW

    22 de noviembre de 2021 a las 3:37


  • @AJW Esa información ya está presentada en la última sección de la Respuesta, “Acerca de java.time”, que actualicé hace un momento.

    – Basil Bourque

    22 de noviembre de 2021 a las 6:10


  • Muy bien, gracias por la actualización.

    – AJW

    22 de noviembre de 2021 a las 15:17

Avatar de usuario de Rubén
Rubén

Lo especifico Date constructor está en desuso, y Calendar debe usarse en su lugar. El JavaDoc para Fecha describe qué constructores están en desuso y cómo reemplazarlos usando un Calendar.

  • El calendario requiere un objeto adicional y como 8 líneas más de código para hacer lo mismo, que es crear un objeto Fecha por lo que puedo decir. Es confuso y parece innecesario cuando solo necesita una fecha y no una variable ajustada de zona horaria.

    – G_V

    6 de marzo de 2017 a las 8:37

  • FYI, las viejas clases de fecha y hora terriblemente problemáticas como java.util.Date, java.util.Calendary java.text.SimpleDateFormat son ahora legadosuplantado por el java.tiempo Clases integradas en Java 8 y versiones posteriores. Ver Tutorial por Oracle.

    – Basil Bourque

    28 de noviembre de 2018 a las 19:18

Avatar de usuario de Kevin Workman
Kevin trabajador

Encontré esta pregunta como un duplicado de una pregunta más nueva que preguntaba cuál era la forma no obsoleta de obtener un Date en un año, mes y día específicos.

Las respuestas aquí hasta ahora dicen usar el Calendar clase, y eso fue cierto hasta que salió Java 8. Pero a partir de Java 8, la forma estándar de hacer esto es:

LocalDate localDate = LocalDate.of(1985, 1, 1);

Y luego, si realmente necesitas un java.util.Datepuede utilizar las sugerencias de esta pregunta.

Para obtener más información, consulte la API o los tutoriales para Java 8.

Avatar de usuario de Stephen C
esteban c

Una de las razones por las que el constructor está en desuso es que el significado del parámetro del año no es el esperado. El javadoc dice:

A partir de la versión 1.1 de JDK, reemplazada por Calendar.set(year + 1900, month, date).

Observe que el campo del año es el número de años desde 1900, por lo que su código de muestra probablemente no hará lo que espera que haga. Y ese es el punto.

En general, el Date La API solo es compatible con el calendario occidental moderno, tiene componentes especificados idiosincráticamente y se comporta de manera inconsistente si establece campos.

El Calendar y GregorianCalendar Las API son mejores que Date, y las API de Joda-time de terceros generalmente se consideraban las mejores. En Java 8, introdujeron el java.time paquetes, y estos son ahora la alternativa recomendada.

  • Esta solución funciona muy bien, excepto que no usa tiempo cero para horas-minutos-segundos-milisegundos como lo hizo la nueva fecha (año, mes, día). Entonces necesitamos algo como: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(año + 1900, mes, fecha); Fecha representación de fecha = cal.getTime();

    – Joel Richard Koett

    3 mayo 2019 a las 23:02


avatar de usuario de nbrooks
nbrooks

Tenga en cuenta que Calendar.getTime() es no determinista en el sentido de que el hora del día parte por defecto a la hora actual.

Para reproducir, intente ejecutar el siguiente código un par de veces:

Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());

Salida, por ejemplo:

Sun Mar 07 10:46:21 CET 2010

Ejecutar exactamente el mismo código un par de minutos más tarde produce:

Sun Mar 07 10:57:51 CET 2010

Entonces, mientras set() obliga a los campos correspondientes a corregir los valores, filtra el tiempo del sistema para los otros campos. (Probado anteriormente con Sun jdk6 y jdk7)

  • Esta solución funciona muy bien, excepto que no usa tiempo cero para horas-minutos-segundos-milisegundos como lo hizo la nueva fecha (año, mes, día). Entonces necesitamos algo como: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(año + 1900, mes, fecha); Fecha representación de fecha = cal.getTime();

    – Joel Richard Koett

    3 mayo 2019 a las 23:02


Avatar de usuario de Rob W
robar w

Date en sí mismo no está en desuso. Es solo que muchos de sus métodos lo son. Ver aquí para más detalles.

Usar java.util.Calendar en cambio.

¿Ha sido útil esta solución?