Java:从日期获取月份整数


157

如何从日期对象(java.util.Date)中将月份作为整数?


23
实际上永远不推荐使用Date上的getMonth();)
Mateusz Dymczyk 2011年

6
@slhck:已弃用。从JDK版本1.1开始,由Calendar.get(Calendar.MONTH)取代。
2011年

3
@Zenzen我看不到在大多数不赞成使用的类中使用不赞成使用的方法的问题。
2011年

1
@Muhd,如果您要处理日期,请自助并使用joda或任何其他库。
2011年

1
@Serabe:问题是有更好的解决方案(至少不建议使用)。getMonth已经被弃用了大约14年,它已经被弃用是有原因的。
Mateusz Dymczyk 2011年

Answers:


57

java.time(Java 8)

您还可以使用Java 8中的java.time包并将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使用该LocalDate::getMonth方法获取枚举对象。


1
好答案。读者注意:您可能想指定一个时区,而不是依赖于Answer中显示的默认呼叫。例如,巴黎的新一天(一个月)比蒙特利尔早。如果您特别在意蒙特利尔,请使用ZoneId.of( "America/Montreal" )
罗勒·布尔克

1
我只想补充一点,有关于引进了一大篇java.time API oracle.com/technetwork/articles/java/...

顺便说一句,给读者的另一条注释:您还可以获得Month枚举对象,而不仅仅是一个整数。Month m = localDate.gotMonth();LocalDate::getMonth方法。使用这样的对象可使您的代码自我记录,确保类型安全并保证有效值。请参阅Oracle的Enum教程
罗勒·布尔克

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::getObjectPreparedStatement::setObject方法。
罗勒·布尔克

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

166
注意,Calendar.MONTH出于明显的原因,基于零,即一月== 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的Date getMonth()也以0开头!
Mateusz Dymczyk

1
@Voo getYear()也是“没有任何明显的理由”,由1900减去
海伦

17

如果您使用Java 8日期API,则可以直接在一行中获取它!

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

7

乔达时代

或者,使用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,我已经更新了代码。但是,我喜欢.toString("MM")它,因为它显示出比“ MM”更多的可能性。
ssoward

1
这个答案忽略了时区的关键问题。请参阅我对问题和同级答案的评论。我建议将一个DateTimeZone对象传递给该DateTime构造函数:DateTimeZone.forID( "America/Montreal" )
罗勒·布尔克

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类的巨大改进。请参阅java.time上的Oracle教程

我将添加一些代码,展示在不使用java.util.Date的情况下如何使用java.time。

简而言之使用java.time… Instant在UTC时间轴上是片刻。套用时区(ZoneId)取得ZonedDateTime

Month班是一个复杂的枚举来表示一般一个月。该枚举具有方便的方法,例如获取本地化名称。并且请放心,java.time中的月份号是一个合理的数字,1-12,而不是java.util.Date/.Calendar中从零开始的废话(0-11)。

要获取当前日期时间,时区至关重要。在任何时候,世界各地的日期都不相同。因此,如果临近月份的结束/开始,则该月份在世界各地并不相同。

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.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


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开始,因此应在结果中加1。


6
您的答案有两个问题:一是您可以通过new Date()不使用来与当前时间约会System.currentTimeMillis。另一个是不建议使用getMonth。
Muhd

@Muhd那么最好的解决方案是什么?
twlkyao

@Muhd我在这里添加的System.currentTimeMillis()表示这是一个长类型,您可以指定日期。
twlkyao

4
日期::得到月已经弃用Java 1.1中(cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/...
Ortomala Lokni
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.