Lorsque je crée un nouvel objet Date
, il est initialisé à l'heure actuelle, mais dans le fuseau horaire local. Comment puis-je obtenir la date et l'heure actuelles en GMT?
Java.util.Date
n'a pas de fuseau horaire spécifique, bien que sa valeur soit le plus souvent considérée par rapport à l'UTC. Qu'est-ce qui te fait penser que c'est en heure locale?
Pour être précis: la valeur entre Java.util.Date
est le nombre de millisecondes écoulées depuis l’époque Unix, qui s’est produite à minuit le 1er janvier 1970, UTC. La même époque pourrait également être décrite dans d'autres fuseaux horaires, mais la description traditionnelle est exprimée en UTC. Comme il s’agit d’un nombre de millisecondes depuis une époque fixe, la valeur dans Java.util.Date
est identique dans le monde entier à tout moment, quel que soit le fuseau horaire local.
Je suppose que le problème est que vous l'affichez via une instance de Calendar qui utilise le fuseau horaire local, ou éventuellement avec Date.toString()
qui utilise également le fuseau horaire local, ou une instance SimpleDateFormat
, qui utilise également par défaut le fuseau horaire local.
Si ce n'est pas le problème, postez un exemple de code.
Je recommanderais cependant que vous utilisiez Joda-Time anyway, qui offre une API beaucoup plus claire.
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
Instant.now() // Capture the current moment in UTC.
Générez une chaîne pour représenter cette valeur:
Instant.now().toString()
2016-09-13T23: 30: 52.123Z
Comme la réponse correcte de Jon Skeet a déclaré, un objet Java.util.Date a le fuseau horaire no†. Cependant, son implémentation toString
applique le fuseau horaire par défaut de la machine virtuelle lors de la génération de la représentation sous forme de chaîne de cette valeur date-heure. De manière confuse pour le programmeur naïf, une Date semble avoir un fuseau horaire mais ne l’a pas.
Les classes Java.util.Date
, j.u.Calendar
et Java.text.SimpleDateFormat
fournies avec Java sont notoirement gênantes. Évite-les. Utilisez plutôt l'une de ces bibliothèques date-heure compétentes:
Java 8 apporte un excellent nouveau package Java.time. *) Pour supplanter les anciennes classes Java.util.Date/Calendar.
Obtenir l'heure actuelle en UTC/GMT est un simple vol…
Instant instant = Instant.now();
Cette classe { Instant
_ est le bloc de construction de base de Java.time, représentant un moment sur la timeline dans UTC avec une résolution de nanosecondes .
En Java 8, le moment actuel est capturé avec une résolution ne dépassant pas quelques millisecondes. (Java 9 apporte une nouvelle implémentation) de Clock
capture le moment actuel jusqu'à la capacité maximale de la nanoseconde de cette classe, en fonction de la capacité du matériel d'horloge de votre ordinateur hôte.
C'est la méthode toString
qui génère une représentation sous forme de chaîne de sa valeur en utilisant un format ISO 8601 spécifique . Ce format génère zéro, trois, six ou neuf chiffres comme suit: millisecondes , microsecondes ou nanosecondes ) pour représenter la fraction de seconde.
Si vous souhaitez une mise en forme plus souple ou d’autres fonctionnalités supplémentaires, appliquez un décalage de 0 par rapport à l’UTC, pour l’heure UTC proprement dite ( ZoneOffset.UTC
constante ) pour obtenir un OffsetDateTime
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );
Décharger pour consoler…
System.out.println( "now: " + now );
Quand couru…
now: 2014-01-21T23:42:03.522Z
Les classes Java.time sont définies par JSR 310 . Ils ont été inspirés par Joda-Time mais ont été entièrement restructurés.
UPDATE: Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .
En utilisant la Joda-Time librairie gratuite à source ouverte tierce, vous pouvez obtenir la date et l'heure actuelles dans une seule ligne de code.
Joda-Time a inspiré les nouvelles classes Java.time. * De Java 8, mais présente une architecture différente. Vous pouvez utiliser Joda-Time dans les anciennes versions de Java. Joda-Time continue de fonctionner en Java 8 et continue d'être activement maintenu (à partir de 2014). Cependant, l'équipe Joda-Time recommande la migration vers Java.time.
System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );
Exemple de code plus détaillé (Joda-Time 2.3)…
org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );
Décharger pour consoler…
System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );
Quand couru…
Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z
Pour plus d’exemples de code effectuant un travail de fuseau horaire, voir ma réponse à une question similaire.
Je vous recommande de toujours spécifier un fuseau horaire plutôt que de vous appuyer implicitement sur le fuseau horaire par défaut actuel de la JVM (qui peut changer à tout moment!). Une telle confiance semble être une cause fréquente de confusion et de bugs dans le travail de date-heure.
Lorsque vous appelez now()
, transmettez le fuseau horaire souhaité/attendu à attribuer. Utilisez la classe DateTimeZone
.
DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );
Cette classe contient un fuseau horaire constant pour UTC .
DateTime now = DateTime.now( DateTimeZone.UTC );
Si vous voulez vraiment utiliser le fuseau horaire par défaut de la machine virtuelle Java, passez un appel explicite afin que votre code soit auto-documenté.
DateTimeZone zoneDefault = DateTimeZone.getDefault();
Lisez à propos des formats ISO 8601 . Java.time et Joda-Time utilisent tous deux les formats sensibles de cette norme comme valeurs par défaut pour l’analyse et la génération de chaînes.
† En fait, Java.util.Date a-t-il un fuseau horaire enfoui profondément sous des couches de code source. Dans la plupart des cas, ce fuseau horaire est ignoré. En bref, nous disons que Java.util.Date n'a pas de fuseau horaire. De plus, ce fuseau horaire enterré est pas celui utilisé par la méthode toString
de Date; cette méthode utilise le fuseau horaire actuel par défaut de la machine virtuelle Java. Raison de plus pour éviter cette classe déroutante et rester avec Joda-Time et Java.time.
Ceci retourne définitivement l'heure UTC: sous forme d'objets String et Date!
static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static Date getUTCdatetimeAsDate() {
// note: doesn't check for null
return stringDateToDate(getUTCdatetimeAsString());
}
public static String getUTCdatetimeAsString() {
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
final String utcTime = sdf.format(new Date());
return utcTime;
}
public static Date stringDateToDate(String StrDate) {
Date dateToReturn = null;
SimpleDateFormat dateFormat = new SimpleDateFormat(DATEFORMAT);
try {
dateToReturn = (Date)dateFormat.parse(StrDate);
}
catch (ParseException e) {
e.printStackTrace();
}
return dateToReturn;
}
Calendar c = Calendar.getInstance();
System.out.println("current: "+c.getTime());
TimeZone z = c.getTimeZone();
int offset = z.getRawOffset();
if(z.inDaylightTime(new Date())){
offset = offset + z.getDSTSavings();
}
int offsetHrs = offset / 1000 / 60 / 60;
int offsetMins = offset / 1000 / 60 % 60;
System.out.println("offset: " + offsetHrs);
System.out.println("offset: " + offsetMins);
c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
c.add(Calendar.MINUTE, (-offsetMins));
System.out.println("GMT Time: "+c.getTime());
En fait, pas le temps, mais sa représentation pourrait être modifiée.
SimpleDateFormat f = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));
Le temps est le même en tout point de la Terre, mais notre perception du temps peut être différente selon les endroits.
Ce code imprime l'heure actuelle UTC.
import Java.text.ParseException;
import Java.text.SimpleDateFormat;
import Java.util.Date;
import Java.util.TimeZone;
public class Test
{
public static void main(final String[] args) throws ParseException
{
final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));
}
}
Résultat
2013-10-26 14:37:48 UTC
Calendrier aGMTCalendar = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); ;__. Ensuite, toutes les opérations effectuées à l'aide de l'objet aGMTCalendar seront effectuées avec le fuseau horaire GMT et ne seront pas appliquées à l'heure d'été ni aux décalages fixes.
Faux!
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
aGMTCalendar.getTime(); //or getTimeInMillis()
et
Calendar aNotGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));aNotGMTCalendar.getTime();
reviendra le même temps. Idem pour
new Date(); //it's not GMT.
Cela fonctionne pour obtenir des millisecondes UTC dans Android.
Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;
Jon Skeet demande:
@Downvoter: Vous voulez commenter? Qu'est-ce qui est inexact dans ma réponse? – Jon Skeet 26 octobre 09 à 21:09
Je ne suis pas le votant inférieur, mais voici ce qui semble être incorrect dans cette réponse. Tu as dit:
Java.util.Date
est toujours en UTC. Qu'est-ce qui vous fait penser que c'est en local temps? Je soupçonne que le problème est que vous l'affichez via un instance de calendrier qui utilise le fuseau horaire local, ou éventuellement,Date.toString()
qui utilise également le fuseau horaire local.
Cependant, le code:
System.out.println(new Java.util.Date().getHours() + " hours");
donne les heures locales, pas l'heure GMT (heures UTC), en n'utilisant aucun Calendar
et aucun SimpleDateFormat
du tout.
C'est pourquoi il semble que quelque chose est incorrect.
En rassemblant les réponses, le code:
System.out.println(Calendar.getInstance(TimeZone.getTimeZone("GMT"))
.get(Calendar.HOUR_OF_DAY) + " Hours");
affiche les heures GMT au lieu des heures locales - notez que getTime.getHours()
est manquant car cela créerait un objet Date()
, qui stocke théoriquement la date dans GMT, mais renvoie les heures dans le fuseau horaire local.
Si vous voulez un objet Date avec des champs modifiés pour UTC, vous pouvez le faire comme ceci avec Joda Time :
import org.joda.time.DateTimeZone;
import Java.util.Date;
...
Date local = new Date();
System.out.println("Local: " + local);
DateTimeZone zone = DateTimeZone.getDefault();
long utc = zone.convertLocalToUTC(local.getTime(), false);
System.out.println("UTC: " + new Date(utc));
Vous pouvez directement utiliser ceci
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));
Vous pouvez utiliser:
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Ensuite, toutes les opérations effectuées à l'aide de l'objet aGMTCalendar seront effectuées avec le fuseau horaire GMT et ne seront pas appliquées à l'heure avancée ou aux décalages fixes. Je pense que l'affiche précédente indique correctement que l'objet Date () renvoie toujours une heure GMT. Ce n'est que lorsque vous effectuez une opération avec l'objet Date que celui-ci est converti au fuseau horaire local.
Voici une autre suggestion pour obtenir un objet Horodatage GMT:
import Java.sql.Timestamp;
import Java.util.Calendar;
...
private static Timestamp getGMT() {
Calendar cal = Calendar.getInstance();
return new Timestamp(cal.getTimeInMillis()
-cal.get(Calendar.ZONE_OFFSET)
-cal.get(Calendar.DST_OFFSET));
}
Voici un autre moyen d'obtenir l'heure GMT au format String
String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z" ;
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String dateTimeString = sdf.format(new Date());
Avec:
Calendar cal = Calendar.getInstance();
Alors cal
ont la date et l'heure actuelles.
Vous pouvez également obtenir la date et l’heure actuelles du fuseau horaire avec:
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));
Vous pouvez demander à cal.get(Calendar.DATE);
ou à une autre constante du calendrier de vous renseigner sur les autres détails.
La date et l’horodatage sont obsolètes en Java. La classe de calendrier ce n'est pas.
Conversion de l'heure actuelle en heure UTC:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
DateTimeZone dateTimeZone = DateTimeZone.getDefault(); //Default Time Zone
DateTime currDateTime = new DateTime(); //Current DateTime
long utcTime = dateTimeZone.convertLocalToUTC(currDateTime .getMillis(), false);
String currTime = formatter.print(utcTime); //UTC time converted to string from long in format of formatter
currDateTime = formatter.parseDateTime(currTime); //Converted to DateTime in UTC
Pour simplifier les choses, pour créer une Date
dans UTC
, vous pouvez utiliser Calendar
:
Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Ce qui construira une nouvelle instance pour Calendar
en utilisant "UTC" TimeZone
.
Si vous avez besoin d'un objet Date
de ce calendrier, vous pouvez simplement utiliser getTime()
.
Exemple de code pour afficher l'heure système dans un fuseau horaire et un format spécifiques.
import Java.text.SimpleDateFormat;
import Java.util.Calendar;
import Java.util.Date;
import Java.util.TimeZone;
public class TimZoneTest {
public static void main (String[] args){
//<GMT><+/-><hour>:<minutes>
// Any screw up in this format, timezone defaults to GMT QUIETLY. So test your format a few times.
System.out.println(my_time_in("GMT-5:00", "MM/dd/yyyy HH:mm:ss") );
System.out.println(my_time_in("GMT+5:30", "'at' HH:mm a z 'on' MM/dd/yyyy"));
System.out.println("---------------------------------------------");
// Alternate format
System.out.println(my_time_in("America/Los_Angeles", "'at' HH:mm a z 'on' MM/dd/yyyy") );
System.out.println(my_time_in("America/Buenos_Aires", "'at' HH:mm a z 'on' MM/dd/yyyy") );
}
public static String my_time_in(String target_time_zone, String format){
TimeZone tz = TimeZone.getTimeZone(target_time_zone);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat date_format_gmt = new SimpleDateFormat(format);
date_format_gmt.setTimeZone(tz);
return date_format_gmt.format(date);
}
}
Sortie
10/08/2011 21:07:21
at 07:37 AM GMT+05:30 on 10/09/2011
at 19:07 PM PDT on 10/08/2011
at 23:07 PM ART on 10/08/2011
Voici mon implémentation de toUTC:
public static Date toUTC(Date date){
long datems = date.getTime();
long timezoneoffset = TimeZone.getDefault().getOffset(datems);
datems -= timezoneoffset;
return new Date(datems);
}
Il y a probablement plusieurs façons de l'améliorer, mais cela fonctionne pour moi.
public static void main(String args[]){
LocalDate date=LocalDate.now();
System.out.println("Current date = "+date);
}
Cela a fonctionné pour moi, renvoie l'horodatage à GMT!
Date currDate;
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
long currTime = 0;
try {
currDate = dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
currTime = currDate.getTime();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Si vous voulez éviter d'analyser la date et que vous voulez juste un horodatage dans GMT, vous pouvez utiliser:
final Date gmt = new Timestamp(System.currentTimeMillis()
- Calendar.getInstance().getTimeZone()
.getOffset(System.currentTimeMillis()));
Utilisez cette classe pour obtenir l'heure UTC correcte d'un serveur en ligne NTP:
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Java.net.InetAddress;
class NTP_UTC_Time
{
private static final String TAG = "SntpClient";
private static final int RECEIVE_TIME_OFFSET = 32;
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;
private static final int NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_VERSION = 3;
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
// 70 years plus 17 leap days
private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
private long mNtpTime;
public boolean requestTime(String Host, int timeout) {
try {
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(timeout);
InetAddress address = InetAddress.getByName(Host);
byte[] buffer = new byte[NTP_PACKET_SIZE];
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
socket.send(request);
// read the response
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
socket.close();
mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
} catch (Exception e) {
// if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
return false;
}
return true;
}
public long getNtpTime() {
return mNtpTime;
}
/**
* Reads an unsigned 32 bit big endian number from the given offset in the buffer.
*/
private long read32(byte[] buffer, int offset) {
byte b0 = buffer[offset];
byte b1 = buffer[offset+1];
byte b2 = buffer[offset+2];
byte b3 = buffer[offset+3];
// convert signed bytes to unsigned values
int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
}
/**
* Reads the NTP time stamp at the given offset in the buffer and returns
* it as a system time (milliseconds since January 1, 1970).
*/
private long readTimeStamp(byte[] buffer, int offset) {
long seconds = read32(buffer, offset);
long fraction = read32(buffer, offset + 4);
return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);
}
/**
* Writes 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
*/
private void writeTimeStamp(byte[] buffer, int offset) {
int ofs = offset++;
for (int i=ofs;i<(ofs+8);i++)
buffer[i] = (byte)(0);
}
}
Et utilisez-le avec:
long now = 0;
NTP_UTC_Time client = new NTP_UTC_Time();
if (client.requestTime("pool.ntp.org", 2000)) {
now = client.getNtpTime();
}
Si vous avez besoin de l'heure UTC "maintenant" en tant que fonction d'utilisation DateTimeString:
private String get_UTC_Datetime_from_timestamp(long timeStamp){
try{
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();
int tzt = tz.getOffset(System.currentTimeMillis());
timeStamp -= tzt;
// DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
DateFormat sdf = new SimpleDateFormat();
Date netDate = (new Date(timeStamp));
return sdf.format(netDate);
}
catch(Exception ex){
return "";
}
}
et l'utiliser avec:
String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);
Pour faire simple. Un objet de calendrier stocke des informations sur le fuseau horaire, mais lorsque vous exécutez cal.getTime (), les informations de fuseau horaire seront perdues. Donc, pour les conversions de fuseaux horaires, je vous conseillerai d'utiliser les classes DateFormat ...
c'est ma mise en œuvre:
public static String GetCurrentTimeStamp()
{
Calendar cal=Calendar.getInstance();
long offset = cal.getTimeZone().getOffset(System.currentTimeMillis());//if you want in UTC else remove it .
return new Java.sql.Timestamp(System.currentTimeMillis()+offset).toString();
}
public class CurrentUtcDate
{
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC Time is: " + dateFormat.format(date));
}
}
Sortie:
UTC Time is: 22-01-2018 13:14:35
Vous pouvez modifier le format de la date si nécessaire.
Si vous utilisez l'heure joda et que vous voulez l'heure actuelle en millisecondes sans votre décalage local vous pouvez utiliser ceci:
long instant = DateTimeZone.UTC.getMillisKeepLocal(DateTimeZone.getDefault(), System.currentTimeMillis());
Date actuelle en UTC
Instant.now().toString().replaceAll("T.*", "");