JavaRush /Blog Java /Random-ES /Una biblioteca intuitiva y robusta para trabajar con hora...
theGrass
Nivel 24
Саратов

Una biblioteca intuitiva y robusta para trabajar con horas y fechas finalmente está disponible en Java (Parte 1).

Publicado en el grupo Random-ES
Java     finalmente tiene una forma intuitiva y confiable de trabajar con fechas y horas. Los principios de fecha y hora son fundamentales en muchas aplicaciones. Varias cosas, como fechas de nacimiento, fechas de alquiler, horarios de eventos y horarios de apertura de tiendas, se basan en fechas y horas, pero Java SE no proporcionó una forma conveniente de trabajar con ellos. A partir de Java SE 8 , hubo un conjunto de paquetes java.time , que proporcionan una API bien estructurada para trabajar con fechas y horas.
Fondo
    Cuando apareció Java por primera vez, en la versión 1.0 , la única clase para trabajar con fechas y horas era java.util.Date . Lo primero que notaron los desarrolladores fue que no representa una "fecha". De hecho, representa un momento en el tiempo, con una precisión de milisegundos, medido a partir de la fecha del 1 de enero de 1970. Sin embargo, basándose en el hecho de que el método toString() de Date muestra la fecha y la hora en la zona horaria especificada en la configuración de Java de la máquina , algunos desarrolladores concluyeron erróneamente que Date puede funcionar con zonas horarias. Arreglar esta clase resultó ser tan difícil (o tan lento) que en la versión 1.1 tuvimos que agregar una nueva clase: java.util.Calendar . Desafortunadamente, la clase Calendar resultó no ser mucho mejor que Date . A continuación se muestra una pequeña lista de problemas existentes en su implementación:
  • Cambiable. Clases como fecha y hora deben ser inmutables.
  • Compensaciones. Los años en fecha comienzan desde 1900, los meses en ambas clases comienzan desde cero.
  • Nombres. La fecha no es en realidad una "fecha" y el Calendario no es un calendario.
  • Formato. El formateo solo funciona con Fecha, no con Calendario, y no es seguro para subprocesos.
    En 2001 se creó el proyecto Joda-Time . Su objetivo era simple: crear una biblioteca de alta calidad para trabajar con fechas y horas en Java . Tomó algún tiempo, pero finalmente se lanzó la versión 1.0 y rápidamente se volvió muy popular y ampliamente utilizada. Con el tiempo, los desarrolladores exigieron cada vez más que se proporcionara una biblioteca de conveniencia similar como parte del JDK . Con la participación de Michael Nascimento Santos de Brasil, se lanzó el proyecto JSR-310 , que es el proceso oficial para crear e integrar una nueva API para trabajar con fechas y horas en el JDK .
Revisar
La nueva API java.time contiene 5 paquetes:
  • java.time: el paquete base que contiene objetos para almacenar valores
  • java.time.chrono: proporciona acceso a diferentes calendarios
  • java.time.format: formato y reconocimiento de fecha y hora
  • java.time.temporal: bibliotecas de bajo nivel y funcionalidad avanzada
  • java.time.zone - clases para trabajar con zonas horarias
    La mayoría de los desarrolladores utilizarán principalmente el paquete base y el formato, y quizás java.time.temporal . Así, aunque se han añadido 68 nuevos tipos, los desarrolladores sólo utilizarán alrededor de un tercio de ellos.
fechas
    La clase LocalDate es una de las más importantes de la nueva API . Contiene un valor inmutable que representa una fecha. No se puede configurar la hora ni la zona horaria. El nombre "local" puede que le resulte familiar por Joda-Time y originalmente proviene del estándar ISO-8601 . Significa precisamente la ausencia de una zona horaria. Básicamente, LocalDate es una descripción de una fecha, como "5 de abril de 2014". La hora real de esta fecha variará según su zona horaria. Por ejemplo, en Australia esta fecha será 10 horas antes que en Londres y 18 horas antes que en San Francisco. La clase LocalDate tiene todos los métodos comúnmente necesarios: LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     en nuestro ejemplo, vemos una fecha creada usando un método de fábrica (todos los constructores son privados). A continuación le pedimos al objeto algunos datos. Tenga en cuenta que las enumeraciones Month y DayOfWeek están diseñadas para hacer que el código sea más legible y confiable. En el siguiente ejemplo veremos cómo modificar la fecha. Como la clase es inmutable, el resultado serán nuevos objetos, pero el original permanecerá como estaba. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     Estos son cambios relativamente simples, pero a menudo es necesario realizar modificaciones de fecha más complejas. Hay un mecanismo especial para esto en la API java.time: TemporalAdjuster . Su propósito es proporcionar una herramienta integrada que le permita manipular fechas, por ejemplo obteniendo un objeto correspondiente al último día del mes. Algunos de ellos están incluidos en la API , pero puedes agregar los tuyos propios. Usar modificadores es muy fácil, pero requiere importaciones estáticas: import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     el uso de modificadores simplifica enormemente su código. Nadie quiere ver mucha manipulación manual de fechas. Si se produce algún tipo de manipulación de fechas varias veces en su proyecto, escriba su propio modificador y su equipo podrá usarlo como un componente ya escrito y probado.
Hora y fecha como valores.
    Vale la pena dedicar un poco de tiempo a comprender qué hace que LocalDate sea un valor. Los valores son tipos de datos simples que son completamente intercambiables; cuando son iguales, la identidad de los objetos deja de tener sentido. Un ejemplo clásico de una clase de valor es String . Comparamos cadenas usando equals() y no nos importa si los objetos son idénticos en comparación con el operador == . La mayoría de las clases para trabajar con fechas y horas también son valores. Entonces, compararlos usando el operador == es una mala idea, como se indica en la documentación. Para aquellos interesados ​​en aprender más, consulte mi definición reciente de VALJO , que describe un conjunto estricto de reglas que deben seguir los objetos de valor en Java , incluida la inmutabilidad, los métodos de fábrica y la definición adecuada de equals() , hashCode , toString() , y comparar con .() .
Calendarios alternativos
    La clase LocalDate , como todas las clases principales de java.time , está vinculada a un único calendario, como se describe en el estándar ISO-8601 . La norma 8601 describe el calendario estándar mundial, también conocido como calendario gregoriano. Un año estándar incluye 365 días, un año bisiesto, 366. Cada cuarto año es bisiesto a menos que sea divisible por 100 o divisible por 400. El año anterior al primer año de una nueva era se considera cero para facilitar el cálculo. La primera consecuencia de que este sea el sistema predeterminado es que los resultados no siempre coinciden con los calculados usando GregorianCalendar . La clase GregorianCalendar tiene un cambio incorporado al sistema juliano para todas las fechas anteriores al 15 de octubre de 1582. En el sistema juliano, cada cuatro años era bisiesto, sin excepción. La pregunta es, dado que la transición de un sistema a otro es un hecho histórico, ¿por qué java.time no la modela? Sí, porque diferentes países cambiaron al sistema gregoriano en diferentes momentos, y considerando solo la fecha de la transición del Vaticano obtendremos datos incorrectos para la mayoría de los demás países. Por ejemplo, el Imperio Británico, incluidas las colonias de América del Norte, cambió al calendario gregoriano el 14 de septiembre de 1752, casi 200 años después. Rusia no cambió su calendario hasta el 14 de febrero de 1918, y la transición de Suecia es en general un asunto turbio. Como resultado, el significado real de las fechas anteriores a 1918 varía mucho según las circunstancias. Los autores del código LocalDate tomaron una decisión completamente racional de no modelar en absoluto la transición del calendario juliano al calendario gregoriano para evitar discrepancias. La segunda consecuencia de utilizar ISO-8601 como calendario predeterminado en todas las clases principales es que se requiere un conjunto adicional de clases para manejar los calendarios restantes. La interfaz Cronología es la base para trabajar con calendarios alternativos, permitiéndole encontrar el calendario deseado por nombre local. Java 8 viene con 4 calendarios adicionales: budista tailandés, mingguo (taiwanés), japonés e islámico. Otros calendarios pueden venir con programas. Cada calendario tiene una clase de fecha especial como ThaiBuddhistDate , MinguoDate , JapaneseDate y HijrahDate . Tiene sentido utilizarlos en aplicaciones muy localizadas, como las del gobierno japonés. Se utiliza una interfaz adicional, ChronoLocalDate , como abstracción central de las cuatro clases anteriores junto con LocalDate., que le permite escribir código independientemente del tipo de calendario utilizado. Aunque esta abstracción existe, no se recomienda su uso. Comprender por qué no se recomienda esta abstracción es importante para comprender cómo funciona toda la API java.time . La conclusión es que la mayor parte del código que se escribe sin referencia a un calendario específico resulta no funcionar. Por ejemplo, no puedes estar seguro de que un año tenga 12 meses, pero algunos desarrolladores añaden 12 meses y piensan que han añadido un año completo. No se puede estar seguro de que todos los meses contengan aproximadamente el mismo número de días: en el calendario copto hay 12 meses de 30 días y 1 mes de cinco o seis días. Además, no puedes estar seguro de que el número del próximo año será 1 más que el actual, porque en el calendario japonés los años se cuentan a partir de la proclamación del próximo emperador (en este caso, incluso 2 días del mismo mes). pueden pertenecer a diferentes años). La única forma de escribir código funcional y de alta calidad que funcione con varios calendarios a la vez es que el núcleo de su código, que realiza todas las operaciones en fechas y horas, debe escribirse usando un calendario estándar, y solo al ingresar/imprimir fechas. en caso de que se convierta a otros sistemas de calendario. Es decir, se recomienda utilizar LocalDate para el almacenamiento y todas las manipulaciones de fechas en su aplicación. Y sólo al localizar fechas de entrada y salida se debe utilizar ChronoLocalDate , que normalmente se obtiene de la clase de calendario almacenada en el perfil del usuario. Es cierto que la mayoría de las aplicaciones no necesitan una localización tan seria. Si necesitas una explicación más detallada de todo lo descrito en este capítulo, bienvenido a la documentación de la clase ChronoLocalDate .      Continuación del artículo      Artículo original
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION