J'essaye de créer une chaîne dans un format comme 2015-08-20T08: 26: 21.000Z
au 2015-08-20T08: 26: 21Z
Je sais que cela peut être fait avec certaines techniques de fractionnement de chaîne, mais je me demande s’il existe une solution élégante pour cela (avec un minimum de modifications de code).
Les deux éléments ci-dessus sont des chaînes de temps, la dernière dont j'ai besoin est Date dans ISO 8601. http://tools.ietf.org/html/rfc3339#section-5.6
J'ai essayé quelques questions similaires, telles que convertir une chaîne de date en millisecondes en Java mais elles ne résolvent pas le but recherché.
Aussi essayé d'utiliser:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
Mais il ne fait toujours pas de conversions de chaîne à chaîne. Obtenir l'erreur suivante:
23: 04: 13,829 WARN [RuntimeExceptionMapper] a capturé une exception RuntimeException: {}: Java.lang.IllegalArgumentException: Impossible de formater un objet donné en tant que date
Y a-t-il une bibliothèque que quelqu'un peut suggérer?
Merci.
Instant.parse( "2015-08-20T08:26:21.000Z" )
.toString()
2015-08-20T08: 26: 21Z
Si vous souhaitez uniquement éliminer le .000
, utilisez des objets date-heure pour analyser la valeur de votre chaîne d'entrée, puis générez une nouvelle représentation sous forme de chaîne de cette valeur date-heure dans un format différent.
Soit dit en passant, si tel est votre objectif, le titre de la question n’a aucun sens car les deux chaînes mentionnées dans la première phrase sont valides ISO 8601 chaînes formatées.
2015-08-20T08:26:21.000Z
2015-08-20T08:26:21Z
Java 8 et versions ultérieures ont le nouveau package Java.time . Ces nouvelles classes supplantent les anciennes classes Java.util.Date/.Calendar & Java.text.SimpleDateFormat. Ces anciennes classes étaient déroutantes, gênantes et défectueuses.
Si tout ce que vous voulez, c'est le fuseau horaire UTC, vous pouvez utiliser la classe Instant
. Cette classe représente un point de la timeline sans égard à un fuseau horaire particulier (essentiellement le temps UTC).
DateTimeFormatter.ISO_INSTANT
L’appel d’un toString
d’Instant génère une représentation sous forme de chaîne de la valeur date-heure à l'aide d'une instance DateTimeFormatter.ISO_INSTANT
formatter. Ce formateur est automatiquement flexible sur la fraction de seconde. Si la valeur a une seconde entière, aucune décimale n'est générée (apparemment ce que la Question souhaite). Pendant une fraction de seconde, les chiffres apparaissent par groupes de 3, 6 ou 9, selon les besoins, pour représenter la valeur avec une résolution allant jusqu'à la nanoseconde. Remarque: ce format peut dépasser la limite de millisecondes ISO 8601 (3 décimales).
Voici un exemple de code dans Java 8 Update 51.
String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );
sortie: 2015-08-20T08: 26: 21Z
Passage à une fraction de seconde, .08
String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );
sortie: 2015-08-20T08: 26: 21.080Z
Si vous êtes intéressé par un fuseau horaire autre que UTC, créez un objet ZonedDateTime
à partir de cette Instant
.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;
La conversion d'une date String
de formatage inconnu en une date String
qui utilise un formatage connu peut être effectuée à l'aide de deux objets DateFormat
, l'un configuré de manière dynamique pour analyser le format de la variable String
et l'autre pour générer la sortie formatée String
. Dans votre cas, le formatage String
d'entrée n'est pas spécifié et doit être fourni par l'appelant. Toutefois, le formatage String
de sortie peut être configuré pour utiliser le formatage ISO 8601 sans entrée supplémentaire. Généralement, une sortie de date String
formatée ISO 8601 nécessite deux entrées fournies par l'appelant: une String
contenant la date formatée et une autre String
contenant le format SimpleDateFormat
.
Voici la conversion décrite en tant que code Java (j’ai délibérément omis d’effectuer des contrôles et des validations nuls, ajoutez-les en fonction de votre code):
private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {
final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
final Date inputDate = inputDateFormatter.parse(inputDateAsString);
return iso8601DateFormatter.format(inputDate);
}
Si vous souhaitez modifier cette méthode, veuillez noter que SimpleDateFormat
n'est pas thread-safe et que vous ne devriez pas l'utiliser à partir d'un contexte statique sans solution de contournement pour le code multithread (ThreadLocal
est couramment utilisé pour effectuer une telle solution de contournement pour SimpleDateFormat
) .
Un "gotcha" supplémentaire est l'utilisation d'une Locale
lors de la construction des objets SimpleDateFormat
- ne supprimez pas la configuration Locale
. Il n’est pas prudent d’autoriser le système à choisir d’utiliser la valeur par défaut Locale
car elle est spécifique à l’utilisateur/à la machine. Si vous lui permettez d'utiliser la variable Locale
par défaut, vous courez le risque de rencontrer des bogues transitoires car votre ordinateur de développement utilise une variable Locale
différente de la variable Locale
de votre utilisateur final. Vous n’êtes pas obligé d’utiliser ma sélection anglaise sous Locale
, il est tout à fait correct d’utiliser une langue différente (vous devez comprendre les règles de cette Locale
et modifier le code selon vos besoins). La spécification de Locale
et l'utilisation de la valeur par défaut du système sont incorrectes et risquent de vous faire passer de nombreuses heures frustrantes à tenter de diagnostiquer un bogue évasif.
Veuillez comprendre que cette solution n’est pas idéale à partir de Java 8 et de l’inclusion des classes basées sur JodaTime, telles que Instant
. J'ai choisi de répondre en utilisant des API obsolètes, car c'étaient là ce qui semblait vous préoccuper dans votre question. Si vous utilisez Java 8, je vous conseille vivement d’apprendre et d’utiliser les nouvelles classes car elles constituent une amélioration de presque tous les moyens imaginables.
Votre format n'est pas correct essayez ceci: -
try {
String s = "2015-08-20T08:26:21.000Z";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date d = df.parse(s);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
System.out.println(sdf.format(d));
} catch (ParseException e) {
e.printStackTrace();
}