Convertir la date / Heure pour un fuseau horaire donné-java


Je veux convertir cet horodatage GMT en GMT + 13:

2011-10-06 03:35:05

J'ai essayé environ 100 combinaisons différentes de DateFormat, TimeZone, Date, GregorianCalendar etc. pour essayer de faire cette tâche TRÈS basique.

Ce code fait ce que je veux pour l'HEURE ACTUELLE:

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

String newZealandTime = formatter.format(calendar.getTime());

Mais ce que je veux, c'est définir l'heure plutôt que d'utiliser l'heure actuelle.

J'ai trouvé que chaque fois que j'essaie de régler l'heure comme ceci:

calendar.setTime(new Date(1317816735000L));

Le fuseau horaire de la machine locale est utilisé. Pourquoi est-ce? Je sachez que lorsque "new Date ()" renvoie UTC+0 heure, alors pourquoi lorsque vous définissez l'heure en millisecondes ne suppose-t-il plus que l'heure est en UTC?

Est possible de:

  1. Définir l'heure sur un objet (Calendrier/Date/Horodatage)
  2. (Éventuellement) Définir le fuseau horaire de l'horodatage initial (calendrier.setTimeZone(...))
  3. Formater l'horodatage avec un nouveau fuseau horaire (formatter.setTimeZone(...)))
  4. Renvoie une chaîne avec un nouveau fuseau horaire. (formateur.format (calendrier.getTime()))

Merci d'avance pour toute aide :D

Author: travega, 2011-10-06

14 answers

Comprendre comment fonctionne le temps de l'ordinateur est très important. Cela dit, je suis d'accord que si une API est créée pour vous aider à traiter le temps de l'ordinateur comme en temps réel, elle devrait fonctionner de manière à vous permettre de le traiter comme en temps réel. Pour la plupart, c'est le cas, mais il y a quelques oublis majeurs qui nécessitent une attention particulière.

De toute façon, je m'égare!! Si vous avez votre décalage UTC (mieux vaut travailler en UTC que les décalages GMT), vous pouvez calculer le temps en millisecondes et l'ajouter à votre timestamp. Notez qu'un horodatage SQL peut varier d'un horodatage Java car la façon dont le temps écoulé depuis l'époque est calculé n'est pas toujours la même - dépend des technologies de base de données et des systèmes d'exploitation.

Je vous conseille d'utiliser System.currentTimeMillis () comme vos horodatages car ceux-ci peuvent être traités de manière plus cohérente en java sans se soucier de convertir les horodatages SQL en objets de date java, etc.

Pour calculer votre décalage, vous pouvez essayer quelque chose comme ceci:

Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;

if (offset != 0L) {
    int multiplier = (offset*60)*(60*1000);
    timezoneAlteredTime = gmtTime + multiplier;
} else {
    timezoneAlteredTime = gmtTime;
}

Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");

formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));

String newZealandTime = formatter.format(calendar.getTime());

J'espère que cela est utile!

 27
Author: Mukul Goel, 2014-09-25 15:53:16

Pour moi, la façon la plus simple de le faire est:

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

//Here you say to java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));    

//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));
 34
Author: Charleston, 2016-10-07 19:11:59

Comme toujours, je recommande de lire cet article sur la date et l'heure en Java afin que vous le compreniez.

L'idée de base est que "sous le capot" tout est fait en millisecondes UTC depuis l'époque. Cela signifie que c'est plus facile si vous utilisez sans utiliser de fuseaux horaires, à l'exception du formatage de chaîne pour l'utilisateur.

Par conséquent, je sauterais la plupart des étapes que vous avez suggérées.

  1. Définir l'heure sur un objet (Date, Calendrier etc).
  2. Définissez le fuseau horaire sur un objet formatter.
  3. Renvoie une chaîne du formateur.

Alternativement, vous pouvez utiliser Joda time. J'ai entendu dire que c'est une API datetime beaucoup plus intuitive.

 20
Author: Bringer128, 2011-10-06 05:03:56

Tl; dr

Si on donne une entrée de 1317816735000L...

Instant.ofEpochMilli( 1_317_816_735_000L )     // Represent a moment in UTC using a count of milliseconds since the epoch reference of 1970-01-01T00:00Z.
.atZone( ZoneId.of( "Pacific/Auckland" ) )     // Adjust from UTC into the wall-clock time used by the people of a certain region (a time zone). Returns a `ZonedDateTime` object.
.format(                 
    DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM )
    .withLocale( new Locale( "en" , "NZ" ) )   // Locale specifies the human language and cultural norms used in localization.
)                                              // Returns a `String` object that represents the value of our `ZonedDateTime` object’s value.

Si on donne une entrée de 2011-10-06 03:35:05...

LocalDateTime.parse(                  // Parse input string lacking any indicator of time zone or offset-from-UTC using the `LocalDateTime` class.
    "2011-10-06 03:35:05"
    .replace( " " , "T" )             // Comply with ISO 8601 standard by replacing SPACE in the middle with a `T`.
)                                     // Returns a `LocalDateTime` object.
.atZone(                              // Adjust from UTC into the wall-clock time used by the people of a certain region (a time zone). Returns a `ZonedDateTime` object.
    ZoneId.of( "Pacific/Auckland" )   // Always specify a time zone by `Continent/Region` name. Never use 3-4 pseudo-time-zones such as `PST`, `CST`, or `IST`.
)                                     // Returns a `ZonedDateTime` object.

Java.temps

La Question et la plupart des réponses utilisent des classes date-heure héritées obsolètes des premières versions de Java. Ces anciennes classes se sont avérées gênantes et déroutantes. Les éviter. Utilisez plutôt le java.les classes de temps.

ISO 8601

Votre chaîne d'entrée est presque au format standard ISO 8601. Il suffit de remplacer l'ESPACE au milieu avec un T.

String input = "2011-10-06 03:35:05".replace( " " , "T" ) ;  // Comply with ISO 8601 standard format by replacing the SPACE with a `T`.

Le java.les classes time utilisent ces formats standard par défaut lors de l'analyse/génération de chaînes. Donc pas besoin de spécifier le format.

LocalDateTime

Maintenant analyser comme un LocalDateTime parce que l'entrée manque d'informations sur le décalage par rapport à l'UTC ou au fuseau horaire. Un LocalDateTime n'a pas de concept de décalage ni de fuseau horaire, donc il ne pas représente un moment réel sur la timeline.

LocalDateTime ldt = LocalDateTime.parse( input );

ZoneOffset

Vous semblez dire que dans le contexte commercial, vous savez que l'intention de cette chaîne est de représenter un moment qui a 13 heures d'avance sur UTC. Nous avons donc instancier un ZoneOffset.

ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.

OffsetDateTime

Appliquer pour obtenir un OffsetDateTime objet. Cela devient un moment réel sur la chronologie.

OffsetDateTime odt = ldt.atOffset( offset);

ZoneId

Mais alors vous mentionnez la Nouvelle-Zélande. Vous aviez donc un fuseau horaire spécifique en tête. Un fuseau horaire est un décalage par rapport à l'UTC plus un ensemble de règles pour traitement des anomalies telles que l'heure d'été (DST). Nous pouvons donc spécifier un ZoneId à un ZonedDateTime plutôt qu'un simple décalage.

Spécifiez unnom de fuseau horaire approprié . N'utilisez jamais l'abréviation de 3-4 lettres telle que EST ou IST car ce ne sont pas de vrais fuseaux horaires, non standardisés et même pas uniques(!). Par exemple, Pacific/Auckland.

ZoneId z = ZoneId.of( "Pacific/Auckland" );

ZonedDateTime

Appliquer le ZoneId.

ZonedDateTime zdt = ldt.atZone( z );

Vous pouvez facilement ajuster dans une autre zone pour le même moment sur le TIMELINE.

ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );  // Same moment in time, but seen through lens of Paris wall-clock time.

Compter de l'époque

Je recommande fortement de ne pas gérer les valeurs date-heure en tant que compte à partir de l'époque, telles que les millisecondes à partir du début de 1970 UTC. Mais si vous devez, créez un Instant à partir d'un tel numéro.

Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );

Attribuez ensuite un fuseau horaire comme vu ci-dessus, si vous le souhaitez, pour vous éloigner de l'UTC.

ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );

Votre valeur de 1_317_816_735_000L est:

  • 2011-10-05T12:12:15Z (Wed, 05 Oct 2011 12:12:15 GMT)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (jeudi 06 octobre 2011 01:12: 15 à Auckland Nouvelle-Zélande).

Générer des chaînes

Pour générer une chaîne au format standard ISO 8601, appelez simplement toString. Notez que ZonedDateTime étend judicieusement le format standard en ajoutant le nom du fuseau horaire entre crochets.

String output = zdt.toString();

Pour d'autres formats, recherchez Stack Overflow pour DateTimeFormatter classe. Déjà couvert plusieurs fois.

Spécifier un FormatStyle et un Locale.

Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );

À propos de java.temps

Le java.temps framework est intégré à Java 8 et versions ultérieures. Ces classes permettent d'éviter la pénible vieux héritage date-heure classes telles que java.util.Date, Calendar, & SimpleDateFormat.

Le Joda-Temps le projet, maintenant en mode de maintenance, conseille la migration vers le java.temps classes.

À en savoir plus, voir le Tutoriel Oracle. Et rechercher Stack Overflow 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. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de classes java.sql.*.

Où obtenir le java.les classes de temps?

Le Trois-Extra le projet étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts futurs à java.temps. Vous pouvez trouver quelques classes utiles ici comme Interval, YearWeek, YearQuarter, et plus.

 7
Author: Basil Bourque, 2018-06-29 19:51:44

J'ai regardé et je ne pense pas qu'il y ait un fuseau horaire en Java qui soit GMT + 13. Je pense donc que vous devez utiliser:

Calendar calendar = Calendar.getInstance();
//OR Calendar.getInstance(TimeZone.getTimeZone("GMT"));

calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13);

Date d = calendar.getTime();

( S'il y a alors changer " GMT " à ce fuseau horaire et supprimer la 2ème ligne de code)

OU

SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));

Si vous souhaitez définir une date, vous pouvez également utiliser:

    calendar.set(Calendar.DATE, 15);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.HOUR_OF_DAY, 13); 
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 00);
 4
Author: Craig, 2011-10-06 10:14:44

La solution est en fait assez simple (Java pur et simple):

System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));

LA SORTIE EST:

 NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05
 4
Author: J S Raggio, 2015-03-09 16:09:58

Joda-Temps

Le java.util.Les classes de date/calendrier sont un gâchis et doivent être évitées.

Mise à jour: Le projet Joda-Time est en mode maintenance. L'équipe conseille la migration vers java.les classes de temps.

Voici votre réponse en utilisant la bibliothèque Joda-Time 2.3. Très facile.

Comme indiqué dans l'exemple de code, je vous suggère d'utiliser des fuseaux horaires nommés dans la mesure du possible afin que votre programmation puisse gérer Heure d'été (DST) et d'autres anomalies.

Si vous avait placé un T dans le milieu de votre chaîne au lieu d'un espace, vous pouvez passer les deux premières lignes de code, en traitant avec un formateur pour analyser la chaîne. Le constructeur DateTime peut prendre une chaîne au format ISO 8601 .

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

// Parse string as a date-time in UTC (no time zone offset).
DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" );
DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" );

// Adjust for 13 hour offset from UTC/GMT.
DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 );
DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen );

// Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" );
DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );

Dump ces valeurs...

System.out.println( "dateTimeInUTC: " + dateTimeInUTC );
System.out.println( "thirteenDateTime: " + thirteenDateTime );
System.out.println( "tongatapuDateTime: " + tongatapuDateTime );

Lors de l'exécution...

dateTimeInUTC: 2011-10-06T03:35:05.000Z
thirteenDateTime: 2011-10-06T16:35:05.000+13:00
tongatapuDateTime: 2011-10-06T16:35:05.000+13:00
 2
Author: Basil Bourque, 2016-09-02 20:46:29

J'ai essayé ce code

try{
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z");
            Date datetime = new Date();

            System.out.println("date "+sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

            System.out.println("GMT "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("GMT+13"));

            System.out.println("GMT+13 "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

            System.out.println("utc "+sdf.format(datetime));

            Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

            DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
            formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

            String newZealandTime = formatter.format(calendar.getTime());

            System.out.println("using calendar "+newZealandTime);

        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Et obtenir ce résultat

date 06-10-2011 10:40:05 +0530
GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05
GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05
utc 06-10-2011 05:10:05 +0000
using calendar 06 Oct 2011 18:10:05 GMT+13:00
 1
Author: Pratik, 2011-10-06 05:13:40

Nous pouvons gérer cela en utilisant la valeur de décalage

 public static long convertDateTimeZone(long lngDate, String fromTimeZone,
        String toTimeZone){
    TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
    Calendar toCal = Calendar.getInstance(toTZ);        

    TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
    Calendar fromCal = Calendar.getInstance(fromTZ);
    fromCal.setTimeInMillis(lngDate);
    toCal.setTimeInMillis(fromCal.getTimeInMillis()
            + toTZ.getOffset(fromCal.getTimeInMillis())
            - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));      
    return toCal.getTimeInMillis();
}

Extrait de code de test:

 System.out.println(new Date().getTime())
 System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
                .getDefault().getID(), "EST"));

Sortie: 1387353270742 1387335270742

 1
Author: DeepaGanesh, 2013-12-18 07:58:16

Nous pouvons obtenir l'horodatage UTC/GMT à partir de la date donnée.

/**
 * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss)
 */
public static long getGMTTimeStampFromDate(String datetime) {
    long timeStamp = 0;
    Date localTime = new Date();

    String format = "dd-MM-yyyy HH:mm:ss";
    SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format);
    sdfLocalFormat.setTimeZone(TimeZone.getDefault());

    try {

        localTime = (Date) sdfLocalFormat.parse(datetime); 

        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
                Locale.getDefault());
        TimeZone tz = cal.getTimeZone();

        cal.setTime(localTime);

        timeStamp = (localTime.getTime()/1000);
        Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime
                + ", GMT TimeStamp : " + localTime.getTime());

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return timeStamp;

}

Il renverra l'heure UTC en fonction de la date passée.

  • Nous pouvons inverser comme l'horodatage UTC à la date et à l'heure actuelles (vice versa)

        public static String getLocalTimeFromGMT(long gmtTimeStamp) {
                 try{
                        Calendar calendar = Calendar.getInstance();
                        TimeZone tz = TimeZone.getDefault();
                        calendar.setTimeInMillis(gmtTimeStamp * 1000);
        //              calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); 
                        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                        Date currenTimeZone = (Date) calendar.getTime();
                        return sdf.format(currenTimeZone);
                    }catch (Exception e) {
                    }
                    return "";  
                }
    

J'espère que cela aidera les autres. Merci!!

 0
Author: jagdish, 2014-12-05 14:46:04

Un moyen rapide est :

String dateText ="Thu, 02 Jul 2015 21:51:46";
long hours = -5; // time difference between places

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH);     
LocalDateTime date = LocalDateTime.parse(dateText, formatter);        
date = date.with(date.plusHours(hours));

System.out.println("NEW DATE: "+date);

Sortie

NOUVELLE DATE: 2015-07-02T16:51:46

 0
Author: Ev., 2015-07-02 22:52:17
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){

    String clientDnT = dt ;// "2017-06-01 07:20:00";
    try{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = sdf.parse(clientDnT);
    TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user
    sdf.setTimeZone(tz);

    // Convert to servertime zone 
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone tzInAmerica = TimeZone.getDefault();
    sdf1.setTimeZone(tzInAmerica);

    // assign date to date
    String serverDate = sdf1.format(date);

    // Convert to servertime zone to Timestamp
    Date date2 =  sdf.parse(serverDate);
    Timestamp tsm = new Timestamp(date2.getTime());
    return  tsm;
    }
    catch(Exception e){
        System.err.println(e);
    }

    return null;
}
 0
Author: Sourav Barman, 2017-06-02 07:27:53

Un moyen facile. Une chose importante à retenir que la date ne maintient pas le fuseau horaire, son seul numéro long millis, tel qu'il a été traité ici.

/**
 * Converts source in GMT+0 to timezone specified by server
 * 
 * @throws IllegalStateException if server timezone wasnt set
 */
public static Date convertGmt(Date source)
{
    if (timeZoneServer == null)
    {
        throw new IllegalStateException("Server timezone wasnt set");
    }

    long rawOffset = timeZoneServer.getRawOffset();

    Date dest = new Date(source.getTime() + rawOffset);

    return dest;
}

/**
 * Converts source in device timezone format to GMT
 */
public static Date convertToGmt(Date source)
{
    int rawOffset = TimeZone.getDefault().getRawOffset();

    Date dest = new Date(source.getTime() - rawOffset);

    return dest;
}

TimezoneServer est quelque chose comme TimeZone timeZoneServer = TimeZone.getTimeZone("GMT+1")

 -1
Author: Serge, 2013-12-11 06:58:30

Votre approche fonctionne sans aucune modification.

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Timestamp for 2011-10-06 03:35:05 GMT
calendar.setTime(new Date(1317872105000L));

DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); 
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));

// Prints 2011-10-06 16:35:05 GMT+13:00
System.out.println(formatter.format(calendar.getTime()));
 -1
Author: augurar, 2016-04-16 09:35:37