Code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); System.out.println(new Date()); try { Ssortingng d = sdf.format(new Date()); System.out.println(d); System.out.println(sdf.parse(d)); } catch (Exception e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. }
Sortie:
Thu Aug 08 17:26:32 GMT+08:00 2013 2013.08.08 09:26:32 GMT Thu Aug 08 17:26:32 GMT+08:00 2013
Notez que format()
formate correctement la Date
en GMT, mais que parse()
perdu les détails GMT. Je sais que je peux utiliser la subssortingng()
et contourner ce problème, mais quelle est la raison de ce phénomène?
Voici une question en double qui n’a pas de réponse.
Edit: Permettez-moi de poser la question d’une autre manière, quelle est la manière de récupérer un object Date afin qu’il soit toujours dans GMT?
Tout ce dont j’avais besoin était ceci:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); try { Ssortingng d = sdf.format(new Date()); System.out.println(d); System.out.println(sdfLocal.parse(d)); } catch (Exception e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. }
Sortie: légèrement douteuse, mais je veux seulement que la date soit cohérente
2013.08.08 11:01:08 Thu Aug 08 11:01:08 GMT+08:00 2013
La solution d’OP à son problème, comme il le dit, a des résultats douteux. Ce code montre encore une confusion sur les représentations du temps. Pour dissiper cette confusion et créer un code qui ne conduise pas à des moments incorrects, considérez cette extension de ce qu’il a fait:
public static void _testDateFormatting() { SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT")); SimpleDateFormat sdfGMT2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z"); sdfGMT2.setTimeZone(TimeZone.getTimeZone("GMT")); SimpleDateFormat sdfLocal1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); SimpleDateFormat sdfLocal2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z"); try { Date d = new Date(); Ssortingng s1 = d.toSsortingng(); Ssortingng s2 = sdfLocal1.format(d); // Store s3 or s4 in database. Ssortingng s3 = sdfGMT1.format(d); Ssortingng s4 = sdfGMT2.format(d); // Resortingeve s3 or s4 from database, using LOCAL sdf. Ssortingng s5 = sdfLocal1.parse(s3).toSsortingng(); //EXCEPTION Ssortingng s6 = sdfLocal2.parse(s3).toSsortingng(); Ssortingng s7 = sdfLocal1.parse(s4).toSsortingng(); Ssortingng s8 = sdfLocal2.parse(s4).toSsortingng(); // Resortingeve s3 from database, using GMT sdf. // Note that this is the SAME sdf that created s3. Date d2 = sdfGMT1.parse(s3); Ssortingng s9 = d2.toSsortingng(); Ssortingng s10 = sdfGMT1.format(d2); Ssortingng s11 = sdfLocal2.format(d2); } catch (Exception e) { e.printStackTrace(); } }
examiner les valeurs dans un débogueur:
s1 "Mon Sep 07 06:11:53 EDT 2015" (id=831698113128) s2 "2015.09.07 06:11:53" (id=831698114048) s3 "2015.09.07 10:11:53" (id=831698114968) s4 "2015.09.07 10:11:53 GMT+00:00" (id=831698116112) s5 "Mon Sep 07 10:11:53 EDT 2015" (id=831698116944) s6 -- omitted, gave parse exception s7 "Mon Sep 07 10:11:53 EDT 2015" (id=831698118680) s8 "Mon Sep 07 06:11:53 EDT 2015" (id=831698119584) s9 "Mon Sep 07 06:11:53 EDT 2015" (id=831698120392) s10 "2015.09.07 10:11:53" (id=831698121312) s11 "2015.09.07 06:11:53 EDT" (id=831698122256)
sdf2 et sdfLocal2 incluent le fuseau horaire, nous pouvons donc voir ce qui se passe réellement. s1 & s2 sont à 06:11:53 dans la zone EDT. s3 & s4 sont à 10:11:53 dans la zone GMT – équivalent à l’heure EDT d’origine. Imaginez que nous économisons s3 ou s4 dans une firebase database, où nous utilisons la GMT pour la cohérence, de sorte que nous pouvons avoir des temps de n’importe où dans le monde, sans stocker différents fuseaux horaires.
s5 parsing l’heure GMT, mais la traite comme une heure locale. Donc, il est dit “10:11:53” – l’heure GMT – mais pense qu’il est 10:11:53 à l’ heure locale . Pas bon.
s7 parsing l’heure GMT, mais ignore le GMT dans la chaîne, donc le traite toujours comme une heure locale.
S8 fonctionne, car nous incluons maintenant GMT dans la chaîne, et l’parsingur de zone locale l’utilise pour convertir un fuseau horaire en un autre.
Supposons maintenant que vous ne souhaitiez pas stocker la zone, vous voulez pouvoir parsingr s3, mais l’afficher comme heure locale. La réponse est d’ parsingr en utilisant le même fuseau horaire dans lequel il a été stocké – utilisez donc le même sdf que celui dans lequel il a été créé, sdfGMT1. s9, s10, & s11 sont toutes des représentations de l’heure d’origine. Ils sont tous “corrects”. C’est-à-dire, d2 == d1. Alors ce n’est qu’une question de comment vous voulez l’afficher. Si vous souhaitez afficher ce qui est stocké dans l’heure DB-GMT, vous devez le formater à l’aide d’un fichier sdf GMT. C’est s10.
Voici donc la solution finale, si vous ne souhaitez pas stocker explicitement avec “GMT” dans la chaîne et que vous souhaitez afficher au format GMT:
public static void _testDateFormatting() { SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT")); try { Date d = new Date(); Ssortingng s3 = sdfGMT1.format(d); // Store s3 in DB. // ... // Resortingeve s3 from database, using GMT sdf. Date d2 = sdfGMT1.parse(s3); Ssortingng s10 = sdfGMT1.format(d2); } catch (Exception e) { e.printStackTrace(); } }
Quelle est la manière de récupérer un object Date afin qu’il soit toujours en GMT?
Instant.now()
Vous utilisez d’anciennes classes date-heure déroutantes qui sont maintenant supplantées par les classes java.time.
Instant
= UTC La classe Instant
représente un moment sur la timeline en UTC avec une résolution de nanosecondes (jusqu’à neuf (9) chiffres d’une fraction décimale).
Instant instant = Instant.now() ; // Current moment in UTC.
Pour échanger ces données sous forme de texte, utilisez exclusivement les formats standard ISO 8601 . Ces formats sont judicieusement conçus pour être non ambigus, faciles à traiter par machine et faciles à lire dans de nombreuses cultures.
Les classes java.time utilisent les formats standard par défaut lors de l’parsing et de la génération de chaînes.
Ssortingng output = instant.toSsortingng() ;
2017-01-23T12: 34: 56.123456789Z
Si vous voulez voir le même moment que celui présenté dans l’horloge d’une région particulière, appliquez un ZoneId
pour obtenir un ZonedDateTime
.
Spécifiez un nom de fuseau horaire approprié dans le format de continent/region
, tel que America/Montreal
, Africa/Casablanca
ou Pacific/Auckland
. N’utilisez jamais l’abréviation de 3-4 lettres comme EST
ou IST
car ce ne sont pas de véritables fuseaux horaires, non standardisés, et même pas uniques (!).
ZoneId z = ZoneId.of( "Asia/Singapore" ) ; ZonedDateTime zdt = instant.atZone( z ) ; // Same simultaneous moment, same point on the timeline.
Voir ce code en direct sur IdeOne.com .
Notez la différence de huit heures, car le fuseau horaire de l’ Asia/Singapore
actuellement un décalage par rapport à l’UTC de +08: 00. Même moment, heure de l’horloge différente.
instant.toSsortingng (): 2017-01-23T12: 34: 56.123456789Z
zdt.toSsortingng (): 2017-01-23T20: 34: 56.123456789 + 08: 00 [Asie / Singapour]
Évitez la classe java.util.Date
héritée. Mais si vous devez, vous pouvez convertir. Regardez les nouvelles méthodes ajoutées aux anciennes classes.
java.util.Date date = Date.fromInstant( instant ) ;
… Aller dans l’autre sens…
Instant instant = myJavaUtilDate.toInstant() ;
Pour la date uniquement, utilisez LocalDate
.
LocalDate ld = zdt.toLocalDate() ;
Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes de date / heure héritées telles que java.util.Date
, Calendar
et SimpleDateFormat
.
Le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes java.time .
Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .
Où obtenir les classes java.time?
Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts futurs à java.time. Vous pouvez y trouver des classes utiles telles que Interval
, YearWeek
, YearQuarter
, etc.