I'm trying to iterate in my Java program over all weeks between two dates (the end date being today). First, I get the starting date:
Calendar start = Calendar.getInstance();
start = data.getFirstDate(users, threads);
So far, so good. The start date is correct and I can work with it. Now I iterate:
Calendar current = start;
while(current.before(Calendar.getInstance()) {
// Do something
current.add(Calendar.DATE, 7);
}
Well, this kind of works. I start at 2002/8/23, then comes 2002/8/30, then 2002/9/7... UNTIL 2002/11/30. The date after that is 2003/0/6, which is neither correct nor even a valid date!
What am I doing wrong? I tried current.add(Calendar.DATE, 7), current.add(Calendar.WEEK_OF_YEAR, 1), current.add(Calendar.DAY_OF_YEAR, 7) and two other ways. Using current.roll(Calendar.DATE, 7) does not work because I stay in the same month. Using GregorianCalendar has no effect as well.
Any suggestions would be greatly appreciated!
Thanks
Julian
The month field in the Calendar API is 0-based not 1-based. So 0 stands for January. Don't ask me why.
I think your interpretation of the dates is incorrect. The month field is zero-based, i.e. JANUARY is 0. So, 2002/11/30 is DECEMBER 30th.
If you're seeing 0 as a month, that's January since months are 0 index based. 0 is January and 11 is December.
tl;dr
LocalDate.now().plusWeeks( 1 ).isBefore( stopDate )
java.time
The modern answer uses java.time classes rather than Calendar.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
LocalDate weekLater = today.plusWeeks( 1 ) ;
Get your starting date. You may specify the month by a number, with sane numbering 1-12 for January-December, unlike the crazy zero-based numbering in the legacy class.
LocalDate start = LocalDate.of( 2017 , 2 , 23 ) ; // Month is 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year.
LocalDate start = LocalDate.of( 2017 , Month.FEBRUARY , 23 ) ;
From there, looping is just basic Java, using the LocalDate object’s comparison methods: isBefore, isAfter, and isEqual.
LocalDate ld = start ;
while( ld.isBefore( today ) ) {
ld = ld.plusWeeks( 1 ) ;
…
}
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
Related
I need to get the last date of a given month, in my case I need to get the last Date of June. My code is following:
cal.set(Calendar.DAY_OF_MONTH,
Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
int month = cal.get(Calendar.MONTH) + 1;
if (month <= 6) {
cal.set(Calendar.DAY_OF_YEAR, Calendar.getInstance()
.getActualMaximum(Calendar.JUNE));
return (Calendar) cal;
} else {
cal.set(Calendar.DAY_OF_YEAR, Calendar.getInstance()
.getActualMaximum(Calendar.DAY_OF_YEAR));
return (Calendar) cal;
}
At first I get the actual month and wether it's the first half of the year or the second in need another date, always the last date of that half year. With the code above the return is
2015-01-31
and not 2015-06-31 as I thought it should be. How could I possibly fix this?
Your code is all over the place at the moment, unfortunately - you're creating new calendars multiple times for no obvious reason, and you're calling Calendar.getActualMaximum passing in the wrong kind of constant (a value rather than a field).
You want something like:
int month = cal.get(Calendar.MONTH) <= Calendar.JUNE
? Calendar.JUNE : Calendar.DECEMBER;
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calenday.DAY_OF_MONTH));
return cal;
However, I would strongly recommend using java.time if you're on Java 8, and Joda Time if you're not - both are much, much better APIs than java.util.Calendar.
java.time
Much easier now with the modern java.time classes. Specifically, the YearMonth, Month, and LocalDate classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
YearMonth
With a LocalDate in hand, get the year-month of that date.
YearMonth ym = YearMonth.from( ld ) ;
See which half year it is in.
Set < Month > firstHalfOfYear = EnumSet.range( Month.JANUARY , Month.JUNE ); // Populate the set with first six months of the year.
boolean isFirstHalf = firstHalfOfYear.contains( ym.getMonth() );
Knowing which half of the year, get the end of June or the end of December in the same year.
LocalDate result = null;
if ( isFirstHalf ) {
result = ym.withMonth( Month.JUNE.getValue() ).atEndOfMonth();
} else { // Else in last half of year.
result = ym.withMonth( Month.DECEMBER.getValue() ).atEndOfMonth();
}
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
The following code gives the wrong information:
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
public class test {
public static void main(String[] args) {
GregorianCalendar fmt = new GregorianCalendar(2000, 7, 3);
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
String result = df.format(fmt.getTime());
System.out.println("fmt: " + result);
}
}
It outputs:
fmt: 03-Aug-2000
While I need the Month to be July, as I have set the month to 7?
My guess, is that you're expecting the 7th month to be July, but the month value is 0-based, so July would be represented by a 6.
month - the value used to set the MONTH calendar field in the calendar. Month value is 0-based. e.g., 0 for January.
You also probably want to enter the 4-digit date
You'd end up with the following
GregorianCalendar fmt = new GregorianCalendar(1975, 6, 3);
Here's the documentation for GregorianCalendar
As noted by other people, there are two problems in your current code:
Months are zero based. So, month 7 is August, not July =\
Year doesn't start by default at 1900 but at 1970, but if you set the year by yourself you'll get as year the same number you're setting, in this case, 75 (not 1975 as expected).
To solve this, you may create the GregorianCaledar as new GregorianCaledar(1975, 6, 3). Or even better, stop working directly with this class and instead use the abstract class Calendar:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 1975);
calendar.set(Calendar.MONTH, Calendar.JULY);
calendar.set(Calendar.DATE, 3);
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
String result = df.format(calendar.getTime());
System.out.println("fmt: " + result);
Why to use Calendar instead of GregorianCalendar? Because you should always work with abstract class/interface instead of class implementation.
Of course,
You have instantiated the GregorianCalendar to year 75.
What was your purpose?
See the API
http://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html
Also pay attention that in GregorianCalendar the month start from 0
Taken from the JavaDoc above:
"month - the value used to set the MONTH calendar field in the calendar. Month value is 0-based. e.g., 0 for January."
In the GregorianCalendar months are marked from 0 (which represents January), and so do the years. So if you want to represent July 3rd, 1975, you should use:
GregorianCalendar fmt = new GregorianCalendar(1975, 6, 3);
tl;dr
LocalDate.of( 2000 , 7 , 3 )
…or…
LocalDate.of( 2000 , Month.JULY , 3 )
java.time
As already noted, the troublesome old GregorianCalendar has crazy numbering schemes with year, month, and day-of-week. Months are numbered 0-11 for January-December, so August is # 7 rather than # 8. Avoid these old legacy classes like the Plague. Instead, use the modern java.time classes.
Te java.time classes use sane numbering:
2014 means the year 2014. No funky math with 1900.
2 means February, 1-12 for January-December.
1 means Monday, 1-7 for Monday-Sunday per [ISO 8601][1] standard.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 2000 , 7 , 3 ) ; // Years use sane direct numbering (2014 means year 2014). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 2000 , Month.JULY , 3 ) ;
Generate a String in your desired format. Note the Locale argument used to specify the human language and cultural norms to be used in localizing.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) ;
String output = ld.format( f ) ;
03-Jul-2000
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I am trying to figure out how to make my program count the number of Sundays in a week.
I have tried the following thing:
if (date.DAY_OF_WEEK == date.SUNDAY) {
System.out.println("Sunday!");
}
Yet it does not seem to work?
When I try to System.out.Println the date.DAY_OF_WEEK I get: 7
Does anyone know how I can check if the current calendar date is Sunday?
UPDATE FOR MORE INFORMATION
firt of all the date.DAY_OF_WEEK is a Calendar object!
i made sure to set the Calendar object date to a sunday
The system out print where i get 7 is what it returns to me when i try to run date.DAY_OF_MONTH even if the day it set to a sunday
2nd UPDATE TO ALEX
This is more or less my code
Calendar startDate = Calendar.getInstance();
startDate.set(2012, 12, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
}else {
System.out.println("FALSE");
}
Calendar cal = ...;
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("Sunday!");
}
Calendar.DAY_OF_WEEK always equals to 7 no matter what instance of Calendar you are using (see this link), it is a constant created to be used with the Calendar.get() method to retrieve the correct value.
It is the call to Calendar.get(Calendar.DAY_OF_WEEK) that will return the real day of week. Besides, you will find useful values in the Calendar class like Calendar.SUNDAY (and the other days and months) in order for you to be more explicit in your code and avoid errors like JANUARY being equal to 0.
Edit
Like I said, the Calendar class does contains useful constants for you to use. There is no month number 12 they start at 0 (see above), so DECEMBER is month number 11 in the Java Date handling.
Calendar startDate = Calendar.getInstance();
startDate.set(2012, Calendar.DECEMBER, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
} else {
System.out.println("FALSE");
}
Will print true of course.
Note: the Joda-Time project is now in maintenance mode. See this answer if you don't have to work with legacy code.
If you have to work with date or time a lot, you might want to try using Joda-Time.
Your code would look something like this:
LocalDate startDate = new LocalDate(2012, 12, 2);
int day = startDate.dayOfWeek().get(); // gets the day of the week as integer
if (DateTimeConstants.SUNDAY == day) {
System.out.println("It's a Sunday!");
}
You can also get a text string from dayOfWeek():
String dayText = startDate.dayOfWeek().getAsText();
will return the string "Sunday".
tl;dr
boolean todayIsSunday = LocalDate.now( ZoneId.of( "America/Montreal" ) ).getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
java.time
The other Answers are outdated. The modern approach uses java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
DayOfWeek
For any LocalDate, you can obtain its day-of-week as a DayOfWeek object. The DayOfWeek enum automatically instantiates seven objects, one for each day of the week.
boolean isSunday = ld.getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
One Sunday per week
count the number of Sundays in a week.
That would be 1, always one Sunday per week.
If your goal is finding the next Sunday, use a TemporalAdjuster defined in TemporalAdjusters class.
TemporalAdjuster ta = TemporalAdjusters.nextOrSame( DayOfWeek.SUNDAY ) ;
LocalDate nextOrSameSunday = ld.with( ta ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
I'd love your help understanding the following:
Assume that I have a Value of type date
Date start;
How can I chack whether the current date is a week or more since the date of start ?
I tried to chack Java API on the web, and I got confused.
Thank you.
Using calendar you can add days to the start date and then compare it to the current date.
For example:
Date start = Calendar.getInstance().getTime();
start.setTime(1304805094L); // right now...
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, 7);
start.compareTo(cal.getTime());
I would use Joda time for that.
http://joda-time.sourceforge.net/
You can then use this method as a template for what you want to do. The method is an example from the Joda site:
public boolean isRentalOverdue(DateTime datetimeRented) {
Period rentalPeriod = new Period().withDays(2).withHours(12);
return datetimeRented.plus(rentalPeriod).isBeforeNow();
}
tl;dr
whether the current date is a week or more since the date of start ?
LocalDate.now().minusWeeks( 1 ).isAfter( someLocalDate )
java.time
The modern approach uses java.time classes.
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
Specify the other date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
So, is the current date at least a week after the target date?
Calculate a week ago.
LocalDate weekAgo = today.minusWeeks( 1 ) ;
Compare with isBefore, isAfter, and isEqual methods.
Boolean isOverAWeekOld = ld.isBefore( weekAgo ) ;
Bonus: See if the target date is within the past week.
boolean inPastWeek = ( ! ld.isBefore( weekAgo ) ) && ld.isBefore( today ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
Right now is 3/15/11 and when I'm calling a new date object:
Date now = new Date();
I'm getting in return
the month as 2 (getMonth()),
the day as 2 (getDay())
and the year (getYear()) as 111.
Is there a reason for this convention?
Straight from the class's documentation:
A year y is represented by the integer y - 1900.
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
A date (day of month) is represented by an integer from 1 to 31 in the usual manner.
And as for getDay():
Returns the day of the week represented by this date. The returned value (0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday, 5 = Friday, 6 = Saturday) represents the day of the week that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.
March 15th 2011 is in fact a Tuesday.
Is there a reason for this convention?
The reason is that it is what the javadoc for Date specifies; see #matt b's answer.
The Date APIs were created in the days of JDK 1.0, and are well known to be problematic in a number of areas. That is why most of the Date methods are marked as Deprecated. (By the way, that means that it is recommended that you don't use them in new code!!)
The Calendar APIs are a significant improvement on Date, but the best by far APIs for handling date / time values in Java are the 3rd-party Joda time APIs.
If you want examples of Joda time usage, look at the link above. There's an example of Calendar usage in the GregorianCalendar javadocs. More examples of Calendar usage may be found on this page.
tl;dr
LocalDate // Modern class to represent a date-only value, without time-of-day, without time zone or offset-from-UTC.
.now( ZoneId.of( "Africa/Tunis" ) ) // Capture the current date as seen in the wall-clock time used by the people of a specific region (a time zone).
.getYear() // Get year number, such as 2019 presently.
…and:
.getMonthValue() // Get month number, 1-12 for January-December.
…and:
.getDayOfMonth() // Get day-of-month number, 1-31.
Details
Apparently you are using either of two terrible date-time classes, java.util.Date or java.sql.Date. Both are outmoded as of the adoption of JSR 310, defining their replacement, the modern java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Accessing parts of a date
The java.time classes use sane numbering, 1-12 for months, 1-7 for days of the week, the year number such as 2019 is the year 2019, and such.
int year = ld.getYear() ; // The year, such as 2019 presently.
int monthNumber = ld.getMonthValue() ; // Number of the month 1-12 for January-December.
Month month = ld.getMonth() ; // Get the `Month` enum object, one of a dozen predefined objects (one for each month of the year).
int dayOfMonth = ld.getDayOfMonth() ; // Get the day of the month, 1-31.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.