JDBC ResultSet: j'ai besoin d'un getDateTime, mais il n'y a que getDate et getTimeStamp

j'aimerais obtenir la colonne DATETIME d'une Table Oracle DB avec JDBC. Voici mon code:

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);
}

je dois d'abord identifier le type de colonne. Le domaine qui m'intéresse est reconnu comme un type.DATE, mais c'est vraiment une DATETIME dans le DB car il a ce format: "07.05.2009 13:49:32"

GETDATE tronque l'heure:" 07.05.2009" et getString ajoute ".0 0 0 0 0 0 0 0 0 0 0: "07.05.2009 13:49:32.0"

de bien sûr que je peux enlever la finale .0 et travailler avec getString tout le temps, mais c'est un sale boulot.

des idées ? Je cherchais une méthode getDateTime.

santé, Tim

36
demandé sur Tim 2014-01-16 17:10:04

4 réponses

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

alors formatez-le comme vous voulez.

76
répondu Leos Literak 2014-01-16 13:42:57

Le réponse de Leos Literak est correct, mais aujourd'hui désuet, à l'aide de l'un de l'importun de longue date du temps des classes, java.sql.Timestamp .

tl; dr

c'est vraiment un DATETIME dans la DB

Non, ça ne l'est pas. Aucun type de données tel que DATETIME dans la base de données Oracle.

je cherchais une méthode getDateTime.

Utiliser de java.les classes de temps dans JDBC 4.2 et plus tard plutôt que les classes d'héritage gênantes vues dans votre Question. En particulier, plutôt que java.sql.TIMESTAMP , utilisez Instant classe pour un moment tel que le type standard SQL TIMESTAMP WITH TIME ZONE .

extrait de code inventé:

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

détails

je voudrais obtenir la colonne DATETIME d'un Oracle Table DB avec JDBC.

selon CE doc , il n'y a pas de type de données de colonne DATETIME dans la base de données Oracle. Cette terminologie semble être le mot D'Oracle pour se référer à tous leurs types de date-heure en tant que groupe.

Je ne vois pas le point de votre code qui détecte le type et les branches sur lesquelles le type de données. Généralement, je pense que vous devriez être l'élaboration de votre code explicitement dans le contexte de votre particulier table et des problèmes. Cela serait peut-être utile dans une sorte de cadre générique. Si vous insistez, lisez la suite pour en savoir plus sur les différents types, et pour en savoir plus sur le nouveau java extrêmement utile .les classes time intégrées dans Java 8 et plus tard qui remplacent les classes utilisées dans votre Question.

"1519800920 des" objets Intelligents, pas idiot chaînes

valueToInsert = aDate.toString ();

vous semblez essayer d'échanger des valeurs date-heure avec votre base de données en tant que texte, comme String objets. Ne le fais pas.

pour échanger des valeurs date-heure avec votre base de données, utilisez des objets date-heure. Maintenant en Java 8 et plus tard, cela signifie java.les objets de temps , tel que discuté ci-dessous.

Divers systèmes de type

vous pouvez confondre trois ensembles de types de données liées à l'heure et à la date:

  • Standard SQL types
  • types brevetés
  • types JDBC

SQL standard types

la norme SQL définit cinq types :

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

Date

  • DATE

    Date seulement, pas d'Heure, pas de fuseau horaire.

Heure de la journée seulement

  • TIME ou TIME WITHOUT TIME ZONE

    Temps seulement, pas de date. Ignore silencieusement tout fuseau horaire spécifié comme faisant partie de l'entrée.
  • TIME WITH TIME ZONE (ou TIMETZ )

    seulement L'Heure, pas de date. Applique les règles relatives aux fuseaux horaires et à l'heure avancée si des données suffisantes sont incluses avec la saisie. D'une utilité douteuse compte tenu des autres types de données, comme discuté dans le doc Postgres .

Date Et Heure De La Journée

  • TIMESTAMP ou TIMESTAMP WITHOUT TIME ZONE

    Date et heure, mais ignore fuseau horaire. Toute information de fuseau horaire transmise à la base de données est ignorée sans ajustement à UTC. Donc ce ne pas représente un moment spécifique sur la ligne de temps, mais plutôt une gamme de moments possibles sur environ 26-27 heures. Utilisez ceci si le fuseau horaire ou le décalage est (a) inconnu ou (B) non pertinent tel que "toutes nos usines autour du monde ferment à midi pour le déjeuner". Si vous avez des doutes, probablement pas le bon type .
  • TIMESTAMP WITH TIME ZONE (ou TIMESTAMPTZ )

    Date et heure en respectant le fuseau horaire. Notez que ce nom est quelque peu erroné selon la mise en œuvre. Certains systèmes peuvent stocker les informations données sur les fuseaux horaires. Dans d'autres systèmes tels que Postgres le information de fuseau horaire est pas stocké , au lieu de l'information de fuseau horaire passé à la base de données est utilisé pour ajuster la date-heure à UTC.

exclusive

de nombreuses bases de données offrent leurs propres types de date-heure. Les types propriétaires varient largement . Certains sont anciens, des types de legs qui devraient être évités. Certains sont considérés par le vendeur comme offrant certains avantages; vous décidez de vous en tenir aux types standards seulement ou non. Attention: certains types propriétaires ont un nom en conflit avec un type standard; Je te regarde Oracle DATE 1519780920" .

JDBC

la plate-forme Java traite les détails internes de la date-heure différemment de la norme SQL ou des bases de données spécifiques. Le travail d'un JDBC driver est de servir de médiateur entre ces différences, d'agir comme un pont, traduisant les types et leurs valeurs réelles de données implémentées si nécessaire. Le java.SQL.* paquet est ce pont.

JDBC héritage de classes

avant Java 8, le JDBC spec défini 3 types pour le travail de date-heure. Les deux premiers sont des hacks comme avant la Version 8, Java n'avait aucune classe pour représenter une valeur date-only ou time-only.

  • de java.SQL.Date

    simule une date-seulement, prétend n'avoir pas de temps, pas de temps zone. Peut être déroutant car cette classe est un wrapper autour de java.util.Date qui suit à la fois la date et heure. À l'interne, le temps est réglé à zéro (minuit UTC).
  • de java.SQL.Temps

    Temps seulement, prétend n'ont pas de date, et pas de temps horaire. Peut aussi être déroutant car cette classe aussi est un emballage mince autour de java.util.Date qui suit à la fois la date et heure. À l'interne, la date est fixée à zéro (1er janvier 1970).
  • de java.SQL.Horodatage

    Date et heure, mais pas de fuseau horaire. Ceci aussi est un emballage fin autour de java.util.Date.

de sorte que répond à votre question concernant aucune méthode "getDateTime" dans le L'interface de résultat . Cette interface offre méthodes getter pour les trois passerelles types de données définis dans JDBC:

notez que le premier n'a aucune notion de fuseau horaire ou de décalage par rapport à-UTC. Le dernier, java.sql.Timestamp est toujours en UTC malgré sa méthode toString vous le dit.

classes modernes JDBC

vous devez éviter les classes JDBC mal conçues énumérées ci-dessus. Ils sont supplantés par le java.temps .

  • au lieu de java.sql.Date , utilisez LocalDate . Costumes de type SQL-standard DATE .
  • au lieu de java.sql.Time , utilisez LocalTime . Costumes SQL-standard TIME WITHOUT TIME ZONE type.
  • au lieu de java.sql.Timestamp , utilisez Instant . Costumes de type SQL-standard TIMESTAMP WITH TIME ZONE .

à partir de JDBC 4.2 et plus tard, vous pouvez directement échanger java.time objets avec votre base de données. Utiliser les méthodes setObject / getObject .

insérer / mettre à jour.

myPreparedStatement.setObject( … , instant ) ;

de Récupération.

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

le Instant classe représente un moment sur la ligne de temps dans UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).

Ajustement du fuseau horaire

si vous voulez voir le moment d'un Instant vu à travers l'heure d'horloge utilisée par les gens d'une région particulière (un fuseau horaire) plutôt que comme UTC, ajuster en appliquant un ZoneId pour obtenir un ZonedDateTime objet.

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

le résultat ZonedDateTime objet est le même moment , le même point simultané sur la ligne de temps. Un nouveau jour se lève plus tôt à l'est, la date et l'heure de la journée sera différente. Par exemple, quelques minutes après minuit, en Nouvelle-Zélande est encore "hier" en UTC.

vous pouvez appliquer encore un autre fuseau horaire au Instant ou ZonedDateTime pour voir le même moment simultané à travers encore une autre horloge murale utilisée par les gens d'une autre région.

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

donc maintenant nous avons trois objets ( instant , zdtAuckland , zMontréal ) tous représentent le même moment, le même point sur la ligne du temps.

Type de détection

pour revenir au code en Question sur la détection du type de données des bases de données: (a) pas mon domaine d'expertise, (b) je voudrais éviter cela comme mentionné ci-dessus, et (c) si vous insistez là-dessus, prenez garde qu'à partir de Java 8 et plus tard, la classe java.sql.Types est dépassée. Cette classe est maintenant remplacée par une Java 1519580920 " de JDBCType qui implémente la nouvelle interface SQLType . Voir cette réponse à une question connexe.

ce changement est indiqué dans JDBC Maintenance Release 4.2 , sections 3 et 4. Pour citer:

ajout du java.SQL.JDBCType Enum

Enum utilisé pour identifier les types SQL génériques, appelés Types JDBC. L'intention est d'utiliser JDBCType à la place des constantes définies dans les Types.Java.

l'enum a les mêmes valeurs que l'ancienne classe, mais fournit maintenant type-safety .

Une remarque à propos de syntaxe: en Java moderne, vous pouvez utiliser un switch sur un objet Enum . Donc pas besoin d'utiliser la cascade si-alors des déclarations comme vu dans votre Question. Le seul inconvénient est que le nom de l'objet enum doit être utilisé sans réserve lors de la commutation pour une raison technique obscure, donc vous devez faire votre switch sur TIMESTAMP_WITH_TIMEZONE plutôt que le JDBCType.TIMESTAMP_WITH_TIMEZONE qualifié . Utilisez une instruction static import .

donc, tout ce qui est à dire que je suppose (je n'ai pas encore essayé) vous pouvez faire quelque chose comme l'exemple de code suivant.

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 ;

}

à Propos de de java.heure

Le de java.time framework est construit dans Java 8 et plus tard. Ces classes remplacent les anciennes classes de date legacy telles que java.util.Date , Calendar , & SimpleDateFormat .

le "15193610920 Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.temps classes.

pour en savoir plus, voir le Oracle Tutorial . Et rechercher le débordement de la pile pour de nombreux exemples et explications. La spécification est JSR 310 .

vous pouvez échanger java.temps objets directement avec votre base de données. Utiliser un JDBC driver conforme à JDBC 4.2 ou plus récent. Pas besoin de Chaînes, pas besoin de classes java.sql.* .

où obtenir le java.les classes de temps?

The ThreeTen-Extra le projet s'étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver ici quelques cours utiles tels que: Interval , YearWeek , YearQuarter , et plus .


mise à jour: le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.temps classes. Cette section est restée intacte en tant qu'histoire.

Joda-Time

avant Java 8 (java.temps.* paquet), les classes de date-heure regroupées avec java (java.util.Date et Calendrier, java.texte.SimpleDateFormat) sont notoirement gênants, confus, et défectueux.

une meilleure pratique est de prendre ce que votre pilote JDBC vous donne et de créer des objets Joda-Time, ou en Java 8, java.temps.* paquet . Finalement, vous devriez voir de nouveaux pilotes JDBC qui utilisent automatiquement le nouveau java.temps.* classe. Jusqu'alors, certaines méthodes ont été ajoutées à des classes java.SQL.Horodatage à intervenir avec java.temps tel que toInstant et fromInstant .

chaîne

quant à la dernière partie de la question, rendre une chaîne... un objet formatter doit être utilisé pour générer une valeur de chaîne.

à L'ancienne est avec java.texte.SimpleDateFormat. Pas recommandé.

Joda-Time fournir divers formatteurs intégrés, et vous pouvez également définir votre propre. Mais pour l'écriture des journaux ou des rapports comme vous l'avez mentionné, le meilleur choix peut être le format ISO 8601. Ce format est utilisé par défaut par Joda-Time et java.temps.

Exemple De Code

//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 );

Vidage de la console...

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

Lors de l'exécuter...

dateTimeUtc: 2014-01-16T22:48:46.840Z
dateTimeZoned: 2014-01-16T23:48:46.840+01:00
36
répondu Basil Bourque 2018-04-25 02:56:08

cela a fonctionné:

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

utilisant SimpleDateFormat.

0
répondu Nikolay Kombarov 2017-12-08 10:40:17

la solution que j'ai choisie était de formater la date avec la requête 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));

j'ai eu exactement le même problème. Même si ma table mysql contient des dates formatées comme telles: 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));

retournait une date formatée comme telle : 2017-01-01 21:02:50.0

0
répondu Albizia 2018-03-23 11:13:01