java sql oracle resultset getdate

java - JDBC ResultSet: necesito un getDateTime, pero solo hay getDate y getTimeStamp



get datetime java mysql (4)

La respuesta de Leos Literak es correcta, pero ahora está desactualizada, utilizando una de las antiguas clases problemáticas de fecha y hora, java.sql.Timestamp .

tl; dr

es realmente un DATETIME en el DB

No, no lo es. No hay tipo de datos como DATETIME en la base de datos Oracle.

Estaba buscando un método getDateTime.

Use las clases java.time en JDBC 4.2 y versiones posteriores en lugar de las clases antiguas problemáticas que se ven en su Pregunta. En particular, en lugar de java.sql.TIMESTAMP , utilice la clase Instant por un momento, como el tipo SQL estándar TIMESTAMP WITH TIME ZONE .

Fragmento de código modificado:

if( JDBCType.valueOf( myResultSetMetaData.getColumnType( … ) ) .equals( JDBCType.TIMESTAMP_WITH_TIMEZONE ) ) { Instant instant = myResultSet.getObject( … , Instant.class ) ; }

Detalles

Me gustaría obtener la columna DATETIME de una tabla Oracle DB Table con JDBC.

Según este documento , no hay ningún tipo de datos de columna DATETIME en la base de datos Oracle. Esa terminología parece ser la palabra de Oracle para referirse a todos sus tipos de fecha y hora como un grupo.

No veo el sentido de tu código que detecte el tipo y las ramas en las que se escribe el tipo de datos. En general, creo que debería crear su código explícitamente en el contexto de su tabla particular y un problema comercial particular. Tal vez esto sería útil en algún tipo de marco genérico. Si insiste, siga leyendo para aprender sobre varios tipos y para aprender sobre las nuevas y útiles clases java.time integradas en Java 8 y posteriores que suplantan las clases utilizadas en su Pregunta.

Objetos inteligentes, no cuerdas tontas

valueToInsert = aDate.toString ();

Parece que intenta intercambiar valores de fecha y hora con su base de datos como texto, como objetos String . No lo hagas

Para intercambiar valores de fecha y hora con su base de datos, use objetos de fecha y hora. Ahora en Java 8 y posterior, eso significa objetos java.time , como se explica a continuación.

Varios tipos de sistemas

Puede confundir tres conjuntos de tipos de datos relacionados con la fecha y hora:

  • Tipos de SQL estándar
  • Tipos propietarios
  • Tipos JDBC

Tipos de estándares SQL

El estándar SQL define cinco tipos :

  • DATE
  • TIME WITHOUT TIME ZONE
  • TIME WITH TIME ZONE
  • TIMESTAMP WITHOUT TIME ZONE
  • TIMESTAMP WITH TIME ZONE

Solo fecha

  • DATE
    Solo fecha, sin hora, sin zona horaria.

Hora del día solamente

  • TIME o TIME WITHOUT TIME ZONE
    Solo tiempo, sin fecha. Silenciosamente ignora cualquier zona horaria especificada como parte de la entrada.
  • TIME WITH TIME ZONE TIMETZ TIME WITH TIME ZONE (o TIMETZ )
    Solo tiempo, sin fecha. Aplica las reglas de zona horaria y horario de verano si se incluyen suficientes datos con la entrada. De utilidad cuestionable dados los otros tipos de datos, como se discutió en Postgres doc .

Fecha y hora del día

  • TIMESTAMP o TIMESTAMP WITHOUT TIME ZONE
    Fecha y hora, pero ignora la zona horaria. Cualquier información de zona horaria pasada a la base de datos se ignora sin ajuste a UTC. Por lo tanto, esto no representa un momento específico en la línea de tiempo, sino más bien un rango de momentos posibles durante aproximadamente 26-27 horas. Use esto si la zona horaria o el desplazamiento son (a) desconocidos o (b) irrelevantes, como "Todas nuestras fábricas en todo el mundo cierran al mediodía para almorzar". Si tiene alguna duda, probablemente no es el tipo correcto .
  • TIMESTAMP WITH TIME ZONE (o TIMESTAMPTZ )
    Fecha y hora con respecto a la zona horaria. Tenga en cuenta que este nombre es un nombre poco apropiado dependiendo de la implementación. Algunos sistemas pueden almacenar la información de zona horaria dada. En otros sistemas, como Postgres la información de zona horaria no se almacena , en su lugar, la información de zona horaria pasada a la base de datos se usa para ajustar la fecha y hora a UTC.

Propiedad

Muchas bases de datos ofrecen sus propios tipos relacionados con la fecha y hora. Los tipos propietarios varían ampliamente . Algunos son viejos, tipos heredados que deben evitarse. Algunos creen que el vendedor ofrece ciertos beneficios; usted decide si quedarse con los tipos estándar solamente o no. Cuidado: algunos tipos propietarios tienen un nombre en conflicto con un tipo estándar; Te estoy mirando Oracle DATE .

JDBC

La plataforma Java maneja los detalles internos de la fecha y hora de forma diferente que las bases de datos estándar o específicas de SQL. El trabajo de un controlador JDBC es mediar entre estas diferencias, actuar como un puente, traducir los tipos y sus valores de datos implementados reales según sea necesario. El paquete java.sql. * Es ese puente.

Clases heredadas de JDBC

Antes de Java 8, la especificación JDBC definió 3 tipos para el trabajo de fecha y hora. Los primeros dos son hacks como antes de la Versión 8, Java carecía de cualquier clase para representar un valor solo de fecha o solo de tiempo.

  • java.sql.Date
    Simula una fecha solamente, pretende no tener tiempo, ni zona horaria. Puede ser confuso ya que esta clase es una envoltura alrededor de java.util.Date que rastrea tanto la fecha como la hora. Internamente, la porción de tiempo se establece en cero (UTC de medianoche).
  • java.sql.Time
    Solo el tiempo, pretende no tener fecha, y no huso horario. También puede ser confuso ya que esta clase también es una envoltura delgada alrededor de java.util.Date que rastrea tanto la fecha como la hora. Internamente, la fecha se establece en cero (1 de enero de 1970).
  • java.sql.TimeStamp
    Fecha y hora, pero no zona horaria. Esto también es una envoltura delgada alrededor de java.util.Date.

Entonces, eso responde su pregunta sobre el método "getDateTime" en la interfaz ResultSet . Esa interfaz ofrece métodos getter para los tres tipos de datos de puente definidos en JDBC:

Tenga en cuenta que los primeros carecen de cualquier concepto de zona horaria o desplazamiento desde UTC. El último, java.sql.Timestamp siempre está en UTC a pesar de lo que le dice su método toString .

Clases modernas JDBC

Debe evitar las clases de JDBC mal diseñadas enumeradas anteriormente. Ellos son suplantados por los tipos java.time .

  • En lugar de java.sql.Date , use LocalDate . Se adapta al tipo de DATE SQL estándar.
  • En lugar de java.sql.Time , use LocalTime . Se adapta al estándar SQL TIME WITHOUT TIME ZONE .
  • En lugar de java.sql.Timestamp , usa Instant . Se adapta al TIMESTAMP WITH TIME ZONE SQL estándar con el tipo de TIMESTAMP WITH TIME ZONE .

A partir de JDBC 4.2 y posterior, puede intercambiar directamente objetos java.time con su base de datos. Use los métodos setObject / getObject .

Insertar / actualizar.

myPreparedStatement.setObject( … , instant ) ;

Recuperación.

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

La clase Instant representa un momento en la línea de tiempo en UTC con una resolución de nanoseconds (hasta nueve (9) dígitos de una fracción decimal).

Ajuste de zona horaria

Si desea ver el momento de un Instant visto a través del reloj de pared utilizado por las personas de una región en particular (una zona horaria) en lugar de como UTC, ajuste aplicando un ZoneId para obtener un objeto ZonedDateTime .

ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ; ZonedDateTime zdtAuckland = instant.atZone( zAuckland ) ;

El objeto ZonedDateTime resultante es el mismo momento , el mismo punto simultáneo en la línea de tiempo. Un nuevo día amanece antes hacia el este, por lo que la fecha y la hora del día serán diferentes. Por ejemplo, unos minutos después de la medianoche en Nueva Zelanda todavía está "ayer" en UTC.

Puede aplicar otra zona horaria a Instant ZonedDateTime o ZonedDateTime para ver el mismo momento simultáneo a través de otro reloj de pared utilizado por personas en otra región.

ZoneId zMontréal = ZoneId.of( "America/Montreal" ) ; ZonedDateTime zdtMontréal = zdtAuckland.withZoneSameInstant( zMontréal ) ; // Or, for the same effect: instant.atZone( zMontréal )

Entonces ahora tenemos tres objetos ( instant , zdtAuckland , zMontréal ) que representan el mismo momento, el mismo punto en la línea de tiempo.

Detectando el tipo

Para volver al código en la Pregunta sobre la detección del tipo de datos de las bases de datos: (a) no es mi campo de experiencia, (b) Evitaría esto como se menciona arriba, y (c) si insiste en esto, tenga cuidado que a partir de Java 8 y posterior, la clase java.sql.Types está obsoleta. Esa clase ahora se reemplaza por una Java Enum adecuada de JDBCType que implementa la nueva interfaz SQLType . Vea esta respuesta a una pregunta relacionada.

Este cambio se detalla en la versión de mantenimiento JDBC 4.2 , secciones 3 y 4. Para citar:

Adición de java.sql.JDBCType Enum

Un Enum utilizado para identificar tipos de SQL genéricos, llamados Tipos JDBC. La intención es usar JDBCType en lugar de las constantes definidas en Types.java.

La enumeración tiene los mismos valores que la clase anterior, pero ahora proporciona type-safety .

Una nota sobre la sintaxis: en Java moderno, puede usar un switch en un objeto Enum . Por lo tanto, no es necesario utilizar sentencias en caso de cascada como se ve en su pregunta. La única pega es que el nombre del objeto enum debe usarse sin reservas cuando se cambia por alguna razón técnica oscura, por lo que debe hacer el switch TIMESTAMP_WITH_TIMEZONE lugar del JDBCType.TIMESTAMP_WITH_TIMEZONE calificado.TIMESTAMP_WITH_TIMEZONE. Use una declaración de static import .

Entonces, todo lo que quiero decir es que supongo (todavía no lo he intentado) que puedes hacer algo como el siguiente ejemplo de código.

final int columnType = myResultSetMetaData.getColumnType( … ) ; final JDBCType jdbcType = JDBCType.valueOf( columnType ) ; switch( jdbcType ) { case DATE : // FYI: Qualified type name `JDBCType.DATE` not allowed in a switch, because of an obscure technical issue. Use a `static import` statement. … break ; case TIMESTAMP_WITH_TIMEZONE : … break ; default : … break ; }

Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las problemáticas antiguas clases legacy 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. Use un controlador JDBC que cumpla con JDBC 4.2 o posterior. Sin necesidad de cadenas, sin necesidad de clases java.sql.* .

¿Dónde obtener las clases de java.time?

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

El proyecto ThreeTen-Extra amplía 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 .

ACTUALIZACIÓN: El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time . Esta sección quedó intacta como historia.

Joda-Time

Antes de Java 8 (paquete java.time. *), Las clases de fecha y hora incluidas en java (java.util.Date & Calendar, java.text.SimpleDateFormat) son notoriamente problemáticas, confusas y defectuosas.

Una mejor práctica es tomar lo que su controlador JDBC le brinda y crear objetos Joda-Time, o en Java 8, java.time. * Package . Eventualmente, debería ver nuevos controladores JDBC que usan automáticamente las nuevas clases java.time. *. Hasta entonces, se han agregado algunos métodos a clases como java.sql.Timestamp para interponer con java.time como toInstant y fromInstant .

Cuerda

En cuanto a la última parte de la pregunta, la representación de un String ... Se debe usar un objeto formateador para generar un valor de cadena.

La forma antigua es con java.text.SimpleDateFormat. No recomendado.

Joda-Time proporciona varios formateadores incorporados, y también puede definir el suyo propio. Pero para escribir registros o informes como mencionó, la mejor opción puede ser el formato ISO 8601. Ese formato es el predeterminado utilizado por Joda-Time y java.time.

Código de ejemplo

//java.sql.Timestamp timestamp = resultSet.getTimestamp(i); // Or, fake it // long m = DateTime.now().getMillis(); // java.sql.Timestamp timestamp = new java.sql.Timestamp( m ); //DateTime dateTimeUtc = new DateTime( timestamp.getTime(), DateTimeZone.UTC ); DateTime dateTimeUtc = new DateTime( DateTimeZone.UTC ); // Defaults to now, this moment. // Convert as needed for presentation to user in local time zone. DateTimeZone timeZone = DateTimeZone.forID("Europe/Paris"); DateTime dateTimeZoned = dateTimeUtc.toDateTime( timeZone );

Volcado a la consola ...

System.out.println( "dateTimeUtc: " + dateTimeUtc ); System.out.println( "dateTimeZoned: " + dateTimeZoned );

Cuando se ejecuta ...

dateTimeUtc: 2014-01-16T22:48:46.840Z dateTimeZoned: 2014-01-16T23:48:46.840+01:00

Me gustaría obtener la columna DATETIME de una tabla Oracle DB Table con JDBC. Aquí está mi código:

int columnType = rsmd.getColumnType(i); if(columnType == Types.DATE) { Date aDate = rs.getDate(i); valueToInsert = aDate.toString(); } else if(columnType == Types.TIMESTAMP) { Timestamp aTimeStamp = rs.getTimestamp(i); valueToInsert = aTimeStamp.toString(); } else { valueToInsert = rs.getString(i); }

Debo identificar primero el tipo de columna. El campo en el que estoy interesado se reconoce como Types.DATE, pero en realidad es un DATETIME en el DB ya que tiene este formato: "07.05.2009 13:49:32"

getDate trunca el tiempo: "07.05.2009" y getString agrega ".0" a él: "07.05.2009 13: 49: 32.0"

Por supuesto, podría eliminar el .0 final y trabajar con getString todo el tiempo, pero es una solución sucia.

Algunas ideas ? Estaba buscando un método getDateTime.

Saludos, Tim


La solución que opté por formatear la fecha con la consulta mysql:

String l_mysqlQuery = "SELECT DATE_FORMAT(time, ''%Y-%m-%d %H:%i:%s'') FROM uld_departure;" l_importedTable = fStatement.executeQuery( l_mysqlQuery ); System.out.println(l_importedTable.getString( timeIndex));

Yo tuve exactamente el mismo problema. Aunque mi tabla mysql contiene fechas formateadas como tales: 2017-01-01 21:02:50

String l_mysqlQuery = "SELECT time FROM uld_departure;" l_importedTable = fStatement.executeQuery( l_mysqlQuery ); System.out.println(l_importedTable.getString( timeIndex));

estaba devolviendo una fecha formateada como tal: 2017-01-01 21:02:50.0


esto funcionó

Date date = null; String dateStr = rs.getString("doc_date"); if (dateStr != null) { date = dateFormat.parse(dateStr); }

usando SimpleDateFormat.


java.util.Date date; Timestamp timestamp = resultSet.getTimestamp(i); if (timestamp != null) date = new java.util.Date(timestamp.getTime()));

Luego, formatee de la manera que desee.