I have a program that needs to start on 1/1/09 and when I start a new day, my program will show the next day.
This is what I have so far:
GregorianCalendar startDate = new GregorianCalendar(2009, Calendar.JANUARY, 1);
SimpleDateFormat sdf = new SimpleDateFormat("d/M/yyyy");
public void setStart()
{
startDate.setLenient(false);
System.out.println(sdf.format(startDate.getTime()));
}
public void today()
{
newDay = startDate.add(5, 1);
System.out.println(newDay);
//I want to add a day to the start day and when I start another new day, I want to add another day to that.
}
I am getting the error found void but expected int, in 'newDay = startDate.add(5, 1);'
What should I do?
The Calendar object has an add method which allows one to add or subtract values of a specified field.
For example,
Calendar c = new GregorianCalendar(2009, Calendar.JANUARY, 1);
c.add(Calendar.DAY_OF_MONTH, 1);
The constants for specifying the field can be found in the "Field Summary" of the Calendar class.
Just for future reference, The Java API Specification contains a lot of helpful information about how to use the classes which are part of the Java API.
Update:
I am getting the error found void but
expected int, in 'newDay =
startDate.add(5, 1);' What should I
do?
The add method does not return anything, therefore, trying to assign the result of calling Calendar.add is not valid.
The compiler error indicates that one is trying to assign a void to a variable with the type of int. This is not valid, as one cannot assign "nothing" to an int variable.
Just a guess, but perhaps this may be what is trying to be achieved:
// Get a calendar which is set to a specified date.
Calendar calendar = new GregorianCalendar(2009, Calendar.JANUARY, 1);
// Get the current date representation of the calendar.
Date startDate = calendar.getTime();
// Increment the calendar's date by 1 day.
calendar.add(Calendar.DAY_OF_MONTH, 1);
// Get the current date representation of the calendar.
Date endDate = calendar.getTime();
System.out.println(startDate);
System.out.println(endDate);
Output:
Thu Jan 01 00:00:00 PST 2009
Fri Jan 02 00:00:00 PST 2009
What needs to be considered is what Calendar actually is.
A Calendar is not a representation of a date. It is a representation of a calendar, and where it is currently pointing at. In order to get a representation of where the calendar is pointing at at the moment, one should obtain a Date from the Calendar using the getTime method.
If you can swing it requirement wise, move all your date/time needs to JODA, which is a much better library, with the added bonus that almost everything is immutable, meaning multithreading comes in for free.
Related
I am facing a weird behavior of java.util.Calendar.
The problem is when I add a method call Calendar#getTime() in between only than I get correct result but when I directly get the Dates of the week without calling Calendar#getTime() it refers to the next week instead of current week.
Please consider following code snippet :
public class GetDatesOfWeek {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Calendar cal = Calendar.getInstance();
cal.set(1991, Calendar.DECEMBER, 11);
//System.out.println(cal.getTime());//LINE NO : 14
for(int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) {
cal.set(Calendar.DAY_OF_WEEK, i);
Date date = cal.getTime();
System.out.println(sdf.format(date));
}
}
}
When I uncomment the line no 14 I get following output :
Wed Dec 11 07:38:06 IST 1991
08-12-1991
09-12-1991
10-12-1991
11-12-1991
12-12-1991
13-12-1991
14-12-1991
But when I comment that line and execute the code I get following output.
15-12-1991
16-12-1991
17-12-1991
18-12-1991
19-12-1991
20-12-1991
21-12-1991
Note that in both the cases month and year fields are proper but the start date changed from 08-12-1991 to 15-12-1991 for me 08-12-1991 is correct.
My Question :
Why I am getting different dates of the week in the above two cases ?
Why this kind of functionality is provided in Java ?
If you step through your code in a debugger, you will see interesting things happen to the internal variables of the cal object.
The calendar object stores both the time it represents and adjustment fields separately. After executing line 12, the cal object is constructed with the current time and no adjustment fields, and its internal variable isTimeSet is set to true. This means that the internal time stored is correct.
Executing line 13 clears isTimeSet to false because now the internal time needs to be adjusted by the adjustment fields before it is accurate again. This doesn't happen immediately, rather it waits for a call to getTime() or get(...), getTimeInMillis(), add(...) or roll(...).
Line 14 (if uncommented) forces the internal time to be recalculated using the adjustment fields, and sets the isTimeSet variable to true again.
Line 17 then sets another adjustment field, and unsets the isTimeSet variable again.
Line 18 recalculates the correct time again, based on the adjustment field set in line 17.
The solution:
The problem occurs when you combine setting the day-of-month with the day-of-week. When the day-of-week is set, the day-of-month setting is ignored, and the current day-of-month in the cal object is used as a starting point. You happen to be getting a week starting on the 15th because today's date is the 12th and 15th Dec 1991 is the nearest Sunday to 12th Dec 1991.
Note: If you run your test again in a week's time, you will get a different result.
The solution is to call getTimeInMillis() or getTime() to force recalculation of the time before setting day-of-week adjustments.
Testing:
If you don't want to wait a week to test again, try the following:
public class GetDatesOfWeek {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Calendar cal = Calendar.getInstance();
cal.set(2015, Calendar.AUGUST, 1); // adjust this date and see what happens
cal.getTime();
cal.set(1991, Calendar.DECEMBER, 11);
//System.out.println(cal.getTime());//LINE NO : 14
for(int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) {
cal.set(Calendar.DAY_OF_WEEK, i);
Date date = cal.getTime();
System.out.println(sdf.format(date));
}
}
}
The date is selected by the user using a drop down for year, month and day. I have to compare the user entered date with today's date. Basically see if they are the same date. For example
the user entered 02/16/2012. And if today is 02/16/2012 then I have to display a message. How do I do it?
I tried using milliseconds but that gives out wrong results.
And what kind of object are you getting back? String, Calendar, Date? You can get that string and compare it, at least that you think you'll have problems with order YYYY MM DD /// DD MM YYY in that case I suggest to create a custom string based on your spec YYYYMMDD and then compare them.
Date d1 = new Date();
Date d2 = new Date();
String day1 = d1.getYear()+"/"+d1.getMonth()+"/"+d1.getDate();
String day2 = d2.getYear()+"/"+d2.getMonth()+"/"+d2.getDate();
if(day1.equals(day2)){
System.out.println("Same day");
}
Dates in java are moments in time, with a resolution of "to the millisecond". To compare two dates effectively, you need to first set both dates to the "same time" in hours, minutes, seconds, and milliseconds. All of the "setTime" methods in a java.util.Date are depricated, because they don't function correctly for the internationalization and localization concerns.
To "fix" this, a new class was introduced GregorianCalendar
GregorianCalendar cal1 = new GregorianCalendar(2012, 11, 17);
GregorianCalendar cal2 = new GregorianCalendar(2012, 11, 17);
return cal1.equals(cal2); // will return true
The reason that GregorianCalendar works is related to the hours, minutes, seconds, and milliseconds being initialized to zero in the year, month, day constructor. You can attempt to approximate such with java.util.Date by using deprecated methods like setHours(0); however, eventually this will fail due to a lack of setMillis(0). This means that to use the Date format, you need to grab the milliseconds and perform some integer math to set the milliseconds to zero.
date1.setHours(0);
date1.setMinutes(0);
date1.setSeconds(0);
date1.setTime((date1.getTime() / 1000L) * 1000L);
date2.setHours(0);
date2.setMinutes(0);
date2.setSeconds(0);
date2.setTime((date2.getTime() / 1000L) * 1000L);
return date1.equals(date2); // now should do a calendar date only match
Trust me, just use the Calendar / GregorianCalendar class, it's the way forward (until Java adopts something more sophisticated, like joda time.
There is two way you can do it. first one is format both the date in same date format or handle date in string format.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String date1 = sdf.format(selectedDate);
String date2 = sdf.format(compareDate);
if(date1.equals(date2)){
}else{
}
Or
Calendar toDate = Calendar.getInstance();
Calendar nowDate = Calendar.getInstance();
toDate.set(<set-year>,<set-month>,<set-date->);
if(!toDate.before(nowDate))
//display your report
else
// don't display the report
Above answers are correct but consider using JodaTime - its much simpler and intuitive API.
You could set DateTime using with* methods and compare them.
Look at this answer
i'm retrieving a strange result:
First i get current date using GregorianCalendar:
GregorianCalendar g = new GregorianCalendar();
int m = g.get(Calendar.DAY_OF_MONTH);
int d = g.get(Calendar.DAY_OF_WEEK);
int y = g.get(Calendar.YEAR);
Then i create new object Date:
Date d = new Date(d,m,y);
Then i print them together in this way:
System.out.println(d+" - "+m+" - "+y+" - "+d);
and i get:
1 - 18 - 2012 - Thu Jan 02 00:00:00 CET 1908
can you explain me why? is for deprecated method Date(day,mouth,year) ?
if yes, how can i compare two Date using that parameters?
Then i create new object Date:
Date d = new Date(d,m,y);
The order of the arguments to the constructor is year, month, date, nothing else.
From the documentation:
Date(int year, int month, int day)
how can i compare two Date using that parameters?
Depends on how you want to compare two Dates. If you just want to figure out which comes first, you could use Date.before and Date.after.
But as you've noted, the Date class is deprecated. Use the Calendar class instead, (or better yet, the Joda Time library)
If you need to obtain a new Date object from a GregorianCalendar, do this:
Date d = g.getTime();
In this way, you won't have to use deprecated methods, and the result will be the one you expect. Also, if you need to obtain the current date, simply write new Date(), no need for a GregorianCalendar.
As far as date comparisons go, you can use Date's compareTo(), after() and before() methods. Again, there's no need for a GregorianCalendar.
Create a Calendar, then set the time using the Date object, then you can get any information you need from it.
Example:
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int day = cal.get(Calendar.DAY_OF_MONTH);
// and so on....
My program needs to represent this date as a java.sql.date object , but it seems that when I create a new date (using the calendar) and set it to '9999-12-31' and finally convert this java.util.date object to a java.sql.date object, this date is converted to something like '000-01-31'.
Calendar calendar = Calendar.getInstance();
calendar.set(9999, 12, 31);
infinityDate = new java.sql.Date(normalizeDate(calendar.getTime()).getTime());
infinityDate should be 31-12-9999
but when my code reaches here :
if(otherDate.equals(infinityDate))
{// Do stuff}
It never goes into the if condition as the infinityDate has for some reason been changed to 31-01-000, even though otherDate is infact '31-12-9999'.
The fact that otherDate is 31-12-9999 tells me that java can represent this dates , but for some reason , when I construct it using a calendar it changes the date. (otherDate comes from a jdbc statement which fetches data from a database)
This reference date '31-12-9999' has been fixed by some client , so it cannot be changed and my program has to be able to compare some incoming date values with this.
Does anyone know why this is happening , I realize that http://en.wikipedia.org/wiki/Year_10,000_problem may be a problem for dates after year 9999 , but I should be safe by a day.
EDIT : The Normalize date method only "normalizes the given date to midnight of that day"
private static java.util.Date normalizeDate(java.util.Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
date = calendar.getTime();
return date;
}
But , this issue was appearing before I was normalizing the date , I normalized it in an attempt to fix this.
Months are zero indexed. Use 11 for December, not 12. This is why you are rolling over the year.
Calendar.MONTH is zero-based. The call
calendar.set(9999, 12, 31);
sets the date to "the 31st day in the 13th month of the year 9999", which is then implicitly converted to the 1st month of the year 10000. It would result in an exception if you first called
calendar.setLenient(false);
Check hours, minutes, seconds and milliseconds that are held into these 2 date objects. I believe they are different.
If your want to compare the date (year, month, day) only you should probably create your custom Comparator and use it.
I came across a comment in some java code that states that getTime() needs to be called to update the Calendar object. Is this true? I cannot find anything that says that this is necessary.
Here's the code:
Calendar cal = new GregorianCalendar();
cal.setFirstDayOfWeek(Calendar.SUNDAY);
cal.set(2009, 9 - 1, 10, 2, 30);
// Get Time needs to be called to update the Calendar object
cal.getTime();
cal.getTime() does indeed need to be called to re-calculate its internals. It is very strange behavior for the API but the Calendar javadocs state this explicitly:
Getting and Setting Calendar Field Values
The calendar field values can be set by calling the set methods. Any
field values set in a Calendar will not be interpreted until it needs
to calculate its time value (milliseconds from the Epoch) or values of
the calendar fields. Calling the get, getTimeInMillis, getTime, add
and roll involves such calculation.
...
Field Manipulation
The calendar fields can be changed using three methods: set(), add(),
and roll(). set(f, value) changes calendar field f to value. In
addition, it sets an internal member variable to indicate that
calendar field f has been changed. Although calendar field f is
changed immediately, the calendar's time value in milliseconds is not
recomputed until the next call to get(), getTime(), getTimeInMillis(),
add(), or roll() is made. Thus, multiple calls to set() do not trigger
multiple, unnecessary computations. As a result of changing a calendar
field using set(), other calendar fields may also change, depending on
the calendar field, the calendar field value, and the calendar system.
In addition, get(f) will not necessarily return value set by the call
to the set method after the calendar fields have been recomputed. The
specifics are determined by the concrete calendar class.
The behavior is unexpected and does not always occur but the following unit tests should exemplify this behavior and always occur.
/**
* Fails the assertion due to missing getTime()
* #throws ParseException
*/
public class DateTest {
#Test
public void testNoGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
//testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
#Test
public void testWithGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
}
#skaffman Answer is NOT CORRECT.
Here is an example which proves what I am saying.
//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());
//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());
This is the Log.d output:
Now : java.util.GregorianCalendar[time=1478834995641,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0] Calendar.DAY_OF_MONTH,1:
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=?,areFieldsSet=false,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0]
If you take time to check it:
The calendar at the beginning shows:
time=1478834995641
DAY_OF_MONTH=10
DAY_OF_YEAR=315
However, when you set it to the first day of the month:
time=?
DAY_OF_MONTH=1
DAY_OF_YEAR=315
Yes, it changed the first day of the month as we wanted, nevertheless some attributes remain the same. For instance, how it comes we set the calendar to DAY_OF_MONTH=1 but we are still in DAY_OF_YEAR=315.
If we use any of the following functions, it will force the Calendar to update.
Calling the get, getTimeInMillis, getTime, add and roll.
From the Calendar Class in Javadocs Check :Getting and Setting Calendar Field Values
To fix it, we add the following code calendar.getTimeInMillis(); which forces the Calendar to update its attributes.
//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());
//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
//UPDATE BY CALLING getTimeInMillis() or any of the previously mentioned functions
calendar.getTimeInMillis();
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());
Now, lets Check Results:
Now : java.util.GregorianCalendar[time=1478836452183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=0]
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=1478055252183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=45,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=306,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]
Therefore, #skaffman Answer is not correct, as for your question Calendar.getTime(); indeed is needed if you do not want to get weird values at some point.
You could be hitting Bug ID 4851640
Calling get(...) / getTime() on a Calendar instance makes isSet(...) useless!
No, this is not true.
No, it should not be necessary.
Was the Calendar serialized immediate afterwards?
I've been caught by a bug with Calendar serialization in older jvms.
Bug parade bug #4328747
Calling getTime before serialization may be enough to get around the bug, although I don't have a sufficiently old JVM installed for me to confirm that.