Java: Holen Sie sich die Monats-Ganzzahl vom Datum


157

Wie erhalte ich den Monat als Ganzzahl von einem Date-Objekt ( java.util.Date)?


23
tatsächlich ist getMonth () am Datum seit Ewigkeiten veraltet;)
Mateusz Dymczyk

6
@slhck: Veraltet. Ab JDK Version 1.1, ersetzt durch Calendar.get (Calendar.MONTH).
Adarshr

3
@Zenzen Ich sehe das Problem nicht in der Verwendung einer veralteten Methode in einer meist veralteten Klasse.
Serabe

1
@Muhd Wenn Sie mit Daten arbeiten, helfen Sie sich selbst und verwenden Sie joda oder eine andere Bibliothek.
Serabe

1
@ Serabe: Das Problem ist, dass es bessere Lösungen gibt (solche, die zumindest nicht veraltet sind). Und getMonth ist seit ungefähr 14 Jahren veraltet und aus einem bestimmten Grund veraltet.
Mateusz Dymczyk

Antworten:


57

java.time (Java 8)

Sie können auch das Paket java.time in Java 8 verwenden, Ihr java.util.DateObjekt in ein java.time.LocalDateObjekt konvertieren und dann einfach die getMonthValue()Methode verwenden.

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

Beachten Sie, dass hier Monatswerte von 1 bis 12 angegeben werden, im Gegensatz zu cal.get(Calendar.MONTH)adarshrs Antwort, die Werte von 0 bis 11 angibt.

Aber wie Basil Bourque in den Kommentaren sagte, ist der bevorzugte Weg, ein MonthEnum-Objekt mit der LocalDate::getMonthMethode zu erhalten.


1
Gute Antwort. Hinweis für den Leser: Möglicherweise möchten Sie eine Zeitzone angeben, anstatt sich auf den in der Antwort angegebenen Standardaufruf zu verlassen. Ein neuer Tag (und Monat) bricht beispielsweise in Paris früher an als in Montréal. Wenn Sie sich speziell für Montréal interessieren, ist die Verwendung ZoneId.of( "America/Montreal" ).
Basil Bourque

1
Ich möchte nur hinzufügen, dass es einen großartigen Artikel über die Einführung von java.time api oracle.com/technetwork/articles/java/…

Übrigens noch ein Hinweis für den Leser: Sie können auch ein MonthEnum-Objekt anstelle einer bloßen Ganzzahl erhalten. Month m = localDate.gotMonth();Siehe LocalDate::getMonthMethode. Durch die Verwendung solcher Objekte wird Ihr Code selbstdokumentiert, die Typensicherheit gewährleistet und gültige Werte garantiert. Siehe Enum-Tutorial von Oracle.
Basil Bourque

1
Wenn Sie verwenden date.toInstant()und zufällig mit einem java.sql.Date(dem Kind von java.util.Date) arbeiten, erhalten Sie ein UnsupportedOperationException. Versuchen Sienew java.sql.Date(src.getTime()).toLocalDate()
Adam

1
@Adam java.sql.DateMit den neuen Konvertierungsmethoden, die dieser alten Klasse hinzugefügt wurden, ist das Konvertieren viel einfacher . java.sql.Date.valueOf( myLocalDate )und myJavaSqlDate.toLocalDate() auch JDBC - Treiber für JDBC aktualisiert 4.2 oder später nicht mehr brauchen java.sqlTypen und können direkt java.timeAdresstypen über die ResultSet::getObjectund PreparedStatement::setObjectMethoden.
Basil Bourque

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

166
Beachten Sie, dass dies Calendar.MONTHohne ersichtlichen Grund NULL-basiert ist, dh Januar == 0. Nun, das ist in der API gut dokumentiert, aber für Erstbenutzer ist es immer noch verdammt verwirrend. Ich habe noch niemanden gefunden, der mir sagen könnte, warum sie so vorgegangen sind - vielleicht selbst Zeit für eine neue SO-Frage (obwohl ich befürchte, dass es dafür keinen großartigen Hintergrund gibt: /)
Voo

5
Die Methode @Voo Date.getMonth () basierte auf Null, was wahrscheinlich auch der Hauptgrund für Calendar.MONTH ist.
Muhd

1
@ Muhd ​​Sicher war es doch der Ersatz. Aber das verschiebt die Frage nur dahin, warum Date.getMonth () auf Null basiert? Ich bin ein schreckliches Design, zumal die Tage um eins beginnen (sie könnten zumindest konsistent sein!). Ich nehme an, es war zunächst nur ein Versehen in einer nicht besonders gut gestalteten API (sowohl Datum als auch Kalender). Aber vielleicht gibt es einen Präzedenzfall - es scheint mir nur seltsam und hat meiner Erfahrung nach mehr als einem Anfänger Probleme bereitet.
Voo

2
Eigentlich wurde es hier schon auf SO gefragt (und nicht nur). Das Endergebnis ist, dass es ein Ergebnis einer schlecht gestalteten API ist. Ich meine, wie du erwähnt hast, ist die ganze Date-Klasse ein Witz. Eine lustige Tatsache ist, dass nicht nur Java unter diesem Problem leidet - das Datum getMonth () von iirc JavaScript beginnt auch mit einer 0!
Mateusz Dymczyk

1
@Voo getYear()wird auch "ohne ersichtliche Gründe" bis 1900 abgezogen.
Hele

17

Wenn Sie Java 8 Date API verwenden, können Sie es direkt in einer Zeile erhalten!

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

7

Joda-Zeit

Alternativ mit der Joda-Time- DateTime Klasse.

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

…oder…

int month = dateTime.getMonthOfYear();

2
Noch einfacher, fragen Sie einfach das DateTimeObjekt nach seinem Monat. int month = dateTime.getMonthOfYear();
Basil Bourque

Guter Anruf Basil, ich habe den Code aktualisiert. Ich mag das .toString("MM")jedoch, da es mehr Möglichkeiten gibt als nur "MM".
Ssoward

1
Diese Antwort ignoriert das entscheidende Problem der Zeitzone. Siehe meine Kommentare zu Frage und Antwort der Geschwister. Ich schlage vor, ein DateTimeZoneObjekt an diesen DateTime-Konstruktor zu übergeben : 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 Einzelheiten

Die Antwort von Ortomala Lokni für die Verwendung von java.time ist korrekt. Und Sie sollten java.time verwenden, da dies eine gigantische Verbesserung gegenüber den alten Klassen java.util.Date/.Calendar darstellt. Weitere Informationen finden Sie im Oracle- Lernprogramm auf java.time.

Ich werde Code hinzufügen, der zeigt, wie man java.time ohne Rücksicht auf java.util.Date verwendet, wenn Sie mit neuem Code beginnen.

Verwenden von java.time auf den Punkt gebracht… An Instantist ein Moment auf der Timeline in UTC. Wenden Sie eine Zeitzone ( ZoneId) an, um a zu erhalten ZonedDateTime.

Die MonthKlasse ist eine anspruchsvolle Aufzählung , die einen Monat im Allgemeinen darstellt. Diese Aufzählung enthält praktische Methoden wie das Abrufen eines lokalisierten Namens. Und seien Sie versichert, dass die Monatszahl in java.time eine vernünftige Zahl von 1 bis 12 ist und nicht der auf Null basierende Unsinn (0 bis 11) in java.util.Date/.Calendar.

Um die aktuelle Datums- und Uhrzeitangabe zu erhalten, ist die Zeitzone von entscheidender Bedeutung. Zu jedem Zeitpunkt ist das Datum auf der ganzen Welt nicht dasselbe. Daher ist der Monat weltweit nicht derselbe, wenn er sich dem Ende / Anfang des Monats nähert.

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

Über java.time

Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .

Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für java.sql.*Klassen.

Woher bekomme ich die java.time-Klassen?

Das ThreeTen-Extra- Projekt erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von java.time. Sie können einige nützliche Klassen hier wie finden Interval, YearWeek, YearQuarter, und mehr .


4

Wenn Sie die Joda-Zeit nicht nutzen können und immer noch in der dunklen Welt leben :) (Java 5 oder niedriger), können Sie dies genießen:

Hinweis: Stellen Sie sicher, dass Ihr Datum bereits im Format TT / MM / JJJJ erstellt wurde

/**
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));
}

Du bist die Mutter! / Είσαι η μάνα!
Tzegenos

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

Der zurückgegebene Wert beginnt bei 0, daher sollten Sie dem Ergebnis einen hinzufügen.


6
2 Probleme mit Ihrer Antwort: Eines ist, dass Sie ein Datum mit der aktuellen Uhrzeit erstellen können, indem Sie darauf new Date()verzichten System.currentTimeMillis. Das andere ist, dass getMonth veraltet ist.
Muhd

@ Muhd ​​Also, was ist die beste Lösung?
Twlkyao

@Muhd Das System.currentTimeMillis (), das ich hier hinzugefügt habe, sollte anzeigen, dass es sich um einen langen Typ handelt, und Sie können das Datum angeben.
Twlkyao

4
Date :: getMonth war in Java 1.1 bereits veraltet ( cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/… )
Ortomala Lokni
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.