44

I am having a bit of trouble parsing a string date to a Date object. I use a DateFormat to parse the string, and when I print the value of the date, it gives me what I expect.

But when I try get the day, the month or the year it gives me the wrong values. For instance, the year is 2011, but when I do .getYear() it gives me 111. I have no idea why this is happening. Here is the relevant code segment:

    Date dateFrom = null;

    String gDFString = g.getDateFrom();

    System.out.println(gDFString);

    DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

    try {
        dateFrom = df.parse("04/12/2011");

        System.out.println(dateFrom);

        System.out.println(dateFrom.getYear());
    } catch (ParseException e) {
        e.printStackTrace();
    }

When I out print dateFrom, I get Sun Dec 04 00:00:00 GMT 2011, which is what you would expect. But printing .getYear() returns 111.

I need to be able to get the day, month and year of the date for a time series graph.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Ben Calder
  • 457
  • 1
  • 4
  • 3
  • 25
    It hasn’t even *once* occured to you to read the documentation of [Date.getYear()](http://download.oracle.com/javase/6/docs/api/java/util/Date.html#getYear(%29) which clearly states that it returns “the year represented by this date, minus 1900“? – Bombe Aug 27 '11 at 16:17
  • 5
    Many programmers (including me) would expect year 2011 to be parsed as 2011, not 2011 - 1900 for sure. i think it's Java's implementation which is weird (no matter what internal reasons are behind it), not the OP. – Can Poyrazoğlu Jul 04 '16 at 14:12

6 Answers6

46

Those methods have been deprecated. Instead, use the Calendar class.


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public final class DateParseDemo {
    public static void main(String[] args){
         final DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
         final Calendar c = Calendar.getInstance();
         try {
             c.setTime(df.parse("04/12/2011"));
             System.out.println("Year = " + c.get(Calendar.YEAR));
             System.out.println("Month = " + (c.get(Calendar.MONTH)));
             System.out.println("Day = " + c.get(Calendar.DAY_OF_MONTH));
         } 
         catch (ParseException e) {
             e.printStackTrace();
         }
    }
}

Output:

Year = 2011
Month = 3
Day = 12

And as for the month field, this is 0-based. This means that January = 0 and December = 11. As stated by the javadoc,

Field number for get and set indicating the month. This is a calendar-specific value. The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0; the last depends on the number of months in a year.

mre
  • 43,520
  • 33
  • 120
  • 170
  • Not just you, @Ich – Erik Apr 04 '17 at 17:29
  • I dont know why they do 0 - Jan 11- Dec.. need to do several ugly step just to change the month position to match the index.. – ZeroOne Dec 14 '17 at 04:00
  • 1
    @Ich Yes, the old date-time classes bundled with the earliest versions of Java are an awful mess. That is why they are now legacy, supplanted by the *java.time* classes built into Java 8 and later. For earlier Android, see the *ThreeTen-Backport* and *ThreeTenABP* projects. – Basil Bourque Jan 24 '18 at 22:38
12

Javadoc to the rescue:

Deprecated. As of JDK version 1.1, replaced by Calendar.get(Calendar.YEAR) - 1900.

Returns a value that is the result of subtracting 1900 from the year that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.

You should not use deprecated methods. Deprecated methods are methods which should not be used anymore. But whatever the method you're using, read its javadoc to know what it does.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
9

President Evil nailed it, Date.getYear() returns a value that is the result of subtracting 1900 from the year that contains. And you you shouldn't use it.

But quick fix for the code in the question is:

Date dateFrom = null;

String gDFString = g.getDateFrom();

System.out.println(gDFString);

DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

try {
    dateFrom = df.parse("04/12/2011");

    System.out.println(dateFrom);

    // Add 1900 to dateFrom.getYear() 

    System.out.println(dateFrom.getYear()+1900);
} catch (ParseException e) {
    e.printStackTrace();
}
Anthon
  • 69,918
  • 32
  • 186
  • 246
Dimitar Pavlov
  • 300
  • 3
  • 10
4

tl;dr

int year = 
    LocalDate.parse( 
        "04/12/2011" , 
        DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.US ) 
    ).getYear() ;  

2011

java.time

The troublesome java.util.Date class and its siblings are now supplanted by the excellent java.time classes.

String input = "04/12/2011";
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
LocalDate ld = LocalDate.parse( input , f );

The java.time classes utilize sane numbering, with:

  • Months 1-12 for January-December
  • 2011 means 2011
  • Days of week are 1-7 for Monday-Sunday (per ISO 8601).

Interrogate the LocalDate for its constituent parts.

int year = ld.getYear();  // 2011
int month = ld.getMonthValue();  // 4
int dayOfMonth = ld.getDayOfMonth();  // 12

You can even ask for automatically localized name of month and name of day-of-week.

String monthName = ld.getMonth().getDisplayName( TextStyle.FULL_STANDALONE , Locale.CANDA_FRENCH ); // avril

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
4

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Date.html#getYear%28%29

The specification states that it returns the year minus 1900. Probably a good idea to avoid deprecated methods as well.

3

This is only a guess, but the 111 could be the number of years since 1900. Take a look at documentation/do some tests to verify this (I can't check at the moment)

epochengine
  • 2,072
  • 17
  • 21