Mysql
 sql >> Base de données >  >> RDS >> Mysql

Différence de fuseau horaire dans mysql et java

Contexte :Une idée fausse étonnamment commune - et importante - partagée par des programmeurs même brillants est la notion que les horodatages stockés (dans votre base de données, date, calendrier, horodatage, etc.) contiennent en quelque sorte des informations sur le fuseau horaire. Ils ne le font pas. Un horodatage (jusqu'à Java 8, de toute façon) est stocké en tant que nombre de millisecondes depuis minuit le 1er janvier 1970 UTC. Fin de phrase. La seule chose que fait le réglage du fuseau horaire est de fournir suffisamment d'informations à l'ordinateur pour convertir cet horodatage dans un format lisible par l'homme, et vice versa.

Réponse :Lorsque vous avez pensé qu'il s'agissait d'un problème de fuseau horaire, vous aviez raison . Mais le code que vous avez utilisé pour essayer de vérifier cela a aussi un problème :

end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

Ce setTimeZone déclaration n'a aucun effet sur l'heure stockée dans end , car l'heure a déjà été réglée. Cela n'aurait eu d'effet que si vous aviez stocké l'heure par la suite, et seulement si vous aviez utilisé l'une des méthodes de Calendar qui convertissait l'heure à partir d'un format lisible par l'homme (et non setTimeInMillis ).

Lorsque vous utilisez getTimeInMillis pour transmettre l'horodatage à votre relevé préparé, vous récupérez directement l'horodatage. Puisque vous ne le convertissez pas dans un format humain, une fois de plus, les informations de fuseau horaire sont ignorées.

Lorsque vous essayez

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
end.setTime(sdf.parse("2012-10-01 00:00:00"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));

et

pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));

les choses apparaissent fonctionner parce que vous utilisez maintenant des méthodes qui convertissent vers/à partir d'un format lisible par l'homme, et donc les informations de fuseau horaire spécifiées sont utilisées. Cependant, cela ne fait que masquer le vrai problème. Le vrai problème est que l'heure n'a pas été correctement convertie lorsque vous l'avez analysée à partir de endString . C'est-à-dire le fuseau horaire que endString a été exprimé en ne correspond pas au fuseau horaire défini dans df1 au moment où la date a été analysée.

REPONSE COURTE :avant cette ligne :

end.setTime(df1.parse(endString));

Vous devez :

  • Identifiez le fuseau horaire dans endString a été exprimé en.
  • Définir df1 et non end à ce même fuseau horaire. Depuis df1 est la chose qui convertit la date du format humain, c'est cette information de fuseau horaire qui est utilisée.

Santé !