Convertir une chaîne en objet de calendrier en Java


175

Je suis nouveau sur Java, je travaille généralement avec PHP.

J'essaye de convertir cette chaîne:

Lun 14 mars 16:02:37 GMT 2011

Dans un objet de calendrier afin que je puisse facilement extraire l'année et le mois comme ceci:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

Serait-ce une mauvaise idée de l'analyser manuellement? Vous utilisez une méthode de sous-chaîne?

Tout conseil aiderait merci!


Réponses:


397
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

Remarque: définir Localeselon votre environnement / exigence


Voir également


onlineconversion.com/unix_time.htm . Il s'agit d'un convertisseur d'horodatage en ligne. La valeur qui est calculée par le code java et cette conversion en ligne est différente. Pourquoi?? Pouvez-vous passer par là. Merci :)
Sachin J

6
Notez que cela perd les informations de fuseau horaire. L'objet Calendar aura la TimeZone par défaut du système et non celle analysée.
Cristian Vrabie

Cela ne devrait plus être la réponse principale / acceptée. Puisque Java 8 est déjà sorti depuis plus de 4 ans, la réponse devrait être mise à jour pour être mentionnée java.time. Ce Q / R est assez important sur Google.
Scolytus

18

tl; dr

L'approche moderne utilise les classes java.time .

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011-03

Évitez les anciennes classes date-heure

La manière moderne est d'utiliser les classes java.time. Les anciennes classes de date-heure telles que celles-ci se Calendarsont avérées mal conçues, déroutantes et gênantes.

Définissez un formateur personnalisé pour correspondre à votre entrée de chaîne.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

Analyser comme un fichier ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

Vous êtes intéressé par l'année et le mois. Les classes java.time incluent une YearMonthclasse à cet effet.

YearMonth ym = YearMonth.from( zdt );

Vous pouvez interroger les numéros de l'année et du mois si nécessaire.

int year = ym.getYear();
int month = ym.getMonthValue();

Mais la toStringméthode génère une chaîne au format standard ISO 8601 .

String output = ym.toString();

Mettez tout cela ensemble.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

Dump dans la console.

System.out.println( "input: " + input );
System.out.println( "zdt: " + zdt );
System.out.println( "ym: " + ym );

entrée: Mon Mar 14 16:02:37 GMT 2011

zdt: 2011-03-14T16: 02: 37Z [GMT]

ym: 2011-03

Code en direct

Voir ce code en cours d'exécution dans IdeOne.com .

Conversion

Si vous devez avoir un Calendarobjet, vous pouvez le convertir en un en GregorianCalendarutilisant de nouvelles méthodes ajoutées aux anciennes classes.

GregorianCalendar gc = GregorianCalendar.from( zdt );

À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers java.time.

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

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 futurs ajouts à java.time. Vous trouverez peut - être des classes utiles ici, comme Interval, YearWeek, YearQuarteret plus .


14

Eh bien, je pense que ce serait une mauvaise idée de reproduire le code qui est déjà présent dans des classes comme SimpleDateFormat .

D'un autre côté, personnellement, je suggérerais d'éviter Calendaret Dateentièrement si vous le pouvez, et d'utiliser Joda Time à la place, comme une API de date et d'heure bien mieux conçue. Par exemple, vous devez être conscient que ce SimpleDateFormatn'est pas thread-safe, vous avez donc besoin soit de threads locals, de synchronisation ou d'une nouvelle instance à chaque fois que vous l'utilisez. Les analyseurs et formateurs Joda sont thread-safe.


Merci pour votre contribution, je vais certainement examiner l'utilisation de Joda à l'avenir, il semble que cela puisse être très utile
Doug Molineux

@Jon Skeet Joda ne désérialisera pas sous Android. Joda vaut peu à moins que vous n'ayez pas besoin de sauvegarder les dates et l'heure.
Frank Zappa

@FrankZappa: Je ne suis pas d'accord avec cela - vous pouvez faire tous vos calculs de date / heure dans Joda Time, mais ensuite les convertir en d'autres types (peut-être juste des chaînes pour plus de simplicité) à des fins de sérialisation.
Jon Skeet

Désolé, j'ai dû voter contre, la réponse est trop ancienne, elle est obsolète pour être la réponse la mieux classée. Aujourd'hui, java.timec'est la voie à suivre, Basil Bourque a fourni une excellente réponse.
Scolytus

2
@Scolytus: La meilleure réponse (et acceptée) a 332 votes contre 10 sur celle-ci. Je pense que si vous arrondissez le vote à tous les 7 ans et plus de réponse qui a une meilleure solution maintenant, vous manquerez de votes négatifs ... (Je suis d'accord que la réponse de Basil est bonne, et j'ai voté pour cela.)
Jon Skeet

10

Aucun nouveau calendrier ne doit être créé, SimpleDateFormat utilise déjà un calendrier en dessous.

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(Je ne peux pas encore commenter, c'est pourquoi j'ai créé une nouvelle réponse)


1
Votre solution semble élégante, mais présente deux inconvénients: 1. Le JavaDoc ne garantit pas que le comportement est conforme aux attentes. 2. Au moins pour Java 6, vous trouvez un chemin à la ligne 1353 où l'objet calendrier est cloné. Alors alors! Date.equals (cal.getTime ()).
niels

5

SimpleDateFormatc'est génial, notez simplement que HHc'est différent du hhtravail avec des heures. HHretournera des heures basées sur 24 heures et hh retournera des heures basées sur 12 heures.

Par exemple, ce qui suit renverra 12 heures:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

Bien que cela revienne 24 heures:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

4

Analyser une heure avec le fuseau horaire, Zdans le modèle est pour le fuseau horaire

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

Sortie: il renverra l'heure UTC

1508899140000

entrez la description de l'image ici

Si nous ne définissons pas le fuseau horaire selon un modèle comme yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatutilisera le fuseau horaire défini dansSetting


3

Oui, ce serait une mauvaise pratique de l'analyser vous-même. Jetez un œil à SimpleDateFormat , il transformera la chaîne en une date et vous pourrez définir la date en une instance de calendrier.


1

Méthode simple:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.