Question Chaîne Java pour la conversion de date


Quelle est la meilleure façon de convertir un String au format «2 janvier 2010» à un Date en Java?

En fin de compte, je veux séparer le mois, le jour et l'année en nombres entiers afin que je puisse utiliser

Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();

convertir la date en temps.


735
2017-11-18 15:53


origine


Réponses:


C'est à la dure, et ceux java.util.Date Les méthodes setter ont été dépréciées depuis Java 1.1 (1997). Formatez simplement la date en utilisant SimpleDateFormat en utilisant un modèle de format correspondant à la chaîne d'entrée.

Dans votre cas spécifique du "2 janvier 2010" comme chaîne de saisie:

  1. "Janvier" est le mois en texte intégral, utilisez donc le MMMM motif pour cela
  2. "2" est le jour du mois court, utilisez le d modèle pour cela.
  3. "2010" est l'année à 4 chiffres, utilisez le yyyy modèle pour cela.

String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010

Notez l'importance de l'explicite Locale argument. Si vous l'omettez, il utilisera le paramètres régionaux par défaut ce qui n'est pas nécessairement l'anglais tel qu'il est utilisé dans le nom du mois de la chaîne d'entrée. Si les paramètres régionaux ne correspondent pas à la chaîne d'entrée, vous obtiendrez java.text.ParseException même si le motif de format semble valide.

Voici un extrait de pertinence de le javadoc, répertoriant tous les formats de format disponibles:

Letter  Date or Time Component  Presentation        Examples
------  ----------------------  ------------------  -------------------------------------
G       Era designator          Text                AD
y       Year                    Year                1996; 96
Y       Week year               Year                2009; 09
M/L     Month in year           Month               July; Jul; 07
w       Week in year            Number              27
W       Week in month           Number              2
D       Day in year             Number              189
d       Day in month            Number              10
F       Day of week in month    Number              2
E       Day in week             Text                Tuesday; Tue
u       Day number of week      Number              1
a       Am/pm marker            Text                PM
H       Hour in day (0-23)      Number              0
k       Hour in day (1-24)      Number              24
K       Hour in am/pm (0-11)    Number              0
h       Hour in am/pm (1-12)    Number              12
m       Minute in hour          Number              30
s       Second in minute        Number              55
S       Millisecond             Number              978
z       Time zone               General time zone   Pacific Standard Time; PST; GMT-08:00
Z       Time zone               RFC 822 time zone   -0800
X       Time zone               ISO 8601 time zone  -08; -0800; -08:00

Notez que les modèles sont sensibles à la casse et que les modèles basés sur du texte de quatre caractères ou plus représentent la forme complète; sinon, un formulaire court ou abrégé est utilisé s'il est disponible. Ainsi, par exemple MMMMM ou plus est inutile.

Voici quelques exemples de valides SimpleDateFormat patterns pour analyser une chaîne donnée à ce jour:

Input string                            Pattern
------------------------------------    ----------------------------
2001.07.04 AD at 12:08:56 PDT           yyyy.MM.dd G 'at' HH:mm:ss z
Wed, Jul 4, '01                         EEE, MMM d, ''yy
12:08 PM                                h:mm a
12 o'clock PM, Pacific Daylight Time    hh 'o''clock' a, zzzz
0:08 PM, PDT                            K:mm a, z
02001.July.04 AD 12:08 PM               yyyyy.MMMM.dd GGG hh:mm aaa
Wed, 4 Jul 2001 12:08:56 -0700          EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700                       yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700            yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00           yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3                              YYYY-'W'ww-u

Une note importante est que SimpleDateFormat est ne pas thread sécurisé. En d'autres termes, vous ne devez jamais le déclarer et l'affecter en tant que variable statique ou instance, puis le réutiliser à partir de différentes méthodes / threads. Vous devriez toujours le créer tout neuf dans la portée locale de la méthode.


Java 8 mise à jour

Si vous êtes sur Java 8 ou plus récent, utilisez DateTimeFormatter (également ici, cliquez sur le lien pour voir tous les formateurs prédéfinis et les modèles de format disponibles; le tutoriel est disponible ici). Cette nouvelle API est inspirée par JodaTime.

String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02

Remarque: si votre modèle de format contient également la partie temps, utilisez LocalDateTime#parse(text, formatter) au lieu de LocalDate#parse(text, formatter). Et, si votre modèle de format contient également le fuseau horaire, utilisez ZonedDateTime#parse(text, formatter) au lieu.

Voici un extrait de pertinence de le javadoc, répertoriant tous les formats de format disponibles:

Symbol  Meaning                     Presentation  Examples
------  --------------------------  ------------  ----------------------------------------------
G       era                         text          AD; Anno Domini; A
u       year                        year          2004; 04
y       year-of-era                 year          2004; 04
D       day-of-year                 number        189
M/L     month-of-year               number/text   7; 07; Jul; July; J
d       day-of-month                number        10

Q/q     quarter-of-year             number/text   3; 03; Q3; 3rd quarter
Y       week-based-year             year          1996; 96
w       week-of-week-based-year     number        27
W       week-of-month               number        4
E       day-of-week                 text          Tue; Tuesday; T
e/c     localized day-of-week       number/text   2; 02; Tue; Tuesday; T
F       week-of-month               number        3

a       am-pm-of-day                text          PM
h       clock-hour-of-am-pm (1-12)  number        12
K       hour-of-am-pm (0-11)        number        0
k       clock-hour-of-am-pm (1-24)  number        0

H       hour-of-day (0-23)          number        0
m       minute-of-hour              number        30
s       second-of-minute            number        55
S       fraction-of-second          fraction      978
A       milli-of-day                number        1234
n       nano-of-second              number        987654321
N       nano-of-day                 number        1234000000

V       time-zone ID                zone-id       America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name     Pacific Standard Time; PST
O       localized zone-offset       offset-O      GMT+8; GMT+08:00; UTC-08:00;
X       zone-offset 'Z' for zero    offset-X      Z; -08; -0830; -08:30; -083015; -08:30:15;
x       zone-offset                 offset-x      +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z       zone-offset                 offset-Z      +0000; -0800; -08:00;

Notez qu'il a plusieurs formateurs prédéfinis pour les modèles les plus populaires. Donc, au lieu de DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);, tu pourrais utiliser DateTimeFormatter.RFC_1123_DATE_TIME. C'est possible parce qu'ils sont, au contraire, SimpleDateFormat, thread sécurisé. Vous pouvez donc aussi définir le vôtre, si nécessaire.

Pour un format de chaîne d'entrée particulier, vous n'avez pas besoin d'utiliser un format explicite DateTimeFormatter: une référence ISO 8601 date, comme 2016-09-26T17: 44: 57Z, peut être analysé directement avec LocalDateTime#parse(text) comme il utilise déjà le ISO_LOCAL_DATE_TIME formateur. De même, LocalDate#parse(text) analyse une date ISO sans le composant heure (voir ISO_LOCAL_DATE), et ZonedDateTime#parse(text) analyse une date ISO avec un décalage et un fuseau horaire ajoutés (voir ISO_ZONED_DATE_TIME).


1411
2017-11-18 15:55



Ah oui la discussion Java Date, encore une fois. Pour faire face à la manipulation de la date, nous utilisons Rendez-vous amoureux, Calendrier, Calendrier Grégorien, et SimpleDateFormat. Par exemple en utilisant votre date de janvier comme entrée:

Calendar mydate = new GregorianCalendar();
String mystring = "January 2, 2010";
Date thedate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(mystring);
mydate.setTime(thedate);
//breakdown
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

Ensuite, vous pouvez manipuler cela avec quelque chose comme:

Calendar now = Calendar.getInstance();
mydate.set(Calendar.YEAR,2009);
mydate.set(Calendar.MONTH,Calendar.FEBRUARY);
mydate.set(Calendar.DAY_OF_MONTH,25);
mydate.set(Calendar.HOUR_OF_DAY,now.get(Calendar.HOUR_OF_DAY));
mydate.set(Calendar.MINUTE,now.get(Calendar.MINUTE));
mydate.set(Calendar.SECOND,now.get(Calendar.SECOND));
// or with one statement
//mydate.set(2009, Calendar.FEBRUARY, 25, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

62
2017-11-19 03:27



String str_date = "11-June-07";
DateFormat formatter;
Date date;
formatter = new SimpleDateFormat("dd-MMM-yy");
date = formatter.parse(str_date);

36
2018-01-15 07:02



Avec Java 8, nous obtenons une nouvelle API Date / Heure (JSR 310).

La manière suivante peut être utilisée pour analyser la date dans Java 8 sans compter sur Joda-Time:

String str = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(str, formatter);

// access date fields
int year = date.getYear(); // 2010
int day = date.getDayOfMonth(); // 2
Month month = date.getMonth(); // JANUARY
int monthAsInt = month.getValue(); // 1

LocalDate est la classe Java 8 standard pour représenter une date (sans temps). Si vous voulez analyser des valeurs contenant des informations de date et d'heure, utilisez LocalDateTime. Pour les valeurs avec l'utilisation des fuseaux horaires ZonedDateTime. Les deux fournissent un parse() méthode similaire à LocalDate:

LocalDateTime dateWithTime = LocalDateTime.parse(strWithDateAndTime, dateTimeFormatter);
ZonedDateTime zoned = ZonedDateTime.parse(strWithTimeZone, zoneFormatter);

La liste des caractères de formatage Javadoc de DateTimeFormatter:

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. 
The following pattern letters are defined:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
 G       era                         text              AD; Anno Domini; A
 u       year                        year              2004; 04
 y       year-of-era                 year              2004; 04
 D       day-of-year                 number            189
 M/L     month-of-year               number/text       7; 07; Jul; July; J
 d       day-of-month                number            10

 Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
 Y       week-based-year             year              1996; 96
 w       week-of-week-based-year     number            27
 W       week-of-month               number            4
 E       day-of-week                 text              Tue; Tuesday; T
 e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
 F       week-of-month               number            3

 a       am-pm-of-day                text              PM
 h       clock-hour-of-am-pm (1-12)  number            12
 K       hour-of-am-pm (0-11)        number            0
 k       clock-hour-of-am-pm (1-24)  number            0

 H       hour-of-day (0-23)          number            0
 m       minute-of-hour              number            30
 s       second-of-minute            number            55
 S       fraction-of-second          fraction          978
 A       milli-of-day                number            1234
 n       nano-of-second              number            987654321
 N       nano-of-day                 number            1234000000

 V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 z       time-zone name              zone-name         Pacific Standard Time; PST
 O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
 X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

29
2018-03-04 18:56



Bien que certaines réponses soient techniquement correctes, elles ne sont pas recommandables.

  • Les classes java.util.Date et Calendar sont notoirement gênantes. En raison de défauts dans la conception et la mise en œuvre, évitez-les. Heureusement, nous avons le choix entre deux autres excellentes bibliothèques de date-heure:
    • Joda-Time
      Cette librairie populaire gratuite et open-source peut être utilisée sur plusieurs versions de Java. De nombreux exemples de son utilisation peuvent être trouvés sur StackOverflow. La lecture de certaines d'entre elles vous aidera à vous mettre au courant rapidement.
    • java.time. * package
      Ce nouvel ensemble de classes est inspiré de Joda-Time et défini par JSR 310. Ces classes sont construites dans Java 8. Un projet est en cours pour rétrograder ces classes vers Java 7, mais ce backport n'est pas supporté par Oracle.
  • Comme Kristopher Johnson l'a justement noté dans son commentaire sur la question, les autres réponses ignorent les questions vitales de:
    • Moment de la journée
      La date comporte à la fois une partie date et une partie heure-du-jour)
    • Fuseau horaire
      Le début d'une journée dépend du fuseau horaire. Si vous ne spécifiez pas de fuseau horaire, le fuseau horaire par défaut de la JVM est appliqué. Cela signifie que le comportement de votre code peut changer lorsqu'il est exécuté sur d'autres ordinateurs ou avec un paramètre de fuseau horaire modifié. Probablement pas ce que tu veux.
    • Lieu
      Le langage Locale spécifie comment interpréter les mots (nom du mois et du jour) rencontrés lors de l'analyse. (Le réponse de BalusC gère cela correctement.) En outre, les paramètres régionaux affecte la sortie de certains formateurs lors de la génération d'une représentation sous forme de chaîne de votre date-heure.

Joda-Time

Quelques notes sur Joda-Time suivent.

Fuseau horaire

Dans Joda-Time, une DateTime L'objet connaît vraiment son propre fuseau horaire. Cela contraste la classe java.util.Date qui semble avoir un fuseau horaire mais pas.

Notez dans l'exemple de code ci-dessous comment nous passons un objet de fuseau horaire au formateur qui analyse la chaîne. Ce fuseau horaire est utilisé pour interpréter cette date-heure comme ayant eu lieu dans ce fuseau horaire. Vous devez donc réfléchir et déterminer le fuseau horaire représenté par cette entrée de chaîne.

Puisque vous n'avez pas de portion de temps dans votre chaîne de saisie, Joda-Time affecte le premier moment du jour du fuseau horaire spécifié comme étant l'heure du jour. Habituellement, cela signifie 00:00:00 mais pas toujours, à cause de Heure d'été (DST) ou d'autres anomalies. Par ailleurs, vous pouvez faire la même chose à n'importe quelle instance de DateTime en appelant withTimeAtStartOfDay.

Formatter Format

Les caractères utilisés dans le modèle d'un formateur sont similaires dans Joda-Time à ceux de java.util.Date/Calendar mais pas exactement les mêmes. Lisez attentivement le document.

Immutabilité

Nous utilisons généralement les classes immuables dans Joda-Time. Plutôt que de modifier un objet date-heure existant, nous appelons des méthodes qui créent une nouvelle instance basée sur l'autre objet avec la plupart des aspects copiés sauf si des modifications étaient souhaitées. Un exemple est l'appel à withZone en dernière ligne ci-dessous. Immutabilité aide à rendre Joda-Time très sûr pour les threads, et peut également rendre certains travaux plus clairs.

Conversion

Vous aurez besoin d'objets java.util.Date à utiliser avec d'autres classes / frameworks qui ne connaissent pas les objets Joda-Time. Heureusement, il est très facile de faire des allers-retours.

À partir d'un objet java.util.Date (nommé ici date) à Joda-Time DateTime ...

org.joda.time.DateTime dateTime = new DateTime( date, timeZone );

Aller dans l'autre sens de Joda-Time à un objet java.util.Date ...

java.util.Date date = dateTime.toDate();

Exemple de code

String input = "January 2, 2010";

java.util.Locale locale = java.util.Locale.US;
DateTimeZone timeZone = DateTimeZone.forID( "Pacific/Honolulu" ); // Arbitrarily chosen for example.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMMM d, yyyy" ).withZone( timeZone ).withLocale( locale );
DateTime dateTime = formatter.parseDateTime( input );

System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime in UTC/GMT: " + dateTime.withZone( DateTimeZone.UTC ) );

Quand couru ...

dateTime: 2010-01-02T00:00:00.000-10:00
dateTime in UTC/GMT: 2010-01-02T10:00:00.000Z

20
2018-02-13 08:22



Lors du traitement de la classe SimpleDateFormat, il est important de se rappeler que Date n'est pas adaptée aux threads et que vous ne pouvez pas partager un même objet Date avec plusieurs threads.

Il y a aussi une grande différence entre "m" et "M" où un petit cas est utilisé pour des minutes et un cas de majuscule est utilisé pour un mois. La même chose avec "d" et "D". Cela peut causer des bugs subtils qui sont souvent négligés. Voir Javadoc ou Guide pour convertir la chaîne à jour en Java pour plus de détails.


16
2017-12-02 01:48



    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date date;
    try {
        date = dateFormat.parse("2013-12-4");
        System.out.println(date.toString()); // Wed Dec 04 00:00:00 CST 2013

        String output = dateFormat.format(date);
        System.out.println(output); // 2013-12-04
    } 
    catch (ParseException e) {
        e.printStackTrace();
    }

Ça fonctionne bien pour moi.


13
2017-12-04 12:46



En outre, SimpleDateFormat n'est pas disponible avec certaines technologies côté client, comme GWT.

C'est une bonne idée d'aller pour Calendar.getInstance (), et votre exigence est de comparer deux dates; aller pour une longue date.


5
2017-12-10 16:16



Deux simples formateurs que nous avons utilisés:

  1. Quelle date de format voulons-nous?
  2. Quelle date de format est réellement présente?

Nous analysons le format complet de la date à l'heure:

date="2016-05-06 16:40:32";

public static String setDateParsing(String date) throws ParseException {

    // This is the format date we want
    DateFormat mSDF = new SimpleDateFormat("hh:mm a");

    // This format date is actually present
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-mm-dd hh:mm");
    return mSDF.format(formatter.parse(date));
}

5
2018-05-06 10:12