如何在Java中从月份和年份生成日期?

我需要为信用卡到期日生成一个新的Date对象,我只有一个月和一年,我怎样才能根据这两个生成一个Date? 我需要最简单的方法。 我在这里正在阅读其他一些答案,但它们看起来都太复杂了。

你可以使用java.util.Calendar

 Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.set(Calendar.MONTH, month); calendar.set(Calendar.YEAR, year); Date date = calendar.getTime(); 

java.time

使用Java 8中内置的java.time框架

 import java.time.YearMonth; int year = 2015; int month = 12; YearMonth.of(year,month); // 2015-12 

来自String

 YearMonth.parse("2015-12"); // 2015-12 

使用自定义DateTimeFormatter

 import java.time.format.DateTimeFormatter; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM yyyy"); YearMonth.parse("12 2015", formatter); // 2015-12 

转换YearMonth 转换为更标准的日期表示forms,即LocalDate

 LocalDate startMonth = date.atDay(1); //2015-12-01 LocalDate endMonth = date.atEndOfMonth(); //2015-12-31 

因为你要求java.util.Date ,可能是一个非答案,但它似乎是一个很好的机会,指出大多数使用Java中的日期和时间以及日历的工作可能应该使用Joda-Time库来完成,其中案件

 new LocalDate(year, month, 1) 

浮现在脑海中。

Joda-Time在这个月的日子里有很多其他的好东西。 例如,如果您想知道当月的第一天,您可以写信

 LocalDate firstOfThisMonth = new LocalDate().withDayOfMonth(1); 

在您的注释中,您询问是否将字符串传递给java.util.Date构造函数,例如:

 new Date("2012-09-19") 

不推荐使用此版本的构造函数,因此请勿使用它。 您应该创建日期格式化程序并调用parse 。 这是一个很好的建议,因为你可能会将yearmonth作为整数值,并且需要制作一个好的字符串,正确填充和分隔以及所有这些,这在所有情况下都难以置信。 因此,请使用日期格式化程序,它知道如何完美地处理所有这些内容。

其他早期的答案显示了如何做到这一点。

喜欢

 SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM"); Date utilDate = formatter.parse(year + "/" + month); 

复制来自年,月,日forms或类似的创建java.util.Date对象

 DateTime aDate = new DateTime(year, month, 1, 0, 0, 0); 

从什么是用Java创建日期的正确方法复制?

最常见的方法是使用Date(“YYYY-MM-DD”)构造函数,即使它已被弃用。 这是动态创建日期的最简单方法。 谁决定弃用它的螺丝钉。 万岁(“YYYY-MM-DD”)!!!

不要使用这个答案。 使用Przemek和Ray Toel的答案。 正如Przemek所说,更喜欢使用YearMonth代表年月。 如前所述,如果您必须使用日期,请使用LocalDate ,这是一个没有时间的日期。

如果你绝对不可缺少地需要一个老式的java.util.Date对象用于你无法改变的遗留API,这里有一个简单的方法。 它可能无法正常工作,它可能无法准确地提供您所需的日期,这取决于您的确切要求。

  YearMonth expiration = YearMonth.of(2021, 8); // or .of(2021, Month.AUGUST); Date oldFashionedDateObject = Date.from(expiration .atDay(1) .atStartOfDay(ZoneId.systemDefault()) .toInstant()); System.out.println(oldFashionedDateObject); 

在我的电脑上打印

 Sun Aug 01 00:00:00 CEST 2021 

我们得到的是我当地时区午夜的第一个月 – 更确切地说,是我的JVM的时区设置。 这是对遗留API预期的一个很好的猜测,但它也很危险。 JVM的时区设置可能由程序的其他部分或在同一JVM中运行的其他程序在我们的脚下更改。 换句话说,我们无法确定我们得到了什么。

如果将日期传输到运行不同时区的计算机(例如从客户端到服务器或反之亦然)或运行到其自己的时区的数据库,则时区问题会变得更糟。 您的Date将在上个月的时间内达到约50%的风险。

如果您知道最后所需的时区,则有助于指定例如ZoneId.of("America/New_York")而不是上述代码段中的系统默认值。

如果你的API很宽松,而且只需要在正确的月份内获得一些点,那么你最好在它自己的时区中给它当月的第二个月或第三个月。 以下是如何做前者:

  Date oldFashionedDateObject = Date.from(expiration .atDay(2) .atStartOfDay(ZoneOffset.UTC) .toInstant());