Java:从日期获取月份整数

Posted

技术标签:

【中文标题】Java:从日期获取月份整数【英文标题】:Java: Get month Integer from Date 【发布时间】:2011-11-03 05:21:27 【问题描述】:

如何从 Date 对象 (java.util.Date) 中以整数形式获取月份?

【问题讨论】:

实际上 getMonth() on Date 永远被弃用了;) @slhck:已弃用。从 JDK 1.1 版开始,由 Calendar.get(Calendar.MONTH) 取代。 @Zenzen 我没有看到在大部分已弃用的类中使用已弃用的方法的问题。 @Muhd 如果您正在处理日期,请帮助自己并使用joda 或任何其他库。 @Serabe:问题是有更好的解决方案(至少没有被弃用的)。而 getMonth 已经被弃用了 14 年,而且它被弃用是有原因的。 【参考方案1】:

tl;博士

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 的The Answer 使用java.time 是正确的。您应该使用 java.time,因为它是对旧 java.util.Date/.Calendar 类的巨大改进。请参阅 java.time 上的Oracle Tutorial。

我将添加一些代码来展示如何使用 java.time 而无需考虑 java.util.Date,以供您开始使用新代码时使用。

简而言之,使用 java.time...Instant 是 UTC 时间线上的一个时刻。应用时区 (ZoneId) 以获取 ZonedDateTime

Month 类是一个复杂的enum,通常代表一个月。该枚举具有方便的方法,例如获取本地化名称。请放心,java.time 中的月份数字是正常的 1-12,而不是 java.util.Date/.Calendar 中的从零开始的废话 (0-11)。

要获取当前日期时间,time zone 至关重要。在任何时候,世界各地的日期都相同。因此,如果接近月底/月初,世界各地的月份就不一样了。

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 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

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

从哪里获得 java.time 类?

Java SE 8Java SE 9Java SE 10 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

【参考方案2】:

如果你不能使用 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));

【讨论】:

你是妈妈! / Είσαι η μάνα!【参考方案3】:

如果使用Java 8 date api,可以直接一行搞定!

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

【讨论】:

一月是 0 还是 1? 这仅返回一位数的值,即您不能在不使用日期或日历的情况下从中形成 mm dd 值【参考方案4】:

java.time (Java 8)

您还可以在 Java 8 中使用 java.time package 并将您的 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 在 cmets 中所说,首选方法是使用 LocalDate::getMonth 方法获取 Month 枚举对象。

【讨论】:

好答案。读者注意:您可能希望指定一个时区,而不是依赖于答案中显示的默认调用。例如,巴黎的新一天(和一个月)比蒙特利尔更早。如果您特别关心蒙特利尔,请使用ZoneId.of( "America/Montreal" ) 我只是想补充一下,有一篇很棒的文章介绍了java.time api oracle.com/technetwork/articles/java/… 顺便说一句,给读者的另一个提示:您也可以获得一个Month枚举对象,而不仅仅是一个整数。 Month m = localDate.gotMonth();LocalDate::getMonth 方法。使用这样的对象可以使您的代码自我记录,确保类型安全,并保证有效值。请参阅 Oracle 的 Enum tutorial。 如果您使用date.toInstant() 并且您恰好在使用java.sql.Datejava.util.Date 的子代),那么您将获得UnsupportedOperationException。试试new java.sql.Date(src.getTime()).toLocalDate() @Adam 使用添加到旧类的新转换方法更容易与java.sql.Date 进行转换。 java.sql.Date.valueOf( myLocalDate )myJavaSqlDate.toLocalDate() 此外,为 JDBC 4.2 或更高版本更新的 JDBC 驱动程序不再需要 java.sql 类型,并且可以通过 ResultSet::getObjectPreparedStatement::setObject 方法直接寻址 java.time 类型。【参考方案5】:
java.util.Date date= new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month = cal.get(Calendar.MONTH);

【讨论】:

请注意,Calendar.MONTH 没有明显的原因是基于零的,即一月==0。现在在 API 中记录得很好,但对于初次使用的用户来说仍然令人困惑。我还没有找到能告诉我他们为什么要这么做的人——也许是时候自己提出一个新的 SO 问题了(尽管我担心没有任何好的背景:/) @Voo Date.getMonth() 方法是从零开始的,这可能是 Calendar.MONTH 也是如此的主要原因。 @Muhd 当然,毕竟它是替代品。但这只会将问题转移到为什么 Date.getMonth() 从零开始? Imo 一个可怕的设计,特别是因为日子从一天开始(它们至少可以保持一致!)。我认为这只是在一个设计得不是特别好的 API(日期和日历)中的一些疏忽。但也许有一些先例 - 这对我来说似乎很奇怪,并且在我的经验中给不止一位初学者造成了问题。 实际上它已经在这里被问过了(而且不仅如此)。底线是 tnat 它是设计糟糕的 API 的结果。我的意思是,正如你提到的,整个 Date 类都是一个笑话。有趣的事实是,不仅 Java 存在这个问题 - iirc javascript 的 Date getMonth() 也以 0 开头! @Voo getYear() 也是,“没有明显原因”,减去 1900。【参考方案6】:

乔达时间

或者,使用 Joda-Time DateTime 类。

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

……或者……

int month = dateTime.getMonthOfYear();

【讨论】:

更简单,只需询问 DateTime 对象的月份。 int month = dateTime.getMonthOfYear(); 好电话巴兹尔,我已经更新了代码。但是,我喜欢.toString("MM"),因为它表明除了“MM”之外还有更多的可能性。 这个答案忽略了时区的关键问题。在问题和兄弟答案中查看我的 cmets。我建议将 DateTimeZone 对象传递给 DateTime 构造函数:DateTimeZone.forID( "America/Montreal" )【参考方案7】:
Date mDate = new Date(System.currentTimeMillis());
mDate.getMonth() + 1

返回值从 0 开始,所以要加一。

【讨论】:

你的答案有两个问题:一个是你可以通过在没有System.currentTimeMillis的情况下使用new Date()来确定当前时间。另一个是不推荐使用 getMonth。 @Muhd 那么最好的解决方案是什么? @Muhd 我这里加的System.currentTimeMillis()是为了说明这里是long类型,具体日期可以。 Date::getMonth 在 Java 1.1 中已被弃用 (cs.mun.ca/~michael/java/jdk1.1-beta2-docs/api/…) 在 Java 12 中已弃用

以上是关于Java:从日期获取月份整数的主要内容,如果未能解决你的问题,请参考以下文章

在java中如何通过一个月份,获得该月份的第一天的日期?

从日期获取月份名称

从jooq中的日期获取月份名称

从 Oracle 中的日期获取月份名称

如何在Java中获取用户出生日期的月份和日期

如何从 SQL Server 中的日期获取月份编号(不是月份名称)?