web-dev-qa-db-fra.com

Comment convertir une date en UTC et supprimer le T et le Z en Java?

Suis en utilisant Java 1.7. 

Essayer de convertir:

2018-05-23T23:18:31.000Z 

dans

2018-05-23 23:18:31

Classe DateUtils:

public class DateUtils {

    public static String convertToNewFormat(String dateStr) throws ParseException {
        TimeZone utc = TimeZone.getTimeZone("UTC");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        sdf.setTimeZone(utc);
        Date convertedDate = sdf.parse(dateStr);
        return convertedDate.toString();
    }
}

En essayant de l'utiliser:

String convertedDate = DateUtils.convertToNewFormat("2018-05-23T23:18:31.000Z");
System.out.println(convertedDate);

Obtenez l'exception suivante:

Exception in thread "main" Java.text.ParseException: Unparseable date: "2018-05-23T23:22:16.000Z"
   at Java.text.DateFormat.parse(DateFormat.Java:366)
   at com.myapp.utils.DateUtils.convertToNewFormat(DateUtils.Java:7)

Qu'est-ce que je fais peut-être mal? 

Existe-t-il un moyen plus simple de faire (par exemple Apache Commons lib)? 

3
PacificNW_Lover

Essaye ça. Vous devez utiliser un modèle pour l'analyse et un autre pour le formatage.

public static String convertToNewFormat(String dateStr) throws ParseException {
    TimeZone utc = TimeZone.getTimeZone("UTC");
    SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sourceFormat.setTimeZone(utc);
    Date convertedDate = sourceFormat.parse(dateStr);
    return destFormat.format(convertedDate);
}
4
jkumaranc

tl; dr

Instant.parse( "2018-05-23T23:18:31.000Z" )                // Parse this String in standard ISO 8601 format as a `Instant`, a point on the timeline in UTC. The `Z` means UTC.
.atOffset( ZoneOffset.UTC )                                // Change from `Instant` to the more flexible `OffsetDateTime`.
.format(                                                   // Generate a String representing the value of this `OffsetDateTime` object.
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )   // Specify a formatting pattern as desired.
)                                                          // Returns a `String` object.

2018-05-23 23:18:31

ISO 8601

Votre chaîne de saisie est au format standard ISO 8601 .

Les classes Java.time utilisent ces formats standard par défaut pour l'analyse/la génération de chaînes.

La T sépare la portion année-mois-jour de l'heure-minute-seconde. La Z est prononcée Zulu et signifie UTC .

Java.time

Vous utilisez d'anciennes classes de date-heure problématiques qui ont été supplantées il y a des années par les classes Java.time. Apache DateUtils n'est également plus nécessaire, car vous trouverez également ses fonctionnalités dans Java.time

Analyser cette chaîne d'entrée en tant qu'objet Instant. La classe Instant représente un moment sur la ligne temporelle en UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale). 

String input = "2018-05-23T23:18:31.000Z" ;
Instant instant = Instant.parse( input ) ;

Pour générer une chaîne dans un autre format, nous avons besoin d'un objet plus flexible. La classe Instant est censée être un bloc de construction de base. Lets convert it to aOffsetDateTime`, en utilisant UTC lui-même comme décalage spécifié par rapport à UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 

Définissez un modèle de formatage correspondant à la sortie souhaitée.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) ;
String output = odt.format( f ) ;

Conseil: Pensez à utiliser les méthodes DateTimeFormatter::ofLocalized… pour localiser automatiquement la génération de chaîne selon une variable Locale plutôt que de coder en dur un modèle de formatage.


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* classes.

Où obtenir les classes Java.time? 

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

4
Basil Bourque

Pour les autres sans restrictions Java 1.7:

Depuis Java 1.8, vous pouvez le faire en utilisant LocalDateTime et ZonedDateTime à partir du paquetage Java.time

public static void main(String[] args) {
    String sourceDateTime           = "2018-05-23T23:18:31.000Z";
    DateTimeFormatter sourceFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    DateTimeFormatter targetFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    LocalDateTime dateTime          = LocalDateTime.parse(sourceDateTime, sourceFormat);
    String formatedDateTime         = dateTime.atZone(ZoneId.of("UTC")).format(targetFormat);
    System.out.println(formatedDateTime);
}

EDIT: (voir Commentaires)

Extrait de la documentation Oracle Java de LocalDateTime :

LocalDateTime est un objet date-heure immuable qui représente un date-heure, souvent vue année-mois-jour-heure-minute-seconde. Autre champs de date et d'heure, tels que jour de l'année, jour de la semaine et semaine, peut également être consulté. Le temps est représenté à la nanoseconde précision. Par exemple, la valeur "2 octobre 2007 à 13: 45.30.123456789" peut être stockée dans un LocalDateTime.

Cette classe ne stocke ni ne représente un fuseau horaire. Au lieu de cela, c'est un description de la date, utilisée pour les anniversaires, combinée avec le heure locale comme on le voit sur une horloge murale. Il ne peut pas représenter un instant sur la ligne temporelle sans informations supplémentaires telles qu'un décalage ou fuseau horaire.

l’opérateur demande à JUST d’analyser une chaîne d’entrée en une date-heure (sous la forme année-mois-jour-heure-minute-seconde) 

LocalDateTime ... représente une date-heure, souvent affichée sous la forme année-mois-jour-heure-minute-seconde

donc aucune information importante n'est perdue ici. Et la partie dateTime.atZone(ZoneId.of("UTC")) renvoie une ZonedDateTime afin que la zone Zime soit à nouveau traitée à ce stade si l'utilisateur doit travailler avec le fuseau horaire ... etc.

alors n'essayez pas de forcer les utilisateurs à utiliser la solution "One and Only" que vous présentez dans votre réponse.

3
Rami.Q

YYYY ne correspond pas à la partie de l'année. En Java 7, vous avez besoin de yyyy.

Pour T, utilisez 'T' pour le faire correspondre

Vous manquez également la faction de millième partie: .SSS

Essaye ça:

String dateStr="2018-05-23T23:18:31.000Z";
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(utc);
Date convertedDate = sdf.parse(dateStr);
convertedDate.toString();