How to generate a Date from just Month and Year in Java?

前端 未结 6 2153
深忆病人
深忆病人 2021-02-12 11:30

I need to generate a new Date object for credit card expiration date, I only have a month and a year, how can I generate a Date based on those two? I need the easiest way possib

6条回答
  •  说谎
    说谎 (楼主)
    2021-02-12 12:12

    Don’t use this answer. Use the answers by Przemek and Ray Toel. As Przemek says, prefer to use a YearMonth for representing year and month. As both say, if you must use a date, use LocalDate, it’s a date without time of day.

    If you absolutely indispensably need an old-fashioned java.util.Date object for a legacy API that you cannot change, here’s one easy way to get one. It may not work as desired, it may not give you exactly the date that you need, it depends on your exact requirements.

        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);
    

    On my computer this prints

    Sun Aug 01 00:00:00 CEST 2021
    

    What we got is the first of the month at midnight in my local time zone — more precisely, my JVM’s time zone setting. This is one good guess at what your legacy API expects, but it is also dangerous. The JVM’s time zone setting may be changed under our feet by other parts of the program or by other programs running in the same JVM. In other words, we cannot really be sure what we get.

    The time zone issue gets even worse if the date is transmitted to a computer running a different time zone, like from client to server or vice versa, or to a database running its own time zone. There’s about 50 % risk that your Date will come through as a time in the previous month.

    If you know the time zone required in the end, it will help to specify for example ZoneId.of("America/New_York") instead of the system default in the above snippet.

    If your API is lenient and just needs some point within the correct month, you’ll be better off giving it the 2nd of the month UTC or the 3rd of the month in your own time zone. Here’s how to do the former:

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

提交回复
热议问题