Java: รับเดือนจำนวนเต็มจากวันที่


157

ฉันจะรับเดือนเป็นจำนวนเต็มจากวัตถุ Date ( java.util.Date) ได้อย่างไร


23
จริง getMonth () ในวันที่เลิกตั้งแต่ตลอดไป)
Mateusz Dymczyk

6
@slhck: เลิกใช้แล้ว ในฐานะของ JDK รุ่น 1.1 แทนที่ด้วย Calendar.get (Calendar.MONTH)
adarshr

3
@ Zenzen ฉันไม่เห็นปัญหาในการใช้เมธอดที่คัดค้านในคลาสที่คัดค้านส่วนใหญ่
Serabe

1
@Muhd ถ้าคุณทำงานกับเดทช่วยตัวเองและใช้jodaหรือห้องสมุดอื่น ๆ
Serabe

1
@Serabe: ปัญหาคือมีวิธีแก้ปัญหาที่ดีกว่า (อย่างน้อยก็ไม่เลิก) และ getMonth ได้ถูกคัดค้านมาแล้วประมาณ 14 ปีแล้วและถูกเลิกใช้ด้วยเหตุผล
Mateusz Dymczyk

คำตอบ:


57

java.time (Java 8)

คุณยังสามารถใช้แพ็คเกจ java.timeใน Java 8 และแปลงjava.util.Dateวัตถุของคุณเป็นjava.time.LocalDateวัตถุจากนั้นใช้getMonthValue()เมธอด

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

โปรดทราบว่าค่าเดือนจะได้รับตั้งแต่ 1 ถึง 12 ตรงcal.get(Calendar.MONTH)ข้ามกับคำตอบของ adarshr ซึ่งให้ค่าตั้งแต่ 0 ถึง 11

แต่ตามที่ Basil Bourque กล่าวในความคิดเห็นวิธีที่ต้องการคือการรับMonthวัตถุ enum ด้วยLocalDate::getMonthวิธีการ


1
คำตอบที่ดี. หมายเหตุถึงผู้อ่าน: คุณอาจต้องการระบุเขตเวลาแทนที่จะพึ่งพาการโทรสำหรับค่าเริ่มต้นที่แสดงในคำตอบ ตัวอย่างเช่นวันใหม่ (และเดือน) รุ่งอรุณก่อนหน้านี้ในปารีสกว่าMontréal ZoneId.of( "America/Montreal" )หากคุณสนใจเฉพาะเกี่ยวกับมอนทรีออใช้
Basil Bourque

1
ฉันแค่ต้องการเพิ่มว่ามีบทความที่ดีเกี่ยวกับการแนะนำของjava.time api oracle.com/technetwork/articles/java/ …

โดยวิธีการอื่นทราบถึงผู้อ่าน: คุณยังสามารถรับMonthวัตถุ enumมากกว่าจำนวนเต็มเพียง Month m = localDate.gotMonth();ดูLocalDate::getMonthวิธีการ การใช้ออบเจ็กต์เช่นนี้ทำให้โค้ดของคุณเป็นเอกสารด้วยตนเองทำให้มั่นใจถึงความปลอดภัยของประเภทและรับประกันค่าที่ถูกต้อง ดูEnum บทช่วยสอนโดย Oracle
Basil Bourque

1
ถ้าคุณใช้date.toInstant()และคุณเกิดขึ้นที่จะทำงานร่วมกับjava.sql.Date(ลูกของjava.util.Date) UnsupportedOperationExceptionแล้วคุณจะได้รับ ลองnew java.sql.Date(src.getTime()).toLocalDate()
อดัม

1
@Adam ง่ายต่อการแปลงเป็น / จากjava.sql.Dateโดยใช้วิธีการแปลงใหม่ที่เพิ่มในคลาสเก่านั้น java.sql.Date.valueOf( myLocalDate )และmyJavaSqlDate.toLocalDate() นอกจากนี้ไดรเวอร์ JDBC ที่อัพเดตสำหรับ JDBC 4.2 หรือใหม่กว่านั้นไม่ต้องการjava.sqlประเภทอีกต่อไปและสามารถระบุjava.timeประเภทโดยตรงผ่านวิธีการResultSet::getObjectและ PreparedStatement::setObject
Basil Bourque

287
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);

166
โปรดทราบว่าCalendar.MONTHไม่มีเหตุผลที่ชัดเจนตาม ZERO เช่นมกราคม == 0 ตอนนี้เอกสารนั้นใช้ได้ใน API แต่ก็ยังสับสนเหมือนเป็นครั้งแรกสำหรับผู้ใช้ ฉันยังไม่พบใครที่สามารถบอกฉันได้ว่าทำไมพวกเขาถึงทำอย่างนั้น - อาจถึงเวลาสำหรับคำถาม SO ใหม่ด้วยตัวเอง (แม้ว่าฉันกลัวว่าจะไม่มีภูมิหลังที่ยอดเยี่ยมสำหรับ: /)
Voo

5
@Voo Date.getMonth () วิธีการเป็นศูนย์ซึ่งอาจเป็นสาเหตุหลักของ Calendar.MONTH ก็เช่นกัน
Muhd

1
@Muhd แน่นอนหลังจากทั้งหมดมันคือการเปลี่ยน แต่นั่นเปลี่ยนคำถามไปทำไม Date.getMonth () เป็นศูนย์ Imo การออกแบบที่น่ากลัวโดยเฉพาะอย่างยิ่งตั้งแต่วันเริ่มต้นที่หนึ่ง (อย่างน้อยพวกเขาอาจจะสอดคล้อง!) ฉันคิดว่ามันเป็นเพียงการกำกับดูแลใน API ที่ไม่ได้รับการออกแบบมาเป็นพิเศษ (ทั้งวันที่และปฏิทิน) เพื่อเริ่มต้น แต่อาจมีแบบอย่างบางอย่าง - มันดูแปลกสำหรับฉันและทำให้เกิดปัญหากับผู้เริ่มต้นมากกว่าหนึ่งคนในประสบการณ์ของฉัน
Voo

2
จริงๆแล้วมันถูกถามแล้วที่นี่ใน SO (และไม่เพียง แต่) บรรทัดล่างคือมันเป็นผลมาจาก API ที่ออกแบบมาไม่ดี ฉันหมายถึงตามที่คุณกล่าวถึงคลาส Date ทั้งหมดเป็นเรื่องตลก ความจริงก็คือไม่เพียง แต่ Java ทนทุกข์จากปัญหานี้ - วันที่ของ iirc JavaScript getMonth () เริ่มต้นด้วย 0!
Mateusz Dymczyk

1
@Voo getYear()เป็นเช่นนั้น "ด้วยเหตุผลที่ไม่ชัดเจน" ถูกลบออกในปี 1900
Hele

17

หากคุณใช้Java 8 date API คุณสามารถรับได้โดยตรงในบรรทัดเดียว!

LocalDate today = LocalDate.now();
int month = today.getMonthValue();

7

Joda เวลา

อีกทางเลือกหนึ่งด้วยคลาสJoda-Time DateTime

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

…หรือ…

int month = dateTime.getMonthOfYear();

2
ง่ายยิ่งขึ้นเพียงแค่ถามDateTimeสิ่งของในเดือนนั้น int month = dateTime.getMonthOfYear();
Basil Bourque

สวัสดีสายโหระพาฉันอัพเดทรหัสแล้ว อย่างไรก็ตามฉันชอบที่.toString("MM")มันแสดงให้เห็นว่ามีความเป็นไปได้มากกว่า "MM"
ssoward

1
คำตอบนี้ไม่สนใจปัญหาสำคัญของเขตเวลา ดูความคิดเห็นของฉันเกี่ยวกับคำถามและคำตอบของพี่น้อง ผมขอแนะนำให้ผ่านDateTimeZoneวัตถุนวกรรมิก DateTime 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 รายละเอียด

คำตอบโดย Ortomala Lokni สำหรับการใช้java.timeถูกต้อง และคุณควรใช้ java.time เนื่องจากเป็นการปรับปรุงที่ใหญ่กว่าคลาส java.util.Date/.Calendar เก่า ดูบทช่วยสอนของ Oracleใน java.time

ฉันจะเพิ่มรหัสแสดงวิธีการใช้ java.time โดยไม่คำนึงถึง java.util.Date สำหรับเมื่อคุณเริ่มต้นด้วยรหัสสด

การใช้ java.time โดยย่อ… Instantหนึ่งนาทีบนเส้นเวลาใน UTC สมัครโซนเวลา ( ZoneId) ZonedDateTimeเพื่อให้ได้

Monthชั้นที่มีความซับซ้อนenumเพื่อเป็นตัวแทนของเดือนโดยทั่วไป Enum นั้นมีวิธีการที่สะดวกเช่นรับชื่อที่มีการแปล และมั่นใจได้ว่าจำนวนเดือนใน java.time เป็นตัวเลขที่มีสติ 1-12 ไม่ใช่เรื่องไร้สาระที่เป็นศูนย์ (0-11) ที่พบใน java.util.Date/.Calendar

เพื่อให้ได้รับวันเวลาปัจจุบันเขตเวลาเป็นสิ่งสำคัญ ไม่ว่าช่วงเวลาใดวันนั้นจะไม่เหมือนกันทั่วโลก ดังนั้นเดือนไม่เหมือนกันทั่วโลกถ้าใกล้สิ้นสุด / เริ่มต้นของเดือน

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

เกี่ยวกับjava.time

java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date, และCalendarSimpleDateFormat

Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยังjava.timeชั้นเรียน

ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310

คุณสามารถแลกเปลี่ยนวัตถุjava.timeโดยตรงกับฐานข้อมูลของคุณ ใช้ไดรเวอร์ JDBC ที่สอดคล้องกับJDBC 4.2หรือใหม่กว่า ไม่จำเป็นต้องใช้สตริงไม่จำเป็นต้องมีjava.sql.*คลาส

จะรับคลาส java.time ได้ที่ไหน?

  • Java SE 8 , Java SE 9 , Java SE 10และใหม่กว่า
    • Built-in
    • เป็นส่วนหนึ่งของ Java API มาตรฐานที่มีการใช้งานแบบรวม
    • Java 9 เพิ่มคุณสมบัติและการแก้ไขเล็กน้อย
  • Java SE 6และ Java SE 7
    • มากของการทำงาน java.time จะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับ
  • Android
    • การใช้งานชุดบันเดิล Android รุ่นต่อมาของคลาส java.time
    • สำหรับก่อนหน้านี้ Android (<26) ที่ThreeTenABPโครงการปรับThreeTen-ย้ายกลับ (ดังกล่าวข้างต้น) ดูวิธีการใช้ ThreeTenABP … .

โครงการThreeTen-Extraขยาย java.time ด้วยคลาสเพิ่มเติม โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time คุณอาจพบว่าการเรียนที่มีประโยชน์บางอย่างที่นี่เช่นInterval, YearWeek, YearQuarterและอื่น ๆ อีกมากมาย


4

หากคุณไม่สามารถใช้เวลา Joda และยังคงอยู่ในโลกมืด :) (Java 5 หรือต่ำกว่า) คุณสามารถเพลิดเพลินกับสิ่งนี้:

หมายเหตุ: ตรวจสอบให้แน่ใจว่าวันที่ของคุณเสร็จสมบูรณ์ตามรูปแบบ: 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));
}

คุณคือแม่! / Είσαιημάνα!
Tzegenos

0
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

ค่าที่ส่งคืนเริ่มต้นจาก 0 ดังนั้นคุณควรเพิ่มหนึ่งรายการในผลลัพธ์


6
2 ปัญหากับคำตอบของคุณ: หนึ่งคือการที่คุณสามารถทำให้วันที่กับเวลาปัจจุบันด้วยการทำโดยไม่ต้องnew Date() System.currentTimeMillisอีกอย่างคือ getMonth นั้นเลิกใช้แล้ว
Muhd

@Muhd แล้วทางออกที่ดีที่สุดคืออะไร?
twlkyao

@Muhd System.currentTimeMillis () ฉันเพิ่มที่นี่เพื่อระบุว่าที่นี่เป็นประเภทยาวและคุณสามารถระบุวันที่
twlkyao

4
วันที่ :: getMonth เลิกใช้แล้วใน Java 1.1 ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.