¿Qué pasa con la API de fecha y hora de Java? [cerrado]

105

Muy a menudo me encuentro con comentarios negativos sobre Java Datey otras clases relacionadas con la fecha y la hora. Siendo un desarrollador de .NET, no puedo entender completamente (sin haberlos usado), lo que realmente está mal con ellos.

¿Alguien puede arrojar algo de luz sobre esto?

Anton Gogolev
fuente

Respuestas:

142

Ah, la Dateclase de Java . Quizás uno de los mejores ejemplos de cómo no hacer algo en cualquier idioma, en cualquier lugar. ¿Dónde empiezo?

La lectura de JavaDoc puede llevar a uno a pensar que los desarrolladores en realidad tienen buenas ideas. Continúa sobre la diferencia entre UTC y GMT extensamente, a pesar de que la diferencia entre los dos es básicamente segundos intercalares (lo que ocurre muy raramente ).

Sin embargo, las decisiones de diseño realmente desperdician cualquier pensamiento de ser una API bien diseñada. Éstos son algunos de los errores favoritos:

  • A pesar de haber sido diseñado en la última década del milenio, califica los años con dos dígitos desde 1900. Hay literalmente millones de soluciones alternativas para 1900+ (o 1900-) en el mundo de Java como resultado de esta decisión banal.
  • Los meses están indexados a cero, para atender el caso espectacularmente inusual de tener una matriz de meses y no vivir con una matriz de trece elementos, el primero de los cuales contiene un null. Como resultado, tenemos 0..11 (y hoy es el mes 11 del año 109). Hay un número similar de ++ y - en los meses para convertir a una cadena.
  • Son mutables . Como resultado, cada vez que desee devolver una fecha (digamos, como una estructura de instancia), debe devolver un clon de esa fecha en lugar del objeto de fecha en sí (ya que de lo contrario, las personas pueden mutar su estructura).
  • El Calendar, diseñado para 'arreglar' esto, en realidad comete los mismos errores. Todavía son mutables.
  • Daterepresenta a DateTime, pero para diferir a los de SQL land, hay otra subclase java.sql.Date, que representa un solo día (aunque sin una zona horaria asociada).
  • No hay TimeZones asociados con a Date, por lo que los rangos (como un 'día completo') a menudo se representan como una medianoche a medianoche (a menudo en una zona horaria arbitraria)

Finalmente, vale la pena señalar que los segundos intercalares generalmente se corrigen a sí mismos contra un buen reloj del sistema que se actualiza con ntp en una hora (vea los enlaces a continuación). La posibilidad de que un sistema esté todavía en funcionamiento en la introducción de dos segundos intercalares (cada seis meses como mínimo, prácticamente cada pocos años) es bastante improbable, especialmente si se considera el hecho de que debe volver a implementar nuevas versiones de su código de vez en cuando. . Incluso el uso de un lenguaje dinámico que regenera clases o algo así como un motor WAR contaminará el espacio de clases y eventualmente se quedará sin permgen.

AlBlue
fuente
43

JSR 310 , que reemplazó a las antiguas clases de fecha y hora con java.time en Java 8, se justifica en el JSR original de la siguiente manera:

2.5 ¿Qué necesidad de la comunidad Java se abordará con la especificación propuesta?

Actualmente, Java SE tiene dos API de fecha y hora independientes: java.util.Date y java.util.Calendar. Los desarrolladores de Java describen constantemente ambas API como difíciles de usar en blogs y foros. En particular, ambos usan un índice cero durante meses, lo que es la causa de muchos errores. Calendar también ha sufrido muchos errores y problemas de rendimiento a lo largo de los años, principalmente debido a que almacena su estado de dos formas diferentes internamente.

Un error clásico (4639407) impidió que se crearan determinadas fechas en un objeto Calendario. Se podría escribir una secuencia de código que podría crear una fecha en algunos años pero no en otros, teniendo el efecto de evitar que algunos usuarios ingresen sus fechas de nacimiento correctas. Esto se debió a que la clase Calendario solo permitía una ganancia de horario de verano de una hora en verano, cuando históricamente era más 2 horas en la época de la Segunda Guerra Mundial. Si bien este error ahora está solucionado, si en algún momento en el futuro un país opta por introducir una ganancia de horario de verano de más tres horas en verano, la clase de Calendario volvería a romperse.

La API de Java SE actual también sufre en entornos de subprocesos múltiples. Se sabe que las clases inmutables son inherentemente seguras para subprocesos, ya que su estado no puede cambiar. Sin embargo, tanto la fecha como el calendario son mutables, lo que requiere que los programadores consideren la clonación y el subproceso explícitamente. Además, la falta de seguridad de subprocesos en DateTimeFormat no es ampliamente conocida y ha sido la causa de muchos problemas de subprocesos difíciles de rastrear.

Además de los problemas con las clases que tiene Java SE para datetime, no tiene clases para modelar otros conceptos. Las fechas u horas sin zona horaria, las duraciones, los períodos y los intervalos no tienen representación de clase en Java SE. Como resultado, los desarrolladores utilizan con frecuencia un int para representar una duración de tiempo, con javadoc especificando la unidad.

La falta de un modelo completo de fecha y hora también hace que muchas operaciones comunes sean más complicadas de lo que deberían ser. Por ejemplo, calcular el número de días entre dos fechas es un problema particularmente difícil en la actualidad.

Este JSR abordará el problema de un modelo completo de fecha y hora, incluidas fechas y horas (con y sin zonas horarias), duraciones y períodos de tiempo, intervalos, formato y análisis.

meriton
fuente
28
  • Las instancias de fecha son mutables , lo que casi siempre es un inconveniente.
  • Tienen una doble naturaleza. Representan tanto una marca de tiempo como una fecha de calendario. Resulta que esto es problemático al hacer cálculos sobre fechas.
  • Las representaciones numéricas de los datos del calendario son contraintuitivas en muchos casos. Por ejemplo: getMonth()está basado en cero, getYear()está basado en 1900 (es decir, el año 2009 se representa como 109).
  • Les faltan muchas de las funciones que esperas de una Dateclase.
ala de cera
fuente
13

Lo siento por usted ... como ex programador de .NET, hice las mismas preguntas, la API de tiempo en .NET (intervalos de tiempo, sobrecarga del operador) es muy conveniente.

Primero, para crear una fecha específica, usa una API obsoleta o:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

Para restar un día haces cosas malas como

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

o peor

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

Para saber cuánto tiempo pasó entre dos fechas (en días / semanas / meses) ... se pone aún peor

Sin embargo, DateUtils de apache ( org.apache.commons.lang.time.DateUtils) ofrece algunos métodos convenientes y me encontré usándolos solo últimamente

Como escribió Brabster, Joda Time también es una buena biblioteca externa, pero apache parece más "común" que cualquier otra cosa ...

Eran Medan
fuente
Por favor, muéstrenos cómo hacerlo ("averigüe cuánto tiempo pasó entre dos fechas").
Anton Gogolev
Ojalá supiera una manera fácil ... incluidos los años bisiestos, los meses nerviosos y los días volátiles ...
Eran Medan
1
Véase también, org.apache.commons.lang.time: commons.apache.org/lang//api/org/apache/commons/lang/time/…
trashgod
@AntonGogolev En java.time , use Periody Durationclasses para calcular y representar el tiempo transcurrido en una escala de años-meses-días y horas-minutos-segundos respectivamente.
Basil Bourque
4

Para ser honesto, encuentro la API de fecha de Java utilizable. La mayor parte de los problemas que he visto y oído acerca relacionan con el nivel de detalle, la necesidad de involucrar a múltiples clases a hacer nada útil ( Calendar, Date, DateFormat/ SimpleDateFormat) y la falta de métodos de acceso simples como getDayOfWeek().

Joda Time es una API alternativa muy respetada en Java, y en la sección Por qué Joda Time ofrece algunos argumentos más sobre por qué es una alternativa viable que podría ser de interés.

brabster
fuente