tl; dr
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
Aunque no tenía sentido en ese código anterior. Ambos java.util.Date
y Instant
representan un momento en UTC, siempre en UTC. El código anterior tiene el mismo efecto que:
new java.util.Date() // Capture current moment in UTC.
No hay beneficio aquí para usar ZonedDateTime
. Si ya tiene un ZonedDateTime
, ajuste a UTC extrayendo un Instant
.
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
Otra respuesta correcta
La respuesta de ssoltanid aborda correctamente su pregunta específica, cómo convertir un objeto java.time ( ZonedDateTime
) de la nueva escuela en un objeto de la vieja escuela java.util.Date
. Extraiga el Instant
de ZonedDateTime y pase a java.util.Date.from()
.
Pérdida de datos
Tenga en cuenta que sufrirá pérdida de datos , ya que Instant
rastrea nanosegundos desde época mientras que java.util.Date
rastrea milisegundos desde época.
Su pregunta y comentarios plantean otros problemas.
Mantener los servidores en UTC
Sus servidores deben tener su sistema operativo host configurado en UTC como una mejor práctica en general. La JVM toma esta configuración del sistema operativo host como su zona horaria predeterminada, en las implementaciones de Java que conozco.
Especificar zona horaria
Pero nunca debe confiar en la zona horaria predeterminada actual de la JVM. En lugar de elegir la configuración del host, una bandera que se pasa al iniciar una JVM puede establecer otra zona horaria. Peor aún: ¡Cualquier código en cualquier hilo de cualquier aplicación en cualquier momento puede hacer una llamada a java.util.TimeZone::setDefault
para cambiar ese valor predeterminado en tiempo de ejecución!
Timestamp
Tipo Cassandra
Cualquier base de datos y controlador decente debería manejar automáticamente el ajuste de una fecha y hora pasada a UTC para el almacenamiento. No uso Cassandra, pero parece tener un soporte rudimentario para la fecha y la hora. La documentación dice que su Timestamp
tipo es un recuento de milisegundos de la misma época (primer momento de 1970 en UTC).
ISO 8601
Además, Cassandra acepta entradas de cadenas en los formatos estándar ISO 8601 . Afortunadamente, java.time usa formatos ISO 8601 como valores predeterminados para analizar / generar cadenas. La implementación de la Instant
clase funcionará toString
bien.
Precisión: milisegundos vs nanosegundos
Pero primero debemos reducir la precisión de nanosegundos de ZonedDateTime a milisegundos. Una forma es crear un Instant fresco usando milisegundos. Afortunadamente, java.time tiene algunos métodos útiles para convertir desde y hacia milisegundos.
Código de ejemplo
Aquí hay un código de ejemplo en Java 8 Update 60.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
Instant instant = zdt.toInstant();
Instant instantTruncatedToMilliseconds = Instant.ofEpochMilli( instant.toEpochMilli() );
String fodderForCassandra = instantTruncatedToMilliseconds.toString(); // Example: 2015-08-18T06:36:40.321Z
O de acuerdo con este documento del controlador de Cassandra Java , puede pasar una java.util.Date
instancia (que no debe confundirse con java.sqlDate
). Entonces podrías hacer un juDate a partir de eso instantTruncatedToMilliseconds
en el código anterior.
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
Si haces esto con frecuencia, podrías hacer una sola línea.
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
Pero sería mejor crear un pequeño método de utilidad.
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
Note la diferencia en todo este código que en la Pregunta. El código de la pregunta intentaba ajustar la zona horaria de la instancia de ZonedDateTime a UTC. Pero eso no es necesario. Conceptualmente:
ZonedDateTime = Instantáneo + ZoneId
Simplemente extraemos la parte Instant, que ya está en UTC (básicamente en UTC, lea el documento de la clase para obtener detalles precisos).
Acerca de java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date
, Calendar
, y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Para obtener más información, consulte el tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No se necesitan cuerdas, no se necesitan java.sql.*
clases.
¿Dónde obtener las clases java.time?
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval
, YearWeek
, YearQuarter
, y más .
java.util.Date
yjava.sql.Date
.