-1

I have this code:

Date date = new Date(2020, 11, 1);

System.out.println(date); // Wed Dec 01 00:00:00 XXX 3920
System.out.println(date.getYear()); // 2020
System.out.println(date.getMonth()); // 11
System.out.println(date.getDay()); // 3

As can be seen, it prints year 3920 instead of 2020. Why does it happen? Any way to fix it without radically changing the code?

PS I know the constructor and the getter methods are deprecated. Unless that is the reason for the wrong output, I'd prefer to keep using them in this particular example.

parsecer
  • 4,758
  • 13
  • 71
  • 140
  • 4
    So, from the `Date` constructor, it's doing `int y = year + 1900;`, so you "should" be doing `new Date(120, 11, 1);`, but then this leads to `getYear` returning `120` - so, which "problem" to you want to live with? – MadProgrammer Apr 04 '22 at 22:15
  • 1
    I would strongly suggest moving away from `java.util.Date` and use the newer `java.time` API. @MadProgrammer already provided the reason for this. – Jetto Martínez Apr 04 '22 at 22:16
  • 1
    Yeah, don't use those methods. They're deprecated for a reason. If you look at the Javadocs, the constructor automatically adds 1900 to the year, so that you can use it for two-digit years. And the `getYear` automatically subtracts 1900, so that it returns a two-digit year. In other words, Java, although invented in the 1990s, came with its very own Y2K issue. – Dawood ibn Kareem Apr 04 '22 at 22:17

1 Answers1

3

tl;dr

LocalDate.of( 2020, Month.DECEMBER, 1 ) 

Avoid legacy date-time classes

You are using a terrible date-time class, Date, which has many tragic design flaws. One of those flaws is an offset of 1900 years.

The solution is simple: Stop using that class. It is now legacy, supplanted years ago by the modern java.time classes defined in JSR 310.

Plus, the java.util.Date class does not fit your need. That class represents a moment, a date with time of day as seen in UTC, an offset of zero hours minutes seconds. But you want a date-only, without time of day, without the context of an offset or time zone.

The other Date,java.sql.Date class, pretends to fit your need as a date-only value. But actually that class inherited from java.util.Date in an extremely poor design choice.

Use LocalDate

Instead, use java.time.LocalDate.

This class uses sane numbering:

  • The year 2020 is 2020.
  • The months January through December are 1 to 12.

Instantiate via static factory methods.

LocalDate ld = LocalDate.of( 2020, 12, 1 ) ;

Or use the Month enum.

LocalDate ld = LocalDate.of( 2020, Month.DECEMBER, 1 ) ;

Interrogate for parts.

int y = ld.getYear() ;
int m = ld.getMonthValue() ;
String month = ld.etMonth().getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) ;
int d = ld.getDayOfMonth() ;
String dow = ld.getDayOfWeek().getDisplayName( TextStyle.FULL , Locale.JAPAN ) ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154