Konversi String ke Objek Kalender di Jawa

175

Saya baru mengenal Java, biasanya bekerja dengan PHP.

Saya mencoba mengonversi string ini:

Senin 14 Maret 16:02:37 GMT 2011

Menjadi Obyek Kalender sehingga saya dapat dengan mudah menarik Tahun dan Bulan seperti ini:

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

Akankah ide buruk untuk menguraikannya secara manual? Menggunakan metode substring?

Saran apa pun akan membantu terima kasih!

Doug Molineux
sumber

Jawaban:

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

Catatan: atur Localesesuai dengan lingkungan / kebutuhan Anda


Lihat juga

Jigar Joshi
sumber
onlineconversion.com/unix_time.htm . Ini adalah timestamp converter online. Nilai yang dihitung dengan kode java dan konversi daring ini berbeda. Mengapa?? Bisakah kau pergi melalui ini. Terima kasih :)
Sachin J
6
Perhatikan bahwa ini kehilangan informasi zona waktu. Objek Kalender akan memiliki TimeZone sistem default bukan yang diuraikan.
Cristian Vrabie
Ini seharusnya bukan jawaban atas / diterima lagi. Karena Java 8 sudah lebih dari 4 tahun, jawabannya harus diperbarui java.time. Tanya Jawab ini tampil cukup menonjol di google.
Scolytus
18

tl; dr

Pendekatan modern menggunakan kelas 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

Hindari kelas tanggal waktu lama

Cara modern adalah dengan kelas java.time. Kelas tanggal-waktu lama sepertiCalendar telah terbukti tidak dirancang dengan baik, membingungkan, dan menyusahkan.

Tentukan formatter khusus untuk mencocokkan input string Anda.

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

Parse sebagai a ZonedDateTime.

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

Anda tertarik pada tahun dan bulan. Kelas java.time termasuk YearMonthkelas untuk tujuan itu.

YearMonth ym = YearMonth.from( zdt );

Anda dapat menginterogasi untuk angka tahun dan bulan jika diperlukan.

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

Tetapi toStringmetode ini menghasilkan string dalam format standar ISO 8601 .

String output = ym.toString();

Kumpulkan semuanya.

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 ke konsol.

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

input: Sen 14 Mar 16:02:37 GMT 2011

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

ym: 2011-03

Kode langsung

Lihat kode ini berjalan di IdeOne.com .

Konversi

Jika Anda harus memiliki Calendarobjek, Anda bisa mengonversi ke GregorianCalendarmenggunakan metode baru yang ditambahkan ke kelas lama.

GregorianCalendar gc = GregorianCalendar.from( zdt );

Tentang java.time

The java.time kerangka dibangun ke Jawa 8 dan kemudian. Kelas-kelas ini menggantikan tua merepotkan warisan kelas tanggal-waktu seperti java.util.Date, Calendar, &SimpleDateFormat .

Proyek Joda-Time , sekarang dalam mode pemeliharaan , menyarankan migrasi ke java.time.

Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasi adalah JSR 310 .

Di mana mendapatkan kelas java.time?

Proyek ThreeTen-Extra memperpanjang java.time dengan kelas tambahan. Proyek ini adalah ajang pembuktian untuk kemungkinan penambahan masa depan ke java.time. Anda mungkin menemukan beberapa kelas berguna di sini seperti Interval, YearWeek, YearQuarter, dan lebih .

Basil Bourque
sumber
14

Yah, saya pikir itu akan menjadi ide yang buruk untuk mereplikasi kode yang sudah ada di kelas seperti SimpleDateFormat .

Di sisi lain, secara pribadi saya menyarankan untuk menghindari Calendardan Datesepenuhnya jika Anda bisa, dan menggunakan Joda Time sebagai gantinya, API tanggal dan waktu yang dirancang jauh lebih baik. Misalnya, Anda harus menyadari bahwa SimpleDateFormatitu bukan thread-safe, jadi Anda perlu thread-local, sinkronisasi, atau contoh baru setiap kali Anda menggunakannya. Joda parser dan formatters adalah benang-aman.

Jon Skeet
sumber
Terima kasih atas masukan Anda, saya pasti akan melihat ke dalam menggunakan Joda di masa depan, sepertinya itu bisa sangat berguna
Doug Molineux
@Jon Skeet Joda tidak akan deserialize di Android. Joda hanya bernilai sedikit kecuali Anda tidak perlu menyimpan tanggal dan waktu.
Frank Zappa
@ FrankZappa: Saya tidak setuju dengan itu - Anda dapat melakukan semua perhitungan tanggal / waktu Anda di Joda Time, tetapi kemudian mengonversi ke tipe lain (mungkin hanya string untuk kesederhanaan) untuk keperluan serialisasi.
Jon Skeet
Maaf, harus downvote, jawabannya terlalu tua, sudah ketinggalan jaman untuk menjadi jawaban peringkat tertinggi. Hari ini java.timeadalah jalan yang harus ditempuh, Basil Bourque memberikan jawaban yang sangat baik.
Scolytus
2
@Scolytus: Jawaban teratas (dan diterima) memiliki 332 suara dibandingkan dengan 10 pada yang ini. Saya pikir jika Anda berkeliling memilih setiap 7 + tahun jawaban yang memiliki solusi yang lebih baik sekarang, Anda akan kehabisan downvotes ... (Saya setuju bahwa jawaban Basil itu baik, dan saya telah memilih itu.)
Jon Skeet
10

Tidak ada Kalender baru yang perlu dibuat, SimpleDateFormat sudah menggunakan Kalender di bawahnya.

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

(Saya belum bisa berkomentar, itu sebabnya saya membuat jawaban baru)

GoGoris
sumber
1
Solusi Anda terlihat elegan, tetapi memiliki dua kelemahan: 1. JavaDoc tidak menjamin bahwa perilaku tersebut, seperti yang diharapkan. 2. Setidaknya untuk Java 6 Anda menemukan jalur di baris 1353 di mana objek-kalender dikloning. Jadi, maka! Date.equals (cal.getTime ()).
niels
5

SimpleDateFormatbagus, hanya catatan yang HHberbeda dari hhketika bekerja dengan jam. HHakan kembali 24 jam berbasis dan akan kembali 12 jam berbasis

Misalnya, yang berikut ini akan mengembalikan waktu 12 jam:

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

Sementara ini akan kembali 24 jam:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Philip
sumber
4

Pisahkan waktu dengan zona waktu, Zpolanya adalah untuk zona waktu

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

Output: ini akan mengembalikan waktu UTC

1508899140000

masukkan deskripsi gambar di sini

Jika kita tidak mengatur zona waktu dalam pola seperti yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatakan menggunakan zona waktu yang telah ditetapkanSetting

Phan Van Linh
sumber
3

Ya itu akan menjadi praktik buruk untuk menguraikannya sendiri. Lihatlah SimpleDateFormat , itu akan mengubah String menjadi Date dan Anda dapat mengatur Date menjadi instance Calendar.

John Vint
sumber
1

Metode sederhana:

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;
}
Alberto Cerqueira
sumber