2010-01-30 6 views

Respuesta

12

Joda es el camino a seguir. Por qué ?

  1. cuenta con una interfaz mucho más potente e intuitiva que la norma Fecha/Hora API
  2. que no hay problemas de roscado con el formato de fecha/hora. java.text.SimpleDateFormat no es seguro para subprocesos (no mucha gente sabe esto!)

En algún momento el/Hora Fecha API de Java va a ser sustituida (por JSR-310). Creo que esto se basará en el trabajo realizado por los que están detrás de Joda, y como tal, aprenderá una API que influirá en una nueva API estándar de Java.

+0

Ahora, si no puede usar Joda (algunos proyectos están limitados en los archivos JAR externos que pueden introducir en el proyecto), está usando java.util.GregorianCalendar para contener y manipular fechas (asegurándose de que cuenta para DST haciendo algo así como mantener sus fechas en la zona horaria UTC) la mejor práctica? – BestPractices

+0

Para su información, el proyecto [Joda-Time] (http://www.joda.org/joda-time/) se encuentra ahora en modo de mantenimiento, y el equipo recomienda la migración a [java.time] (http: // docs .oracle.com/javase/8/docs/api/java/time/package-summary.html) clases. –

+0

¿De verdad? No sabía eso. Thx para el encabezado –

-2

Para obtener la discusión comenzó, aquí ha sido mi experiencia:

Al crear estándares para un proyecto típico de 3 niveles Enterprise Java, me recomiendan que el proyecto utilice GregorianCalendar para la manipulación de fechas. La razón es que GregorianCalendar es el estándar de facto sobre cualquier otra instancia de Calendar, p. Calendario juliano, etc. Es el calendario reconocido en la mayoría de los países y maneja los años bisiestos, etc. Además de eso, recomendaría que la aplicación almacene sus fechas como UTC para que pueda realizar fácilmente cálculos de fecha como encontrar la diferencia entre dos. fechas (si se almacenara como EST, por ejemplo, tendría que tener en cuenta el ahorro de luz diurna). La fecha puede ser luego localizada en la zona horaria que necesite para que se muestre al usuario como, por ejemplo, localizarlo en EST si es una empresa de la costa este de los EE. UU. Y desea que su información horaria se muestre en EST.

+3

"por ejemplo, calendario juliano, etc." Puede dejar esto, ya que no tiene ningún sentido. Hay muchos casos de esquina para comenzar a enumerar cosas aquí. Por ejemplo, los astrónomos usan un número de día astronómico juliano. También usan fechas gregorianas. Es mejor decir menos sobre este punto. Además, ayuda usar balas para cada uno de sus puntos. –

+1

¿Por qué un proyecto de 3 niveles sería diferente de cualquier otro proyecto? – jontejj

+0

FYI, las antiguas clases de fecha y hora como ['java.util.Date'] (https://docs.oracle.com/javase/8/docs/api/java/util/Date.html), [' java.util.Calendar'] (https://docs.oracle.com/javase/8/docs/api/java/util/Date.html) y 'java.text.SimpleTextFormat' ahora son [legacy] (https : //en.wikipedia.org/wiki/Legacy_system), suplantado por [java.time] (https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) clases. –

10

Joda time (100% interoperable con el JDK)

Joda-Time proporciona un reemplazo de calidad para la fecha y hora de clases Java. El diseño permite múltiples sistemas de calendario, al tiempo que proporciona una API simple

+0

Para su información, el proyecto [Joda-Time] (http://www.joda.org/joda-time/) se encuentra ahora en modo de mantenimiento, y el equipo recomienda la migración a [java.time] (http: // docs .oracle.com/javase/8/docs/api/java/time/package-summary.html) clases. –

25

La mejor práctica suele ser precisamente NOT pensar en términos de objetos de fecha pesada pero para almacenar un punto en el tiempo. Esto normalmente se hace almacenando un valor que no sufre de casos de esquina ni de posibles problemas de análisis. Para hacer esto, las personas generalmente almacenan la cantidad de milisegundos (o segundos) transcurridos desde un punto fijo que llamamos época (1970-01-01). Esto es muy común y cualquier API de Java siempre le permitirá convertir cualquier tipo de fecha a/desde el tiempo expresado en ms desde la época.

Eso es para el almacenamiento. También puede almacenar, por ejemplo, la zona horaria preferida del usuario, si existe tal necesidad.

Ahora tal fecha en milisegundos, como:

System.out.println(System.currentTimeMillis()); 
1264875453 

no es muy útil cuando se muestra al usuario final, eso es por sentado.

Es por eso que utiliza, por ejemplo, el ejemplo Joda time para convertirlo a un formato fácil de usar antes de mostrarlo al usuario final.

Ha solicitado la mejor práctica, aquí está mi opinión: almacenar objetos de "fecha" en un DB en lugar del tiempo en milisegundos está ahí con números en coma flotante para representar montos monetarios.

Suele ser un gran olor a código.

Entonces Joda time en Java es la forma de manipular la fecha, sí. Pero es Joda el camino para ir a store fechas? CIERTAMENTE NO.

2

UTC

pensar, trabajar y almacenar datos en UTC en lugar de cualquier zona horaria. Piense en UTC como One True Time, y todas las demás zonas horarias son meras variaciones. Por lo tanto, al codificar, olvídate de tu propia zona horaria. Haga su lógica de negocio, registro, almacenamiento de datos e intercambio de datos en UTC. Sugiero que cada programador mantenga un segundo reloj en su escritorio configurado en UTC.

java.time

La forma moderna es java.time las clases.

El mencionado proyecto Joda-Time proporcionó la inspiración para las clases java.time, y el proyecto ahora está en modo de mantenimiento con el equipo que recomienda la migración a clases java.time.

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las viejas y problemáticas clases de fecha y hora legacy, como java.util.Date, .Calendar, & java.text.SimpleDateFormat.

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

¿Dónde obtener las clases java.time?

  • Java SE 8 y SE 9 y más tarde
    • incorporado.
    • Parte de la API estándar de Java con una implementación integrada.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y SE 7
    • Gran parte de la funcionalidad de back-java.time está portado a Java 6 & 7 en ThreeTen-Backport.
  • Android
    • El proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) para Android específicamente.
    • Ver How to use….

El proyecto se extiende ThreeTen-Extra java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter y more.

ISO 8601

Cuando seria un valor de fecha y hora al texto, utilizar el estándar ISO 8601.

Por ejemplo, una fecha y hora en UTC es 2016-10-17T01:24:35Z donde Z es la abreviatura de Zulu y significa UTC. Para otros offset-from-UTC, al final aparece el desplazamiento de horas y minutos, como 2016-01-23T12:34:56+05:30. Las clases java.time extienden este formato estándar para agregar el nombre de la zona horaria (si se conoce) entre corchetes, como 2016-01-23T12:34:56+05:30[Asia/Kolkata].

La norma tiene muchos otros formatos prácticos así incluso para durations, intervals, ordinals y year-week.

Base de datos

Para el almacenamiento de base de datos, el uso de tipos de fecha y hora para los valores de fecha y hora, como el SQL standard data types que son principalmente DATE, TIME, y TIMESTAMP WITH TIME ZONE.

Deje que su JDBC driver haga el trabajo pesado. El controlador maneja los detalles esenciales sobre la mediación y la adaptación entre las partes internas de cómo maneja Java los datos y cómo maneja la base de datos los datos de su lado. Pero asegúrese de practicar con datos de ejemplo para conocer los comportamientos de su controlador y su base de datos. El estándar SQL define muy poco sobre el manejo de la fecha y hora, por lo que los comportamientos varían ampliamente, sorprendentemente.

Si utiliza un controlador JDBC que cumpla con JDBC 4.2 y posterior, puede buscar y almacenar los tipos de java.time directamente a través de los métodos ResultSet::getObject y PreparedStatement::setObject.

Instant instant = myResultSet.getObject(…); 
myPreparedStatement.setObject(… , instant); 

Para los controladores más antiguos, tendrá que recurrir a la conversión a través de los tipos java.sql. Busque nuevos métodos de conversión agregados a las clases antiguas. Por ejemplo, java.sql.Timestamp.toInstant().

Instant instant = myResultSet.getTimestamp(…).toInstant(); 
myPreparedStatement.setObject(… , java.sql.Timestamp.from(instant)); 

Utilice los tipos java.sql lo más brevemente posible. Son un truco mal diseñado, como java.sql.Date enmascarado como un valor de fecha solamente, pero en realidad como una subclase de java.util.Date, de hecho tiene una hora establecida en el 00:00:00 en UTC. Y, oh, se supone que debes ignorar el hecho de que esa herencia dice el doc de la clase. Un desastre feo.

código Ejemplo

Consigue el momento actual en GMT.

Instant instant = Instant.now(); 

Almacenamiento y ir a buscar que Instant objeto a/desde una base de datos se muestra arriba.

Para generar una cadena ISO 8601, simplemente llame al toString. El javatodas las clases de tiempo usan formatos ISO 8601 por defecto para analizar y generar cadenas de sus diversos valores de fecha y hora.

String output = instant.toString(); 

Ajuste en cualquier desplazamiento-de-UTC aplicando una ZoneOffset para obtener una OffsetDateTime. Llame al toString para generar un String en formato ISO 8601.

ZoneOffset offset = ZoneOffset.ofHoursMinutes(5 , 30); 
OffsetDateTime odt = instant.atOffset(offset); 

Una zona horaria es un desplazamiento más un conjunto de reglas para el manejo de anomalías tales como Daylight Saving Time (DST). Cuando necesite ver ese mismo momento a través del objetivo de alguna región propia wall-clock time, aplique una zona horaria (ZoneId) para obtener un objeto ZonedDateTime.

Especifique un proper time zone name en el formato de continent/region. Nunca use la abreviatura de 3-4 letras, como EST o IST, ya que no son zonas horarias verdaderas, no están estandarizadas y ni siquiera son únicas (!).

ZoneId z = ZoneId.of("Asia/Kolkata"); 
ZonedDateTime zdt = instant.atZone(z); 

En la otra dirección, se puede extraer un Instant de un OffsetDateTime o ZonedDateTime llamando toInstant.

Instant instant = zdt.toInstant(); 

Formateo

Para su presentación al usuario como cadenas en formatos que no sean ISO 8601, search Stack Overflow para el uso de la clase DateTimeFormatter.

Si bien puede especificar un formato personalizado, generalmente es mejor dejar que java.time se localice automáticamente. Para localizar, especifique:

  • FormatStyle para determinar cuánto tiempo o abreviar debe ser la cadena.
  • Locale para determinar (a) el idioma humano para la traducción del nombre del día, nombre del mes y demás, y (b) las normas culturales que deciden los problemas de abreviatura, mayúsculas, puntuación, etc.

Ejemplo:

Locale l = Locale.CANADA_FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(l); 
String output = zdt.format(f); 

Conversión

mejor para evitar los tipos de fecha y hora de legado siempre que sea posible. Pero si trabaja con un código antiguo que aún no se ha actualizado para los tipos java.time, puede convertir a/desde los tipos java.time. Para más detalles, vea la pregunta, Convert java.util.Date to what “java.time” type?.

utilizar objetos

utilizar objetos en lugar de simples primitivas codificados y cadenas simples. Por ejemplo:

  • No utilice 1-7 para representar un día de la semana, utilice el DayOfWeek enumeración como DayOfWeek.TUESDAY.
  • En lugar de pasar una cuerda como una fecha, pase alrededor de LocalDate objetos.
  • En lugar de pasar un par de enteros por un año y un mes, pase alrededor de YearMonth objetos.
  • En lugar de 1-12 por un mes, use la enumeración Month mucho más legible, como Month.JANUARY.

El uso de tales objetos hace que su código sea más autodocumentado, garantiza valores válidos y proporciona type-safety.

Cuestiones relacionadas