Java: Dapatkan Integer bulan dari Tanggal

157

Bagaimana cara mendapatkan bulan sebagai bilangan bulat dari objek Date ( java.util.Date)?

Muhd
sumber
23
sebenarnya getMonth () pada Tanggal sudah usang sejak selamanya;)
Mateusz Dymczyk
6
@ slhck: Sudah usang. Pada JDK versi 1.1, digantikan oleh Calendar.get (Calendar.MONTH).
adarshr
3
@ Zenzen Saya tidak melihat masalah dalam menggunakan metode usang di sebagian besar kelas usang.
Serabe
1
@ Muhd ​​jika Anda bekerja dengan tanggal, membantu diri sendiri dan menggunakan joda atau perpustakaan lainnya.
Serabe
1
@Serabe: masalahnya adalah ada solusi yang lebih baik (yang setidaknya tidak usang). Dan getMonth telah ditinggalkan selama 14 tahun sekarang dan sudah usang karena suatu alasan.
Mateusz Dymczyk

Jawaban:

57

java.time (Java 8)

Anda juga dapat menggunakan paket java.time di Java 8 dan mengonversi java.util.Dateobjek Anda menjadi java.time.LocalDateobjek dan kemudian cukup menggunakan getMonthValue()metode ini.

Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
int month = localDate.getMonthValue();

Perhatikan bahwa nilai bulan di sini diberikan dari 1 hingga 12 bertentangan dengan cal.get(Calendar.MONTH)jawaban adarshr yang memberikan nilai dari 0 hingga 11.

Tetapi seperti dikatakan Basil Bourque dalam komentar, cara yang lebih disukai adalah mendapatkan Monthobjek enum dengan LocalDate::getMonthmetode tersebut.

Ortomala Lokni
sumber
1
Jawaban yang bagus. Catatan untuk pembaca: Anda mungkin ingin menentukan zona waktu daripada mengandalkan panggilan untuk default yang ditunjukkan dalam Jawaban. Misalnya, hari baru (dan bulan) baru saja tiba di Paris, daripada Montréal. Jika Anda peduli secara khusus tentang Montréal, gunakan ZoneId.of( "America/Montreal" ).
Basil Bourque
1
Saya hanya ingin menambahkan bahwa ada artikel yang bagus tentang pengenalan java.time api oracle.com/technetwork/articles/java/…
By the way, catatan lain untuk pembaca: Anda juga bisa mendapatkan Monthobjek enum daripada bilangan bulat belaka. Month m = localDate.gotMonth();Lihat LocalDate::getMonthmetode. Menggunakan objek seperti ini membuat kode Anda mendokumentasikan diri sendiri, memastikan keamanan jenis, dan menjamin nilai yang valid. Lihat tutorial Enum oleh Oracle.
Basil Bourque
1
jika Anda menggunakan date.toInstant()dan Anda kebetulan bekerja dengan java.sql.Date(anak java.util.Date) maka Anda akan mendapatkan UnsupportedOperationException. Cobanew java.sql.Date(src.getTime()).toLocalDate()
Adam
1
@Adam Jauh lebih mudah untuk mengonversi ke / dari java.sql.Datedengan menggunakan metode konversi baru yang ditambahkan ke kelas lama itu. java.sql.Date.valueOf( myLocalDate )dan myJavaSqlDate.toLocalDate() Juga, driver JDBC yang diperbarui untuk JDBC 4.2 atau yang lebih baru tidak lagi memerlukan java.sqltipe, dan dapat langsung menangani java.timetipe melalui ResultSet::getObjectdan PreparedStatement::setObjectmetode.
Basil Bourque
287
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);
adarshr
sumber
166
Perhatikan bahwa Calendar.MONTHtanpa alasan yang jelas ZERO berdasarkan, yaitu Januari == 0. Nah, itu didokumentasikan dengan baik di API, tetapi masih membingungkan bagi pengguna pertama kali. Saya belum menemukan orang yang bisa memberi tahu saya mengapa mereka pergi dengan itu - mungkin waktu untuk pertanyaan SO baru sendiri (meskipun saya khawatir tidak ada latar belakang yang bagus untuk itu: /)
Voo
5
Metode @Voo Date.getMonth () berbasis nol, yang mungkin merupakan alasan utama Calendar.MONTH juga.
Muhd
1
@Muhd Tentu setelah semua itu penggantinya. Tapi itu hanya menggeser pertanyaan sekitar mengapa Date.getMonth () berbasis nol? Imo desain yang mengerikan, terutama sejak hari mulai pada satu (mereka setidaknya bisa konsisten!). Saya berasumsi itu hanya beberapa pengawasan dalam API yang tidak dirancang dengan baik (Tanggal dan Kalender) untuk memulai. Tapi mungkin ada beberapa preseden - sepertinya aneh bagi saya dan telah menyebabkan masalah lebih dari satu pemula dalam pengalaman saya.
Voo
2
Sebenarnya sudah diminta sudah di sini di SO (dan tidak hanya). Intinya adalah bahwa ini adalah hasil dari API yang dirancang dengan buruk. Maksud saya saat Anda menyebutkan seluruh kelas Date adalah lelucon. Fakta yang menyenangkan adalah bahwa tidak hanya Java yang menderita masalah ini - Date getMonth iirc JavaScript juga dimulai dengan 0!
Mateusz Dymczyk
1
@Vo getYear()juga, "tanpa alasan yang jelas", dikurangi pada tahun 1900.
Hele
17

Jika Anda menggunakan Java 8 date api, Anda dapat langsung mendapatkannya dalam satu baris!

LocalDate today = LocalDate.now();
int month = today.getMonthValue();
Ketan Chitale
sumber
7

Joda-Time

Atau, dengan kelas Joda-Time DateTime .

//convert date to datetime
DateTime datetime = new DateTime(date);
int month = Integer.parseInt(datetime.toString("MM"))

…atau…

int month = dateTime.getMonthOfYear();
ssoward
sumber
2
Lebih sederhana lagi, tanyakan saja bulan berapa DateTimebulan. int month = dateTime.getMonthOfYear();
Basil Bourque
Good call Basil, saya telah memperbarui kodenya. Namun, saya suka .toString("MM")karena itu menunjukkan ada lebih banyak kemungkinan daripada hanya "MM".
ssoward
1
Jawaban ini mengabaikan masalah krusial zona waktu. Lihat komentar saya pada Pertanyaan dan Jawaban saudara. Saya sarankan melewati DateTimeZoneobjek untuk yang DateTime konstruktor: DateTimeZone.forID( "America/Montreal" ).
Basil Bourque
6

tl; dr

myUtilDate.toInstant()                          // Convert from legacy class to modern. `Instant` is a point on the timeline in UTC.
          .atZone(                              // Adjust from UTC to a particular time zone to determine date. Renders a `ZonedDateTime` object. 
              ZoneId.of( "America/Montreal" )   // Better to specify desired/expected zone explicitly than rely implicitly on the JVM’s current default time zone.
          )                                     // Returns a `ZonedDateTime` object.
          .getMonthValue()                      // Extract a month number. Returns a `int` number.

java.time Detail

Jawaban oleh Ortomala Lokni untuk menggunakan java.time sudah benar. Dan Anda harus menggunakan java.time karena ini merupakan peningkatan besar atas kelas java.util.Date/.Calendar lama. Lihat Tutorial Oracle di java.time.

Saya akan menambahkan beberapa kode yang menunjukkan cara menggunakan java.time tanpa memperhatikan java.util.Date, untuk saat Anda memulai dengan kode baru.

Singkatnya, menggunakan java.time ... An Instantadalah saat di timeline di UTC. Terapkan zona waktu ( ZoneId) untuk mendapatkan aZonedDateTime .

The Monthkelas canggih enum untuk mewakili bulan pada umumnya. Enum itu memiliki metode praktis seperti mendapatkan nama yang dilokalkan. Dan yakinlah bahwa jumlah bulan di java.time adalah yang waras, 1-12, bukan omong kosong berbasis nol (0-11) yang ditemukan di java.util.Date/.Calendar.

Untuk mendapatkan tanggal-waktu saat ini, zona waktu sangat penting. Setiap saat, tanggalnya tidak sama di seluruh dunia. Karena itu bulannya tidak sama di seluruh dunia jika mendekati akhir / awal bulan.

ZoneId zoneId = ZoneId.of( "America/Montreal" );  // Or 'ZoneOffset.UTC'.
ZonedDateTime now = ZonedDateTime.now( zoneId );
Month month = now.getMonth(); 
int monthNumber = month.getValue(); // Answer to the Question.
String monthName = month.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH );

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 kelas java.time .

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

Anda dapat bertukar objek java.time secara langsung dengan database Anda. Gunakan driver JDBC yang sesuai dengan JDBC 4.2 atau yang lebih baru. Tidak perlu untuk string, tidak perlujava.sql.* kelas.

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
4

Jika Anda tidak dapat menggunakan waktu Joda dan Anda masih hidup di dunia yang gelap :) (Java 5 atau lebih rendah) Anda dapat menikmati ini:

Catatan: Pastikan tanggal Anda sudah dibuat dengan format: dd / MM / YYYY

/**
Make an int Month from a date
*/
public static int getMonthInt(Date date) {

    SimpleDateFormat dateFormat = new SimpleDateFormat("MM");
    return Integer.parseInt(dateFormat.format(date));
}

/**
Make an int Year from a date
*/
public static int getYearInt(Date date) {

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
    return Integer.parseInt(dateFormat.format(date));
}
Badr DRAIFI
sumber
Kamu adalah ibu! / Είσαι η μάνα!
Tzegenos
0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

Nilai yang dikembalikan dimulai dari 0, jadi Anda harus menambahkannya ke hasilnya.

twlkyao
sumber
6
2 masalah dengan jawaban Anda: satu adalah bahwa Anda dapat membuat kencan dengan waktu saat ini dengan melakukan new Date()tanpa System.currentTimeMillis. Yang lainnya adalah getMonth sudah tidak digunakan lagi.
Muhd
@ Muhd ​​Jadi apa solusi terbaik?
twlkyao
@ Muhd ​​The System.currentTimeMillis () yang saya tambahkan di sini adalah untuk menunjukkan bahwa ini adalah tipe yang panjang, dan Anda dapat menentukan tanggalnya.
twlkyao
4
Date :: getMonth sudah tidak digunakan lagi di Jawa 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni