Java:从日期中获取月份整数

197

如何从一个java.util.Date对象中获取月份的整数值?


25
自古以来,Date对象上的getMonth()方法已被弃用。 - Mateusz Dymczyk
6
已弃用。自JDK版本1.1起,被Calendar.get(Calendar.MONTH)所取代。 - adarshr
4
@Zenzen 我认为在大多数已经被弃用的类中使用已被弃用的方法并不成问题。 - Serabe
1
@Muhd 如果你正在处理日期,建议使用 joda 或其他任何库来帮助自己。 - Serabe
1
@Zenzen:这只是一个玩笑,涉及到使用一个大部分方法已经被弃用的类(包括构造函数在内的33个方法中有22个已经被弃用)。对于误解我感到抱歉。 - Serabe
显示剩余4条评论
8个回答

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

185
请注意,Calendar.MONTH 之所以从零开始计数,即一月==0,原因不明。虽然在 API 中有良好的文档记录,但对于第一次使用者来说仍然非常困惑。我还没有找到任何人能告诉我为什么会这样 - 或许是时候我自己发一个新的 SO 问题了(尽管我担心并没有太多的背景信息 :/)。 - Voo
5
Voo所说的Date.getMonth()方法是从0开始计数的,这很可能是Calendar.MONTH也是从0开始计数的主要原因。 - Muhd
2
实际上在SO(不仅限于此)已经有人问过了。归根结底,这是API设计不佳的结果。我的意思是,就像你提到的整个Date类一样,实在是一个笑话。有趣的是,不只是Java遇到这个问题 - 如果我没记错的话,JavaScript的Date.getMonth()方法也从0开始! - Mateusz Dymczyk
1
@Voo getYear() 也会被“毫无理由地”减去1900。 - Hele
1
注意:此答案未解决时区问题。对于月底附近的日期时间值,由于JVM当前默认时区的不同,结果月份可能会向前或向后摆动。最好明确指定所需/期望的时区。 - Basil Bourque
显示剩余4条评论

87

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给出,与adarshr的答案中给出的cal.get(Calendar.MONTH)(取值范围为0到11)相反。
但正如Basil Bourque在评论中所说,首选方法是使用LocalDate::getMonth方法获取一个Month枚举对象。

1
好的回答。读者请注意:您可能需要指定一个时区,而不是依赖于答案中显示的默认调用。例如,在巴黎,新的一天(和月份)会比蒙特利尔早到来。如果您特别关心蒙特利尔,请使用 ZoneId.of("America/Montreal") - Basil Bourque
1
我只想补充一下,关于 java.time api 的介绍有一篇很棒的文章 http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html - user813853
另外,对于读者的一个提示:您还可以获得一个 Month 枚举对象,而不仅仅是一个整数。Month m = localDate.gotMonth(); 参见 LocalDate::getMonth 方法。使用这样的对象可以使您的代码自我记录,确保类型安全,并保证有效值。请参阅 Oracle 的 枚举教程 - Basil Bourque
1
如果您使用 date.toInstant() 并且您正在使用 java.sql.Datejava.util.Date 的子类),那么您将会得到一个 UnsupportedOperationException。请尝试使用 new java.sql.Date(src.getTime()).toLocalDate() - Adam
1
@Adam 通过使用添加到旧类中的新转换方法,将 java.sql.Date 转换为/从更容易。 java.sql.Date.valueOf(myLocalDate)myJavaSqlDate.toLocalDate() 此外,针对 JDBC 4.2 或更高版本更新的 JDBC 驱动程序不再需要 java.sql 类型,并且可以通过 ResultSet::getObjectPreparedStatement::setObject 方法直接访问 java.time 类型。 - Basil Bourque
了解JDBC 4.2是很好的,我同意你的观点。但是,关于“UnsupportedOperationException”的警告仅适用于您绝对确定在使用“java.util.Date :: toInstant”时不会传递“java.sql.Date”的情况下。在我看来,当他们编写“java.sql.Date”时实现很差。 - Adam

21

如果你使用Java 8的日期API,可以在一行代码中直接获取它!

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

1
这是一月份的0还是1? - gumuruh
这只返回单个数字值,即您无法在不使用日期或日历的情况下形成mm dd值。 - Glorious Kale

9

Joda-Time

或者,使用Joda-TimeDateTime类。

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

…或者…

int month = dateTime.getMonthOfYear();

3
更简单的方法是,只需询问 DateTime 对象的月份即可。 int month = dateTime.getMonthOfYear(); - Basil Bourque
不错的建议,Basil。我已经更新了代码。然而,我喜欢.toString("MM"),因为它显示了除了"MM"之外的更多可能性。 - ssoward
1
这个回答忽略了时区这个关键问题。请参阅我的评论和相邻的回答。我建议将一个DateTimeZone对象传递给该DateTime构造函数:DateTimeZone.forID("America/Montreal") - Basil Bourque

8

简而言之

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 Tutorial上的java.time。

我将添加一些代码,展示如何在不考虑java.util.Date的情况下使用java.time,适用于你从头开始编写代码的时候。

简述使用java.time……Instant表示UTC时间轴上的瞬间。应用时区(ZoneId)即可得到ZonedDateTime

Month类是一个复杂的枚举,用于表示一般的月份。该枚举具有便捷的方法,例如获取本地化名称。请放心,java.time中的月份编号是合理的,为1-12,而不是在java.util.Date/.Calendar中发现的从零开始的无意义编号(0-11)。

要获取当前日期时间,时区至关重要。因为世界各地的日期在任何时刻都不相同。因此,如果接近月末/月初,世界各地的月份也不相同。请注意保留HTML标签。
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.DateCalendarSimpleDateFormat

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

要了解更多信息,请参阅Oracle教程。并搜索Stack Overflow以获取许多示例和说明。规范是JSR 310

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

如何获取java.time类?

ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来添加的可靠依据。您可能会在这里找到一些有用的类,例如Interval, YearWeek, YearQuarter以及更多


6

如果您无法使用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

1

如果我们使用java.time.LocalDate api,我们可以在一行中以整数形式获取月份:

import java.time.LocalDate;
...
int currentMonthNumber = LocalDate.now().getMonthValue(); //OR
LocalDate scoringDate = LocalDate.parse("2022-07-01").getMonthValue(); //for String date

例如今天的日期是2022年7月29日,输出结果将是7。

也可以使用 YearMonth.now()MonthDay.now()。并且可以向 now 方法传递一个 ZoneId,以明确操作是基于时区的。 - Ole V.V.

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

返回值从0开始,因此您应该将结果加一。


6
你的回答有两个问题:一是可以通过执行 new Date() 而不需要 System.currentTimeMillis() 来获取当前时间。另一个问题是 getMonth 已经被弃用。 - Muhd
@Muhd 那么什么是最佳解决方案? - twlkyao
@Muhd 我在这里添加的 System.currentTimeMillis() 是为了表示这是一个 long 类型,您可以指定日期。 - twlkyao
4
Java 1.1中已经废弃了Date :: getMonth方法(http://www.cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/java.util.Date.html#getMonth%28%29)。 - Ortomala Lokni
Java 12 中已弃用 - Glorious Kale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接