Converti stringa in oggetto calendario in Java


175

Sono nuovo di Java, di solito lavoro con PHP.

Sto cercando di convertire questa stringa:

Lun 14 Mar 16:02:37 GMT 2011

In un oggetto calendario in modo che io possa facilmente tirare l'anno e il mese in questo modo:

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

Sarebbe una cattiva idea analizzarlo manualmente? Usando un metodo di sottostringa?

Qualsiasi consiglio aiuterebbe grazie!


Risposte:


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

nota: impostare in Localebase al proprio ambiente / requisito


Guarda anche


onlineconversion.com/unix_time.htm . Questo è un convertitore di data e ora online. Il valore che viene calcolato dal codice Java e questa conversione online diventa diverso. Perché?? Puoi passare attraverso questo. Grazie :)
Sachin J

6
Si noti che questo perde le informazioni sul fuso orario. L'oggetto Calendar avrà il TimeZone predefinito di sistema e non quello analizzato.
Cristian Vrabie,

Questa non dovrebbe più essere la risposta migliore / accettata. Poiché Java 8 è già in circolazione da più di 4 anni, la risposta dovrebbe essere aggiornata per menzionarla java.time. Questo Q / A risulta abbastanza importante su Google.
Scolytus,

18

tl; dr

L'approccio moderno utilizza le classi 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

Evita le classi di data e ora legacy

Il modo moderno è con le classi java.time. Le vecchie classi di data e ora come si Calendarsono dimostrate mal progettate, confuse e problematiche.

Definire un formattatore personalizzato in modo che corrisponda all'input della stringa.

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

Analizza come a ZonedDateTime.

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

Sei interessato all'anno e al mese. Le classi java.time includono la YearMonthclasse a tale scopo.

YearMonth ym = YearMonth.from( zdt );

Puoi interrogare per i numeri di anno e mese se necessario.

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

Ma il toStringmetodo genera una stringa in formato ISO 8601 standard .

String output = ym.toString();

Metti tutto insieme.

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();

Scarica alla console.

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

input: lun 14 mar 16:02:37 GMT 2011

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

ym: 2011-03

Codice live

Vedi questo codice in esecuzione su IdeOne.com .

Conversione

Se è necessario disporre di un Calendaroggetto, è possibile convertire in un GregorianCalendarnuovo metodo aggiunto alle vecchie classi.

GregorianCalendar gc = GregorianCalendar.from( zdt );

Informazioni su java.time

Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date, Calendar, e SimpleDateFormat.

Il progetto Joda-Time , ora in modalità manutenzione , consiglia la migrazione a java.time.

Per saperne di più, consulta il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

Dove ottenere le classi java.time?

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un banco di prova per possibili aggiunte future a java.time. Si possono trovare alcune classi utili, come per esempio Interval, YearWeek, YearQuartere altro .


14

Bene, penso che sarebbe una cattiva idea replicare il codice che è già presente in classi come SimpleDateFormat.

D'altra parte, personalmente suggerirei di evitare Calendare del Datetutto se possibile, e di utilizzare Joda Time come API di data e ora di gran lunga migliore. Ad esempio, devi essere consapevole che nonSimpleDateFormat è thread-safe, quindi hai bisogno di localizzatori di thread, sincronizzazione o una nuova istanza ogni volta che lo usi. I parser e i formattatori Joda sono thread-safe.


Grazie per il tuo contributo, esaminerò sicuramente l'utilizzo di Joda in futuro, sembra che possa essere molto utile
Doug Molineux

@Jon Skeet Joda non si diserializzerà su Android. Joda vale poco se non hai bisogno di salvare date e orari.
Frank Zappa,

@FrankZappa: non sarei d'accordo - puoi fare tutti i tuoi calcoli di data / ora in Joda Time, ma poi convertire in altri tipi (forse solo stringhe per semplicità) per scopi di serializzazione.
Jon Skeet,

Siamo spiacenti, ho dovuto votare in basso, la risposta è troppo vecchia, è obsoleta per essere la risposta più alta. Oggi java.timeè la strada da percorrere, Basil Bourque ha fornito un'ottima risposta.
Scolytus,

2
@Scolytus: la risposta migliore (e accettata) ha 332 voti rispetto a 10 su questo. Penso che se fai il downvoting ogni 7 + anni di risposta che ha una soluzione migliore ora, finirai i downvotes ... (Sono d'accordo che la risposta di Basil è buona, e l'ho votata.)
Jon Skeet,

10

Non è necessario creare un nuovo calendario, SimpleDateFormat utilizza già un calendario sottostante.

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();

(Non posso ancora commentare, ecco perché ho creato una nuova risposta)


1
La tua soluzione sembra elegante, ma presenta due svantaggi: 1. JavaDoc non garantisce che il comportamento sia, come previsto. 2. Almeno per Java 6 trovi un percorso alla riga 1353 in cui viene clonato l'oggetto calendar. Quindi, quindi! Date.equals (cal.getTime ()).
Niels

5

SimpleDateFormatè fantastico, basta notare che HHè diverso da hhquando si lavora con ore. HHrestituirà le ore basate su 24 ore e hh restituirà le ore basate su 12 ore.

Ad esempio, quanto segue restituirà 12 ore:

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

Mentre questo restituirà 24 ore:

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

4

Analizzare un orario con il fuso orario, Znel modello è per il fuso orario

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();
}

Uscita: restituirà l'ora UTC

1508899140000

inserisci qui la descrizione dell'immagine

Se non impostiamo il fuso orario in modo simile yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatutilizzerà il fuso orario impostatoSetting


3

Sì, sarebbe una cattiva pratica analizzarlo da soli. Dai un'occhiata a SimpleDateFormat , trasformerà la stringa in una data e puoi impostare la data in un'istanza di Calendar.


1

Metodo semplice:

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.