Java: ¿Por qué está obsoleto el constructor Date y qué uso en su lugar?


Vengo del mundo de C#, así que aún no tengo mucha experiencia con Java. Eclipse acaba de decir que el 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) se debe usar en su lugar?

Author: Raedwald, 2011-04-15

11 answers

El constructor de Fecha específico está obsoleto, y se debe usar un Calendario en su lugar. El JavaDoc para Date describe qué constructores están obsoletos y cómo reemplazarlos usando un Calendario.

 88
Author: Ruben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-15 13:27:38

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

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();

Echa un vistazo a la fecha Javadoc:

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

 208
Author: BuffaloBuffalo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-15 12:41:53

Tl;dr

LocalDate.of( 1985 , 1 , 1 )

Or o {

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

Detalles

El java.util.Date, java.util.Calendar, y java.text.SimpleDateFormat las clases se apresuraron demasiado rápido 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 desaprobaciones que has encontrado. Lamentablemente, los intentos de mejora fracasaron en gran medida. Deberías evitar estas clases por completo. Son suplantados en Java 8 por nuevas clases.

Problemas En Su Código

Un java.útil.La fecha tiene tanto una fecha como una porción de tiempo. Ignoraste la parte de tiempo en tu código. Por lo tanto, la clase Date tomará el comienzo del día según lo definido por la zona horaria predeterminada de su JVM y aplicará esa hora al objeto Date. Por lo tanto, los resultados de su código variarán dependiendo de la máquina que ejecute o de la zona horaria establecida. Probablemente no es lo que quieres.

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

Joda-Tiempo

Lo primero que hay que aprender en Java: Evite el java notoriamente problemático.útil.Date & java.útil.Calendar classes incluido con Java.

Como se indica correctamente en la respuesta de user3277382, use Joda-Time o el nuevo java.tiempo.* paquete 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.time

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

Tenemos una zona horaria(ZoneId), y construir un objeto fecha-hora asignado a esa zona horaria(ZonedDateTime). Luego, usando el patrón Objetos Inmutables, creamos una nueva fecha-hora basada en el antiguo el mismo instante del objeto (cuenta de nanosegundos desde epoch) pero asignado a otra zona horaria. Por último tenemos 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.time

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

El Joda-Tiempo project, ahora en modo de mantenimiento , aconseja la migración a java .time clases.

Para obtener más información, consulte el Oracle Tutorial. Y desbordamiento de pila de búsqueda para muchos ejemplos y explicaciones. La especificación es JSR 310.

Usted puede intercambiar java.time objetos directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de clases java.sql.*.

Dónde obtener el java.clases de tiempo?

  • Java SE 8, Java SE 9, Java SE 10, y más tarde
    • Incorporado.
    • Parte de la API estándar de Java con un paquete aplicación.
    • Java 9 añade algunas características menores y correcciones.
  • Java SE 6 y Java SE 7
    • Gran parte de java.la funcionalidad de tiempo se vuelve a portar a Java 6 y 7 en ThreeTen-Backport.
  • Android
    • Versiones posteriores de implementaciones de Android bundle de java.clases de tiempo.
    • Para anteriores Android (ThreeTenABP project adapts ThreeTen-Backport (mencionado anteriormente). Véase Cómo usar ThreeTenABP....

El ThreeTen-Extra el proyecto extiende java.tiempo con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a Java.tiempo. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más.

 55
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-28 06:27:21

Me encontré con 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 la clase Calendar, y eso era 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.Date, puedes usar las sugerencias en esta pregunta.

Para más información, echa un vistazo a el API o los tutoriales para Java 8.

 10
Author: Kevin Workman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 16:25:07

Una razón por la que el constructor está obsoleto es que el significado del parámetro year no es lo que esperarías. El javadoc dice:

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

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

En general, la API Date solo soporta el calendario occidental moderno, ha especificado idiosincráticamente componentes, y se comporta de manera inconsistente si establece campos.

Las API Calendar y GregorianCalendar son mejores que Date, y las API de tiempo Joda de 3rd party generalmente se pensaban que eran las mejores. En Java 8, introdujeron los paquetes java.time, y estos son ahora la alternativa recomendada.

 8
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-01 22:41:52

Tenga en cuenta que Calendar.getTime() no es determinista en el sentido de que la parte day time por defecto es 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 eg.:

Sun Mar 07 10:46:21 CET 2010

Ejecutar exactamente el mismo código un par de minutos después produce:

Sun Mar 07 10:57:51 CET 2010

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

 7
Author: Tijn Porcelijn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-14 21:02:01

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

Uso java.util.Calendar en su lugar.

 6
Author: Mike Thomsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 10:40:15

La mayoría de los desarrolladores de Java utilizan actualmente el paquete de terceros Joda-Time. En general se considera que es una aplicación mucho mejor.

Java 8 sin embargo tendrá un nuevo java.tiempo.* paquete . Vea este artículo, Presentando la Nueva API de Fecha y Hora para JDK 8.

 4
Author: davesbrain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 08:45:36

Similar a lo que binnyb sugirió, podría considerar el uso del nuevo método Calendar > GregorianCalendar. Vea estos documentos más recientes:

Http://download.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html

 1
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-15 13:30:13

Puedes hacer un método como new Date(year,month,date) en tu código usando la clase Calendar.

private Date getDate(int year,int month,int date){
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month-1);
    cal.set(Calendar.DAY_OF_MONTH, day);
    return cal.getTime();
}

Funcionará igual que el constructor obsoleto de Date

 0
Author: Sudhanshu Dubey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-11 07:36:24
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(la forma pre-Java-8)

 0
Author: Curtis Yallop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-05 20:12:36