I'm learning the Calendar class in Java and I am unable to understand the Set(Calendar.Day OF MONTH) method.
Here it goes:
import java.util.Calendar;
import java.util.Date
public class TestCalender
{
public static void main(String[] args)
{
Calendar cal = Calendar.getInstance();
Date date= cal.getTime();
System.out.println(date);
cal.set(Calendar.DAY_OF_MONTH,33);
//cal.set(Calendar.MONTH,13);------>(1)
Date newdate = cal.getTime();
System.out.println(newdate);
Output:
Fri May 12 17:30:50 CDT 2017
Fri Jun 02 17:30:50 CDT 2017
When I uncomment the statement(1) the output changes to:
Fri May 12 17:33:22 CDT 2017
Mon Mar 05 17:33:22 CST 2018
Here is my question:
I understood the change of Month to March but I'm not able to figure out why the date has changed to 5. As per my understanding shouldn't the date be changed to April 02 2018 (when 33 days of March is being computed since March has only 31 days the count moves to the month of April).
I will be extremely grateful if someone could help in clearing this doubt.
Thanks in advance.
Regards
Roopa
The Calendar class uses months starting from 0, and ending at 11 for December. Therefore, when you set the month to 13, you specified February of the following year, and the "33rd day of February" (which has 28 days) is the 5th of March.
The java.util.date classes are quirky and hard to use. Use java.time instead.
I'm learning the Calendar class
Don't.
The Calendar class is notoriously troublesome, poorly designed, confusing, and flawed. Now legacy. Supplanted by the java.time classes. We can sweep that class into the dustbin of Java history.
Among its many issues, Calendar uses crazy month numbering 0-11 for January-December. This fact was correctly described in the correct Answer by Kyriacou. The java.time classes, in contrast, use sane numbering 1-12 for Jan-Dec; see the Month enum.
Not quite sure what your goal is in that code snippet, but you seem to be adding 33 days to a date.
The LocalDate class represents a date-only value without time-of-day and without time zone.
One big difference between java.time and the legacy classes is that the modern classes use immutable objects. So adding days to a date results in a new date object with its values based on the original object, while the original object remains untouched. This avoids much confusion, and makes them thread-safe.
LocalDate ld = LocalDate.of( 2017 , Month.MARCH , 23 ) ;
LocalDate later = ld.plusDays( 33 );
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
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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
How to get the fiscal year end date (2017-09-30) dynamically.
Based on the year I need to get the fiscal year end date dynamically.
For example:
If 2017 then output should be 2017-09-30
If 2018 then output should be 2018-09-30 and so on.
Code:
Calendar.getInstance().getActualMaximum(Calendar.SEPTEMBER);
Output I am getting as "4"
Can I know how to get the end date dynamically.
This will help you
private static String getDate(int month, int year) {
Calendar calendar = Calendar.getInstance();
// passing month-1 because 0-->jan, 1-->feb... 11-->dec
calendar.set(year, month - 1, 1);
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
Date date = calendar.getTime();
DateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
return DATE_FORMAT.format(date);
}
Fiscal year?
The term “fiscal year” is not defined here. Usually that is a company-specific definition, and may not be as simple as “end of September”.
Avoid legacy date-time classes
If you are asking for the same month and same day-of-month but adjusted by year, use the java.time classes. The troublesome Calendar class is now legacy, and should be avoided.
LocalDate & MonthDay
The LocalDate class represents a date-only value without time-of-day and without time zone.
The MonthDay class represents a month and day-of-month without any year and without any time zone.
LocalDate ld = LocalDate.of( 2017 , Month.SEPTEMBER , 30 );
MonthDay md = MonthDay.from( ld );
LocalDate ldInAnotherYear = md.atYear( ld.getYear() + 1 );
You could also simply add a year depending on the date in question and what your desired behavior is for handling the last days of a month since months have different lengths, and of course February has the issue of Leap Year.
LocalDate yearLater = LocalDate.of( 2017 , Month.SEPTEMBER , 30 ).plusYears( 1 );
YearMonth
You might find the YearMonth class handy. You can ask it for the last day of the month.
YearMonth ym = YearMonth( 2017 , Month.SEPTEMBER );
LocalDate endOfMonth = ym.atEndOfMonth();
I recommend using objects rather than mere integers. Consider passing around objects such as YearMonth, MonthDay, LocalDate, and Month where appropriate rather than numbers.
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 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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 want to create a calendar object and set it to a certain year and a week in that year.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.WEEK_OF_YEAR, weekOfYear); // 1
calendar.set(Calendar.YEAR, year); // 2016
setWeekChecked(calendar);
This is the toString of the calendar object as I pass it to the setWeekChecked method:
java.util.GregorianCalendar[time=?,areFieldsSet=false,lenient=true,zone=America/New_York,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=2,DAY_OF_MONTH=7,DAY_OF_YEAR=7,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=5,HOUR_OF_DAY=5,MINUTE=25,SECOND=43,MILLISECOND=219,ZONE_OFFSET=-18000000,DST_OFFSET=0]
In the setWeekChecked method:
public void setWeekChecked(final Calendar cal) {
final int targetWeek = cal.get(Calendar.WEEK_OF_YEAR); // Returns 1
final int targetYear = cal.get(Calendar.YEAR); // Returns 2015??
}
This is the toString of the calendar object now:
java.util.GregorianCalendar[time=1451557543219,areFieldsSet=true,lenient=true,zone=America/New_York,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=31,DAY_OF_YEAR=365,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=5,HOUR_OF_DAY=5,MINUTE=25,SECOND=43,MILLISECOND=219,ZONE_OFFSET=-18000000,DST_OFFSET=0]
What am I doing wrong?
I suspect that the calendar is trying to use the current day-of-week (it's Thursday today) in the first week of 2016.
Now, looking at your calendar settings, you've got firstDayOfWeek=1 (so weeks run Sunday to Saturday) and minimalDaysInFirstWeek=1 (so the first week of the year is the one that includes January 1st).
That means that the first week of 2016 in your calendar ran from Decemember 27th 2015 to January 2nd 2016. Therefore Thursday in the first week was December 31st - which is exactly what the calendar you've shown us says.
Fundamentally, calendar arithmetic with "week of year" is tricky because:
There are lots of different culture-specific ways of looking at them
Typically requirements don't specify which of those you're actually interested in
I'd strongly recommend using Joda Time if at all possible to make your date/time-handling code clearer to start with, but you'll still need to work out exactly what you mean by "set it to a certain year and a week in that year". Note that Joda Time separates the concepts of "week-year" (used with week-of-week-year and day-of-week) from "year" (used with month and day-of-month) which helps greatly. You need to be aware that for a given date, the week-year and year may be different.
tl;dr
LocalDate.of( 2016 , Month.JULY , 1 )
.with( IsoFields.WEEK_OF_WEEK_BASED_YEAR , 1 )
Details
The Answer by Jon Skeet is correct. Update: We have a better way.
The java.time classes built into Java 8 and later supplant the troublesome old legacy date-time classes bundled with the earliest versions of Java. And java.time officially supplants Joda-Time, as that project is now in maintenance mode.
As Skeet points out, there are different ways to define week-of-year.
The java.time classes provide support for the standard ISO 8601 definition of week-of-year. This definition is that week number 1 is the first week with a Thursday, and that week starts on a Monday. So the beginning of the week may include one or more days of the previous year, and the last week may include one or more days from the following year. The year always has either 52 or 53 weeks.
See my Answer to a similar Question for more details.
The LocalDate class represents a date-only value without time-of-day and without time zone.
Get a date near the middle of the desired year. That desired year is a week-based year rather than a calendar year, so must avoid the very beginning or ending of the calendar year. In your case, you wanted week-based year of 2016.
LocalDate ld = LocalDate.of( 2016 , Month.JULY , 1 ) ;
Next we adjust that date into the desired week by using IsoFields.WEEK_OF_WEEK_BASED_YEAR.
LocalDate dayIn2016W01 = ld.with( IsoFields.WEEK_OF_WEEK_BASED_YEAR , 1 ) ;
If you want the first day of that week, use another TemporalAdjuster from the TemporalAdjusters class.
LocalDate firstDayOf2016W01 = dayIn2016W01.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) );
Tip: When Android becomes more capable, use the YearWeek class from the ThreeTen-Extra project.
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….
Here is the real calendar now:
March 2015
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
And I get DAY_OF_WEEK of 2015/3/24 like this:
public class TestCalendar {
public static void main(String[] argvs){
Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.set(2015,Calendar.MARCH,24);
System.out.println(cal.get(Calendar.DAY_OF_WEEK));
}
}
Since I have cal.setFirstDayOfWeek to MONDAY the result I expecting is 2, but Whatever day I set to the first day of week(have tried SUNDAY and others) .It kept show me the same result which is 3. So It seemed that firstDayOfWeek won't affect the result.
Have I do something wrong?
EDIT
I just figured and thanks to answers below, that this setFirstDayOfWeek will not affect the result of get(Calendar.DAY_OF_WEEK) nor get(Calendar.WEEK_OF_YEAR)
Then what is this method setFirstDayOfWeek() designed for?
I mean How can I told the program that I want 2015/3/29 be the last day of the 12th week instead of treating it as the first day of the 13th week?
tl;dr
LocalDate.of( 2015 , Month.MARCH , 24 ) // `LocalDate` object for 2015-03-24.
.getDayOfWeek() // DayOfWeek.TUESDAY constant object
.getValue() // 2
Avoid legacy date-time classes
Calendar is a ugly mess, as are its sibling classes. Fortunately these old date-time classes are now legacy, supplanted by the java.time classes.
ISO 8601
If you want Monday as the first day of the week, Sunday the last, numbered 1-7, then use the ISO 8601 calendar used by default in the java.time classes.
DayOfWeek
The DayOfWeek enum hold predefined objects for each of those ISO days of the week. You can interrogate for its number if need be, though generally better to pass around objects of this enum rather than mere integers.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = LocalDate.of( 2015 , Month.MARCH , 24 );
DayOfWeek dow = ld.getDayOfWeek();
int value = dow.getValue(); // 1-7 for Monday-Sunday. But often better to use the `DayOfWeek` object rather than a mere integer number.
For working with other definitions of a week where Monday is not day number one, see the WeekFields class.
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 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.
cal.get(Calendar.DAY_OF_WEEK) will return you which day it is (SUNDAY, MONDAY, etc...) for the given date. So it will return you TUESDAY and then 3, whatever the first day of week is. This has nothing to do with the setFirstDayOfWeek method.
If you want to compute the number of day since the beginning of the week, you just have to get the first day of the week using getFirstDayOfWeek and do some simple math.
setFirstDayOfWeek just tells the Calendar which day is to be considered the first day,i.e., Sunday or Monday or any other day. It will not change the dayOfWeek for any arbitrary date. The javadoc for this method states the following:
public void setFirstDayOfWeek(int value)
Sets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France.
Parameters:
value - the given first day of the week.
I have a requirement like when I insert values into a table in my DB, I need to set target dates which is 3 months apart from the day it was inserted. For Eg: If I insert data on 9th November 2013, My target dates will be 9th Feb 2014, 9th May 2015 and so on. Am storing these target dates in respective columns as well. For this am using Calendar function and adding 3 months to the current instance. Now business does not want my target dates to come on a saturday or Sunday. If it comes, I need to add the required days so that it comes on a weekday.
Any suggestions on how we can do it
Start from what you already know. You know you can use a Calendar to add/subtract values to/from and generate a resulting value....
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.DATE, 9);
cal.set(Calendar.MONTH, Calendar.NOVEMBER);
cal.set(Calendar.YEAR, 2013);
System.out.println("Start at " + cal.getTime());
cal.add(Calendar.MONTH, 3);
System.out.println("End at " + cal.getTime());
Which outputs...
Start at Sat Nov 09 00:00:00 EST 2013
End at Sun Feb 09 00:00:00 EST 2014
Now, you need to use this concept to move the day till it's not a week end. You can get the "day" name using Calendar.DAY_OF_WEEK and simply either add or subtract a day to the Calendar.DATE based on your business rules, for example...
while (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
cal.add(Calendar.DATE, 1);
}
System.out.println("Should end at " + cal.getTime());
Which will (based on the previous example), output...
Should end at Mon Feb 10 00:00:00 EST 2014
Take a closer look at Calendar for more details
java.time
The modern approach uses the java.time classes, extended by the ThreeTen-Extra project.
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate start = LocalDate.of( 2013 , Month.NOVEMBER , 9 ) ;
Step back one day, then ask for the next working day (non-Saturday/Sunday) by using an implementation of TemporalAdjuster found in org.threeten.extra.Temporals.
LocalDate startAgain =
start.minusDays( 1 )
.with( org.threeten.extra.Temporals.nextWorkingDay() ) ;
Add three months for next date. Again, step back a day and ask for next working day.
LocalDate threeMonthsLaterWorkingDay =
startAgain.plusMonths( 3 )
.minusDays( 1 )
.with( org.threeten.extra.Temporals.nextWorkingDay() ) ;
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
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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 have everything setup already to store the current date to a variable in Java. What I am trying to figure out is how to store a date of 1 year after the current date.
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Scanner;
import java.util.Calendar;
Here is what I have for the current date:
DateFormat newDate = new SimpleDateFormat("MM/dd/yyyy");
Date date = new Date();
startDate = newDate.format(date);
So if it were today for example it would store 2/18/2013. I am trying to store the date 2/18/2014. How would I go about doing this?
If you do not want to drag external libraries, just use calendar.add(Calendar.YEAR, 1)
Calendar cal = Calendar.getInstance();
Date today = cal.getTime();
cal.add(Calendar.YEAR, 1); // to get previous year add -1
Date nextYear = cal.getTime();
Note, if the date was 29/Feb/2012 and you added 1 year, you will get 28/Feb/2013
tl;dr
LocalDate.parse(
"2/18/2013" ,
DateTimeFormatter.ofPattern ( "M/d/uuuu" )
).plusYears( 1 )
Details
The accepted Answer is correct, but outdated as of Java 8.
java.time
The java.time framework built into Java 8 and later supplants the troublesome old java.util.Date/.Calendar classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
LocalDate
These new classes include LocalDate, to represent a date-only value with no time-of-day nor time zone.
First we must parse the String input. The java.time formatter uses pattern codes similar to the old classes, but not exactly the same. So be sure to read the new doc carefully.
Padded Zero
Notice that your input String lacks leading zero digit for some values. That means you should use single pattern codes, M and d rather than MM and dd. Double codes means you expect padding zero to always be included for otherwise single-digit values, 02 rather than 2.
String input = "2/18/2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "M/d/uuuu" );
LocalDate localDate = LocalDate.parse ( input , formatter );
Add a year. The java.time framework takes care of leap year.
LocalDate yearLater = localDate.plusYears ( 1 );
Dump to console.
System.out.println ( "localDate: " + localDate + " and yearLater: " + yearLater );
localDate: 2013-02-18 and yearLater: 2014-02-18
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, 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.
Use Calendar#add(int field, int amount) method.You should use Calendar API in-order to manipulate date and time operations.
Calendar today = Calendar.getInstance();
Calendar nextYearToday = today;
nextYearToday.add(Calendar.YEAR, 1);
Calendar cal = Calendar.getInstance();
Date today = cal.getTime();
cal.add(Calendar.YEAR, 1); // to get previous year add 1
cal.add(Calendar.DAY_OF_MONTH, -1); // to get previous day add -1
Date expiryDate = cal.getTime();
System.out.println("today is --> "+today);
System.out.println("expiryDate is --> "+expiryDate);
OutPut
today is --> Fri Dec 01 10:10:52 GMT+05:30 2017
expiryDate is --> Fri Nov 30 10:10:52 GMT+05:30 2018
date today is -> Fri Dec 01 10:10:52 GMT+05:30 2017
expiryDate is -> Fri Nov 30 10:10:52 GMT+05:30 2018
In Android is simpler than ever:
oneYearAfterDate = new Date(date.getTime() + DateUtils.YEAR_IN_MILLIS )