Quand vous faites:
dateFormat.setTimeZone(TimeZone.getDefault());
Et puis analyser le String
, vous dites au formatter: « Je vais vous donner une chaîne avec une date et l'heure dans ce fuseau horaire ». Comme vous avez utilisé TimeZone.getDefault()
, il utilisera le fuseau horaire par défaut de la JVM. La première chose est de dire la formatter à utiliser UTC lors de l'analyse:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use UTC to parse
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
....
date = dateFormat.parse(dateString);
Je teste avec dateString
égale à 2017-08-01 10:00:00
. Ainsi, le date
sera équivalent à 2017-08-01 10:00:00 UTC
. Lorsque vous imprimez la date avec System.out.println
, il appelle le toString()
et le convertit dans le fuseau horaire par défaut de la JVM.
Dans la machine virtuelle Java J'utilise, le fuseau horaire par défaut est America/Sao_Paulo
, quand j'appelle cela:
System.out.println(date);
Il imprime:
Mar 1 août 2017 07:00:00 BRT
Parce que en 1 Août st, 10 heures UTC équivaut à 7 heures à São Paulo. Ce résultat changera en fonction du fuseau horaire par défaut de votre JVM,.
Si vous souhaitez imprimer cette date, mais avec la date et l'heure équivalent à un autre fuseau horaire (autre que UTC), vous aurez besoin d'un autre formatter avec un autre jeu de fuseau horaire:
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use my default timezone to format (America/Sao_Paulo)
dateFormat2.setTimeZone(TimeZone.getDefault());
formattedDate = dateFormat2.format(date);
Ce imprimera:
2017-08-01 07:00:00
au lieu du fuseau horaire par défaut, vous pouvez utiliser ce que fuseau horaire que vous voulez (j'utilise America/New_York
comme exemple):
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use New York timezone
dateFormat2.setTimeZone(TimeZone.getTimeZone("America/New_York"));
formattedDate = dateFormat2.format(date);
Ceci convertira la date/heure au fuseau horaire de New York:
2017-08-01 06:00:00
Si vous voulez imprimer la date/heure en UTC, alors vous n'avez pas besoin de créer un autre formateur, utilisez simplement le premier (car il est déjà défini sur UTC).
Le fuseau horaire par défaut de JVM can be changed without notice, even at runtime, il est donc préférable d'utiliser un spécifique au lieu d'utiliser getDefault()
.
Préférez utiliser IANA timezones names (toujours au format Region/City
, comme America/Sao_Paulo
ou Europe/Berlin
). Évitez d'utiliser les abréviations à 3 lettres (comme CST
ou) car elles sont ambiguous and not standard.
Vous pouvez obtenir la liste des fuseaux horaires disponibles (et choisir celle qui correspond le mieux à votre système) en appelant TimeZone.getAvailableIDs()
.
nouvelle date/API Temps
Les anciennes classes (Date
, Calendar
et SimpleDateFormat
) ont lots of problems et design issues, et ils sont remplacés par les nouvelles API.
Dans Android, vous pouvez utiliser le ThreeTen Backport, un excellent backport pour les nouvelles classes date/heure de Java 8. Pour le faire fonctionner, vous aurez également besoin de ThreeTenABP (plus sur comment l'utiliser here).
Cette API est beaucoup plus facile à utiliser. D'abord, créez un org.threeten.bp.format.DateTimeFormatter
et analysez l'entrée String
en org.threeten.bp.LocalDateTime
.
Ensuite, vous le convertir en UTC (création d'un org.threeten.bp.ZonedDateTime
), puis le fuseau horaire que vous voulez et utilisez un autre formatter pour le sortir:
// date/time with optional milliseconds
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]");
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(dateString, parser);
// convert to UTC
ZonedDateTime z = dt.atZone(ZoneOffset.UTC);
// convert to another timezone
z = z.withZoneSameInstant(ZoneId.of("America/New_York"));
// format it
// date/time without milliseconds
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(z));
Vous pouvez également utiliser le fuseau horaire par défaut en utilisant ZoneId.systemDefault()
, et obtenir tous les fuseaux horaires disponibles avec ZoneId.getAvailableZoneIds()
.
Si vous voulez la date/heure en UTC, vous pouvez passer l'appel à withZoneSameInstant()
.
Pour convertir en un java.util.Date
, vous pouvez utiliser la classe org.threeten.bp.DateTimeUtils
:
// convert ZonedDateTime to java.util.Date
Date d = DateTimeUtils.toDate(z.toInstant());
Pourriez-vous s'il vous plaît fournir des entrées et des sorties (attendu vs ce que vous obtenez)? –
Est-il correct que votre 'dateFormat' analyse l'entrée en tant que TZ locale? – yegodm
Dans votre modèle de format de date, vous n'avez aucune information dans quel fuseau horaire il sera transmis à votre méthode. Ainsi, la chaîne est analysée car elle est déjà dans le fuseau horaire par défaut. – Damian0o