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.Date
、Calendar
和 SimpleDateFormat
。
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 8、Java SE 9、Java SE 10 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 Java 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 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和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.Date
(java.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::getObject
和 PreparedStatement::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:从日期获取月份整数的主要内容,如果未能解决你的问题,请参考以下文章