Convierta LocalDate a LocalDateTime o java.sql.Timestamp

126

Estoy usando JodaTime 1.6.2.

tengo un LocalDate que necesito convertir a un (Joda) LocalDateTimeo un java.sqlTimestamppara ormapping.

La razón de esto es que he descubierto cómo convertir entre a LocalDateTimey ajava.sql.Timestamp :

LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));

Entonces, si solo puedo convertir entre LocalDatey LocalDateTime, entonces puedo hacer la conversión continua a java.sql.Timestamp. ¡Gracias por cualquier empujón en la dirección correcta!

IAmYourFaja
fuente
Para su información, el proyecto Joda-Time ahora está en modo de mantenimiento , y el equipo aconseja migrar a las clases java.time . Ver Tutorial de Oracle . Además, la java.sql.Timestampclase ahora es heredada, suplantada por las clases java.time , específicamente por Instant.
Basil Bourque

Respuestas:

269

JodaTime

Para convertir JodaTime's org.joda.time.LocalDatea java.sql.Timestamp, solo haz

Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());

Para convertir JodaTime's org.joda.time.LocalDateTimea java.sql.Timestamp, solo haz

Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());

JavaTime

Para convertir Java8 java.time.LocalDatea java.sql.Timestamp, solo haz

Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());

Para convertir Java8 java.time.LocalDateTimea java.sql.Timestamp, solo haz

Timestamp timestamp = Timestamp.valueOf(localDateTime);
BalusC
fuente
Tenga cuidado al convertir LocalDateTimea, DateTimeya que no todos los LocalDateTimes son válidos DateTime. Fuente: joda-time.sourceforge.net/faq.html#illegalinstant y solo me encuentro con esto.
Christophe De Troyer
Se produjo un error de compilación en el argumento ya que valueOf () acepta una cadena.
Patriótico
@Patriotic: Eso solo sucederá si en realidad no está utilizando Java SE 1.8 o posterior. Como se indica en la respuesta y en los enlaces proporcionados al Javadoc (los textos azules en la respuesta anterior son en realidad enlaces, puede hacer clic en ellos para profundizar en el Javadoc), el Timestamp#valueOf()método acepta ya que Java SE 1.8 también a LocalDateTime.
BalusC
60

La mejor manera de usar la API de tiempo de Java 8:

  LocalDateTime ldt = timeStamp.toLocalDateTime();
  Timestamp ts = Timestamp.valueOf(ldt);

Para usar con JPA, agregue su modelo ( https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa ):

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime ldt) {
        return Timestamp.valueOf(ldt);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp ts) {
        return ts.toLocalDateTime();
    }
}

Entonces ahora es el tiempo relativo de la zona horaria independiente. Además es fácil hacer:

  LocalDate ld = ldt.toLocalDate();
  LocalTime lt = ldt.toLocalTime();

Formateo:

 DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
 String str = ldt.format(DATE_TME_FORMATTER);
 ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);

ACTUALIZACIÓN: postgres 9.4.1208, HSQLDB 2.4.0, etc., entienden Java 8 Time API sin ninguna conversación.

Grigory Kislin
fuente
17

tl; dr

El proyecto Joda-Time está en modo de mantenimiento, ahora suplantado por las clases java.time .

  • Solo usa lajava.time.Instant clase.
  • No hay necesidad de:
    • LocalDateTime
    • java.sql.Timestamp
    • Instrumentos de cuerda

Capture el momento actual en UTC.

Instant.now()  

Para almacenar ese momento en la base de datos:

myPreparedStatement.setObject(  , Instant.now() )  // Writes an `Instant` to database.

Para recuperar ese momento de la base de datos:

myResultSet.getObject(  , Instant.class )  // Instantiates a `Instant`

Para ajustar la hora del reloj de pared a la de una zona horaria particular.

instant.atZone( z )  // Instantiates a `ZonedDateTime`

LocalDateTime es la clase equivocada

Otras respuestas son correctas, pero no señalan que esa LocalDateTimees la clase incorrecta para su propósito.

Tanto en java.time como en Joda-Time , a LocalDateTimepropósito carece de cualquier concepto de zona horaria o desplazamiento desde UTC. Como tal, no representa un momento y no es un punto en la línea de tiempo. A LocalDateTimerepresenta una idea aproximada sobre los momentos potenciales en un rango de aproximadamente 26-27 horas.

Utilice a LocalDateTimepara cuando la zona / desplazamiento es desconocida (no es una buena situación), o cuando la zona de desplazamiento es indeterminada. Por ejemplo, "La Navidad comienza en el primer momento del 25 de diciembre de 2018" se representaría como un LocalDateTime.

Use a ZonedDateTimepara representar un momento en una zona horaria particular. Por ejemplo, la Navidad comienza en cualquier zona en particular, como Pacific/Aucklando America/Montrealse representaría con un ZonedDateTimeobjeto.

Por un momento siempre en UTC, use Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Aplicar una zona horaria. El mismo momento, el mismo punto en la línea de tiempo, pero se ve con una hora de reloj de pared diferente.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

Entonces, si puedo convertir entre LocalDate y LocalDateTime,

No, estrategia equivocada. Si tiene un valor de solo fecha y desea un valor de fecha y hora, debe especificar una hora del día. Esa hora del día puede no ser válida en esa fecha para una zona en particular, en cuyo caso la ZonedDateTimeclase ajusta automáticamente la hora del día según sea necesario.

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ;  // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

Si desea que el primer momento del día sea su hora del día, deje que java.time determine ese momento. No asuma que el día comienza a las 00:00:00. Anomalías como el horario de verano (DST) significa que el día puede comenzar en otro momento como 01:00:00.

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp es la clase equivocada

Esto java.sql.Timestampforma parte de las problemáticas clases antiguas de fecha y hora que ahora son heredadas, suplantadas completamente por las clases java.time . Esa clase se utilizó para representar un momento en UTC con una resolución de nanosegundos . Ese propósito ahora se cumple java.time.Instant.

JDBC 4.2 con getObject/setObject

A partir de JDBC 4.2 y posterior, su controlador JDBC puede intercambiar directamente objetos java.time con la base de datos llamando a:

Por ejemplo:

myPreparedStatement.setObject(  , instant ) ;

... y ...

Instant instant = myResultSet.getObject(  , Instant.class ) ;

Convertir legado gacy moderno

Si debe interactuar con el código antiguo que aún no se ha actualizado a java.time , convierta de un lado a otro utilizando los nuevos métodos agregados a las clases antiguas.

Instant instant = myJavaSqlTimestamp.toInstant() ;  // Going from legacy class to modern class.

…y…

java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ;  // Going from modern class to legacy class.

Sobre 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 hay necesidad de cadenas, no hay necesidad de java.sql.*clases.

¿Dónde obtener las clases java.time?

  • Java SE 8 , Java SE 9 y posterior
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de las implementaciones de paquetes de Android de las clases java.time.
    • Para anteriormente Android (<26), el ThreeTenABP proyecto adapta ThreeTen-Backport (mencionado anteriormente). Ver Cómo utilizar ThreeTenABP ... .

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 .

Albahaca Bourque
fuente
5

Dependiendo de su zona horaria, puede perder unos minutos (1650-01-01 00:00:00 se convierte en 1649-12-31 23:52:58)

Use el siguiente código para evitar eso

new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);
usuario1302021
fuente
3

Desde Joda se está desvaneció, alguien podría querer convertir LocaltDatea LocalDateTimeen Java 8. En Java 8 LocalDateTimese dará una manera de crear una LocalDateTimeinstancia mediante un LocalDatee LocalTime. Mira aquí.

LocalDateTime público estático de (fecha LocalDate, hora LocalTime)

Muestra sería,

    // just to create a sample LocalDate
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate ld = LocalDate.parse("20180306", dtf);

    // convert ld into a LocalDateTime
    // We need to specify the LocalTime component here as well, it can be any accepted value
    LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

Solo como referencia, para obtener los siguientes segundos de época se puede usar,

    ZoneId zoneId = ZoneId.systemDefault();
    long epoch = ldt.atZone(zoneId).toEpochSecond(); 

    // If you only care about UTC
    long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);
principal
fuente
No hay necesidad de estar usando LocalDateTimeaquí. Esa clase carece deliberadamente de cualquier concepto de zona horaria o desplazamiento desde UTC. Por lo tanto, no sirve para nada aquí. En cambio: LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond()no asuma que el día comienza a las 00:00, no siempre es el caso.
Basil Bourque
¿Por qué quieres decir con no asumir que el día comienza a las 00.00
Primer
1
Anomalías como el horario de verano (DST) significa que en algunas fechas en algunos lugares el día puede comenzar en otro momento, como 01:00:00. Entonces, en lugar de suponer, deje que java.time determine el primer momento llamando java.time.LocalDate.atStartOfDaypara obtener un ZonedDateTime. Ver ejemplos en mi respuesta . Como comenté, la LocalDateTimeclase es inútil y contraproducente en todo esto.
Basil Bourque
Entonces LocalDateTime, ¿debemos usar un ZoneId?
primer
Creo que te has perdido todos mis puntos. Vuelva a leer mi respuesta en esta página. Busque Stack Overflow para obtener más información de muchos más ejemplos y debates. Pero diré por última vez aquí: noLocalDateTime es apropiado para el problema en cuestión aquí. A no no representan un momento. A no tiene nada que ver con una localidad o zona horaria en particular, aunque el nombre puede implicar lo contrario a primera vista: obtenga más información sobre la intención y los detalles de esta clase. La clase tiene un propósito, pero no el propósito visto en esta Pregunta. LocalDateTimeLocalDateTimeLocalDateTime
Basil Bourque
2

la llamada de función asStartOfDay()al java.time.LocalDateobjeto devuelve un java.time.LocalDateTimeobjeto

Ahmad sibai
fuente
0

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)
Mohamed.Abdo
fuente
Útil, pero realmente no parece responder la pregunta.
Ole VV
Gracias por el código, pero no tiene nada que ver con la pregunta.
refaelio