web-dev-qa-db-fra.com

Conversion de la date Java en chaîne UTC

La méthode Java.util.DatetoString() affiche la date dans le fuseau horaire local. 

Il existe plusieurs scénarios courants dans lesquels nous souhaitons que les données soient imprimées dans UTC , y compris les journaux, l’exportation de données et la communication avec des programmes externes.

  • Quel est le meilleur moyen de créer une représentation sous forme de chaîne de Java.util.Date en UTC?
  • Comment remplacer le format toString() de j.u.Date, qui ne peut pas être trié (merci, @JonSkeet!), Par un meilleur format?

Addenda

Je pense que la méthode standard pour imprimer la date dans un format personnalisé et dans un fuseau horaire est assez fastidieuse:

final Date date = new Date();
final String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
final SimpleDateFormat sdf = new SimpleDateFormat(ISO_FORMAT);
final TimeZone utc = TimeZone.getTimeZone("UTC");
sdf.setTimeZone(utc);
System.out.println(sdf.format(date));

Je cherchais un one-liner comme:

System.out.println(prettyPrint(date, "yyyy-MM-dd'T'HH:mm:ss.SSS zzz", "UTC"));
28
Adam Matan

Suite aux commentaires utiles, j'ai complètement reconstruit le formateur de date. L'utilisation est supposée:

  • Être court (une doublure)
  • Représenter des objets jetables (fuseau horaire, format) sous forme de chaînes
  • Prend en charge les formats ISO triables et utiles et le format hérité de la boîte

Si vous estimez que ce code est utile, je peux publier le code source et un fichier JAR dans github.

Usage

// The problem - not UTC
Date.toString()                      
"Tue Jul 03 14:54:24 IDT 2012"

// ISO format, now
PrettyDate.now()        
"2012-07-03T11:54:24.256 UTC"

// ISO format, specific date
PrettyDate.toString(new Date())         
"2012-07-03T11:54:24.256 UTC"

// Legacy format, specific date
PrettyDate.toLegacyString(new Date())   
"Tue Jul 03 11:54:24 UTC 2012"

// ISO, specific date and time zone
PrettyDate.toString(moonLandingDate, "yyyy-MM-dd hh:mm:ss zzz", "CST") 
"1969-07-20 03:17:40 CDT"

// Specific format and date
PrettyDate.toString(moonLandingDate, "yyyy-MM-dd")
"1969-07-20"

// ISO, specific date
PrettyDate.toString(moonLandingDate)
"1969-07-20T20:17:40.234 UTC"

// Legacy, specific date
PrettyDate.toLegacyString(moonLandingDate)
"Wed Jul 20 08:17:40 UTC 1969"

Code

(Ce code fait également l'objet d'une une question sur Code Review stackexchange )

import Java.text.SimpleDateFormat;
import Java.util.Date;
import Java.util.TimeZone;

/**
 * Formats dates to sortable UTC strings in compliance with ISO-8601.
 * 
 * @author Adam Matan <[email protected]>
 * @see http://stackoverflow.com/questions/11294307/convert-Java-date-to-utc-string/11294308
 */
public class PrettyDate {
    public static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
    public static String LEGACY_FORMAT = "EEE MMM dd hh:mm:ss zzz yyyy";
    private static final TimeZone utc = TimeZone.getTimeZone("UTC");
    private static final SimpleDateFormat legacyFormatter = new SimpleDateFormat(LEGACY_FORMAT);
    private static final SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT);
    static {
        legacyFormatter.setTimeZone(utc);
        isoFormatter.setTimeZone(utc);
    }

    /**
     * Formats the current time in a sortable ISO-8601 UTC format.
     * 
     * @return Current time in ISO-8601 format, e.g. :
     *         "2012-07-03T07:59:09.206 UTC"
     */
    public static String now() {
        return PrettyDate.toString(new Date());
    }

    /**
     * Formats a given date in a sortable ISO-8601 UTC format.
     * 
     * <pre>
     * <code>
     * final Calendar moonLandingCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
     * moonLandingCalendar.set(1969, 7, 20, 20, 18, 0);
     * final Date moonLandingDate = moonLandingCalendar.getTime();
     * System.out.println("UTCDate.toString moon:       " + PrettyDate.toString(moonLandingDate));
     * >>> UTCDate.toString moon:       1969-08-20T20:18:00.209 UTC
     * </code>
     * </pre>
     * 
     * @param date
     *            Valid Date object.
     * @return The given date in ISO-8601 format.
     * 
     */

    public static String toString(final Date date) {
        return isoFormatter.format(date);
    }

    /**
     * Formats a given date in the standard Java Date.toString(), using UTC
     * instead of locale time zone.
     * 
     * <pre>
     * <code>
     * System.out.println(UTCDate.toLegacyString(new Date()));
     * >>> "Tue Jul 03 07:33:57 UTC 2012"
     * </code>
     * </pre>
     * 
     * @param date
     *            Valid Date object.
     * @return The given date in Legacy Date.toString() format, e.g.
     *         "Tue Jul 03 09:34:17 IDT 2012"
     */
    public static String toLegacyString(final Date date) {
        return legacyFormatter.format(date);
    }

    /**
     * Formats a date in any given format at UTC.
     * 
     * <pre>
     * <code>
     * final Calendar moonLandingCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
     * moonLandingCalendar.set(1969, 7, 20, 20, 17, 40);
     * final Date moonLandingDate = moonLandingCalendar.getTime();
     * PrettyDate.toString(moonLandingDate, "yyyy-MM-dd")
     * >>> "1969-08-20"
     * </code>
     * </pre>
     * 
     * 
     * @param date
     *            Valid Date object.
     * @param format
     *            String representation of the format, e.g. "yyyy-MM-dd"
     * @return The given date formatted in the given format.
     */
    public static String toString(final Date date, final String format) {
        return toString(date, format, "UTC");
    }

    /**
     * Formats a date at any given format String, at any given Timezone String.
     * 
     * 
     * @param date
     *            Valid Date object
     * @param format
     *            String representation of the format, e.g. "yyyy-MM-dd HH:mm"
     * @param timezone
     *            String representation of the time zone, e.g. "CST"
     * @return The formatted date in the given time zone.
     */
    public static String toString(final Date date, final String format, final String timezone) {
        final TimeZone tz = TimeZone.getTimeZone(timezone);
        final SimpleDateFormat formatter = new SimpleDateFormat(format);
        formatter.setTimeZone(tz);
        return formatter.format(date);
    }
}
14
Adam Matan

Java.time

Dans Java 8 et les versions ultérieures, nous avons intégré le nouveau package Java.time ( Tutorial ). Inspiré de Joda-Time, défini par la JSR 310 et étendu par le projet ThreeTen-Extra .

La meilleure solution consiste à trier vos objets date-heure plutôt que les chaînes. Mais si vous devez travailler avec des chaînes, lisez la suite.

Un Instant représente un moment sur la ligne de temps, essentiellement en UTC (voir le document de classe pour des détails plus précis). L'implémentation toString utilise le format DateTimeFormatter.ISO_INSTANT par défaut. Ce format comprend des chiffres de zéro, trois, six ou neuf chiffres, nécessaires pour afficher une précision d’une fraction de seconde à nanosecondes

String output = Instant.now().toString(); // Example: '2015-12-03T10:15:30.120Z'

Si vous devez interagir avec l'ancienne classe Date, convertissez vers/depuis Java.time via de nouvelles méthodes ajoutées aux anciennes classes. Exemple: Date::toInstant.

myJavaUtilDate.toInstant().toString()

Vous pouvez utiliser un autre formateur si vous avez besoin d'un nombre cohérent de chiffres dans la fraction de seconde ou si vous n'avez pas besoin de fraction de seconde.

Une autre route si vous voulez tronquer des fractions de seconde consiste à utiliser ZonedDateTime au lieu de Instant, en appelant sa méthode pour changer la fraction à zéro _. 

Notez que nous devons spécifier un fuseau horaire pour ZonedDateTime (donc le nom). Dans notre cas, cela signifie UTC. La sous-classe de ZoneID , _ { ZoneOffset , contient une convenable constante pour l'heure UTC . Si nous omettons le fuseau horaire, le fuseau horaire par défaut actuel de la machine virtuelle Java est appliqué implicitement.

String output = ZonedDateTime.now( ZoneOffset.UTC ).withNano( 0 ).toString();  // Example: 2015-08-27T19:28:58Z

Joda-Time

UPDATE: Le projet Joda-Time est maintenant en mode maintenance, l'équipe conseillant la migration vers les classes Java.time. 

Je cherchais un one-liner

Facile si vous utilisez la bibliothèque Joda-Time 2.3. ISO 8601 est le formatage par défaut.

Fuseau horaire

Dans l'exemple de code ci-dessous, notez que je spécifie un fuseau horaire plutôt que de dépendre du fuseau horaire par défaut. Dans ce cas, je spécifie UTC par votre question. La variable Z à la fin, appelée "zoulou", signifie qu’aucun fuseau horaire n'est décalé par rapport à UTC.

Exemple de code

// import org.joda.time.*;

String output = new DateTime( DateTimeZone.UTC );

Sortie…

2013-12-12T18:29:50.588Z
26
Basil Bourque

Le code simplifié suivant, basé sur la réponse acceptée ci-dessus , a fonctionné pour moi:

public class GetSync {
    public static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
    private static final TimeZone utc = TimeZone.getTimeZone("UTC");
    private static final SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT);
    static {
        isoFormatter.setTimeZone(utc);
    }

    public static String now() {
        return isoFormatter.format(new Date()).toString();
    }
}

J'espère que cela aide quelqu'un.

6
Vikram

Java.time.Instant

Utilisez simplement Instant of Java.time.

    System.out.println(Instant.now());

Ceci vient d’être imprimé:

2018-01-27T09:35:23.179612Z

Instant.toString donne toujours l'heure UTC.

La sortie est habituellement triable, mais il existe des exceptions malheureuses. toString vous donne suffisamment de groupes de trois décimales pour rendre la précision qu’elle détient. Sur Java 9 sur mon Mac, la précision de Instant.now() semble être de l'ordre de la microseconde, mais nous devrions nous attendre à ce qu'environ un cas sur mille, elle atteindra plusieurs millisecondes et n'imprimera que trois décimales. Les chaînes avec un nombre différent de nombres décimaux seront triées dans le mauvais ordre (sauf si vous écrivez un comparateur personnalisé pour en tenir compte).

Instant est l'une des classes de Java.time, l'API de date et heure moderne de Java, que je vous recommande vivement d'utiliser à la place de la classe Date obsolète. Java.time est intégré à Java 8 et versions ultérieures et a également été rétroporté à Java 6 et 7.

2
Ole V.V.

Si XStream est une dépendance, essayez:

new com.thoughtworks.xstream.converters.basic.DateConverter().toString(date)
1
Jesse Glick

Pourquoi ne pas simplement utiliser Java.text.SimpleDateFormat?

Date someDate = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String s = df.format(someDate);

Ou voir: http://www.tutorialspoint.com/Java/java_date_time.htm

0
Will

Eh bien, si vous voulez utiliser uniquement Java.util.Date, voici un petit truc que vous pouvez utiliser:

String dateString = Long.toString (Date.UTC (date.getYear (), date.getMonth (), date.getDate (), date.getHours (), date.getMinutes (), date.getSeconds ()));

0
Gaurav Arora