Java Calendar returns wrong month - java

I want store a date into a Calendar Object, like this:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.MONTH, Calendar.JUNE);
cal.set(Calendar.DAY_OF_YEAR, 26);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
All values are set correctly, except the month and if I call cal.getTime() it returns:
Thu Jan 26 10:00:00 CET 2017
What am I doing wrong?

When you use DAY_OF_YEAR you set the number day of the current year.
https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_YEAR
DAY_OF_YEAR Field number for get and set indicating the day number
within the current year.
This overrides all sensible configuration like month or year (to current year and month of the number day).
So instead of use DAY_OF_YEAR you may use DAY_OF_MONTH which seems is what you are looking for, this sets the day of the month you set before.
https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_MONTH
DAY_OF_MONTH Field number for get and set indicating the day of the month. This is a synonym for DATE. The first day of the month has value 1.
So the configuration you are looking for definetively seems it would be like next:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.MONTH, Calendar.JUNE);
cal.set(Calendar.DAY_OF_MONTH , 26);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Then when you call getTime you will get:
Mon Jun 26 11:00:00 CEST 2017

As mentioned in "Why Java Calendar set(int year, int month, int date) not returning correct date?" this is an easy way to initialize a Calendar Object.
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(2017, Calendar.JUNE, 26, 9, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
System.out.println(cal.getTime());
Mon Jun 26 11:00:00 CEST 2017

Related

Why Calendar.getActualMaximum does not work

I want to get the max date of one month, that it's does't work in some day like the code, it's appear by condition as below
February has problem 2017 Feb Max is 28,If your computer's date is larger than 28, like 2017-03-29 or 2017-04-30
Date date = PrimeUtil.formatStringToTime("2017-02","yyyy-MM");
System.out.println(date);
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,date.getYear());
c.set(Calendar.MONTH,date.getMonth());
c.set(Calendar.DAY_OF_MONTH,c.getActualMaximum(Calendar.DAY_OF_MONTH));
System.out.println(c.getTime());
I had your problem. The problem is that when you set the month, the day is shifted if needed.
I had a method:
public static Date getLastDayOfMounth(int month){
Calendar cTemp = Calendar.getInstance();
// here is where I need to set the day
cTemp.set(Calendar.MONTH, month);
cTemp.set(Calendar.DAY_OF_MONTH, cTemp.getActualMaximum(Calendar.DAY_OF_MONTH));
return cTemp.getTime();
}
I had a test unit for the method that test the method for each month, from 0 to 11. It has workt until today.
Today, 29 March 2018, the test case gone on error for february... why?
First cTemp = 29/03/2018 (today)
then cTemp.set(Calendar.MONTH, 1); is 29/02/2018 but this day does not esists, so became 01/03/2018
then cTemp.getActualMaximum(Calendar.DAY_OF_MONTH) is the last day of march.
I solved adding
cTemp.set(Calendar.DAY_OF_MONTH, 1);
before setting the month. So I start always from first day, avoid problem of skipping to the next month.
I solve the problem by myself,I flow the resource code find that If put February, and use c.set(Calendar.MONTH, date.getMonth()) that the GregorianCalendar have return a wrong time, it's maybe a bug of Calendar, I change my code like below, it will work well
Date date = PrimeUtil.formatStringToTime("2017-02","yyyy-MM");
System.out.println(date);
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.DAY_OF_MONTH,c.getActualMaximum(c.DAY_OF_MONTH));
System.out.println(c.getTime());
the console will print:
Wed Feb 01 00:00:00 CST 2017
Tue Feb 28 00:00:00 CST 2017
It's looks like cause by the mythod c.set(Calendar.MONTH, date.getMonth());
I wasn't changing DAY_OF_MONTH, so as the current date is 29 March 2019, even I change month to February, but in 2019, February has only 28 days, so even after changing month to Feb, it was still considering March, to resolve this I have to set DAY_OF_MONTH to 1.
private fun getLengthOfMonth(year: Int, month: Int): Int {
val calendar = Calendar.getInstance()
calendar.set(Calendar.YEAR, year)
calendar.set(Calendar.MONTH, month - 1)
calendar.set(Calendar.DAY_OF_MONTH,1)
return calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
}
Your case: the value of date is "2017-02", the value of c is: "2017-03-30"
date: 2017-02
c: 2017-03-30
c.set(Calendar.YEAR, date.getYear());
c.set(Calendar.MONTH, date.getMonth());
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
=>
c.set(Calendar.YEAR, 2017);
c.set(Calendar.MONTH, 2);
c.set(Calendar.DAY_OF_MONTH, 31);
Here set 31 to DAY_OF_MONTH, Which could not get what you expected!
Another case:
the value of date is "2017-04", the value of c is: "2017-03-31"
date: 2017-04
c: 2017-05-31
When we set 31 to DAY_OF_MONTH, we will not get what we expected.

Parsing zero-based month strings in java

I am trying to parse a String that looks like:
2015, 2, 31, 17, 0, 1
so i figured I'll use
SimpleDateFormat("yyyy, MM, dd, hh, mm, ss")
but it assumed the months are 1-based. In this case the month (2) is March. How can i tell SimpleDateFormat or any other class to parse with zero-based months?
Use Calendar:
String[] yourString = "2015, 2, 31, 17, 0, 1".split(",");
Calendar c = new GregorianCalendar();
c.set(Calendar.YEAR, Integer.valueOf(yourString[0]));
c.set(Calendar.MONTH, Integer.valueOf(yourString[1]));
c.set(Calendar.DAY_OF_MONTH, Integer.valueOf(yourString[2]));
c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(yourString[3]));
c.set(Calendar.MINUTE, Integer.valueOf(yourString[4]));
c.set(Calendar.SECOND, Integer.valueOf(yourString[5]));
One solution i can see increase one month with
Date newDate = DateUtils.addMonths(new Date(), 1);
With calendar
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 1);
By default months are 0 based index. see
Why is January month 0 in Java Calendar?
Why are months off by one with Java SimpleDateFormat?

Calculate time difference between current and future time

I want to calculate time difference in milliseconds from current time of a day(11 am , 1 october,2012) and time at midnight for the same day (11 pm 59 m 59s , 1 october , 2012.
I have tried this
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 59);
cal.add(Calendar.HOUR, 23);
cal.add(Calendar.MINUTE, 59);
cal.getTime().getTime() - today.getTime();
here today is the current date.
But when i print long values of cal and today , the time difference if of 86400 approx one day.
Use cal.set() instead of cal.add()
Calendar cal = Calendar.getInstance();
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.HOUR, 23);
cal.set(Calendar.MINUTE, 59);
long diff = cal.getTime().getTime() - today.getTime();
You can set your date to newly created Calendar instance..
And then compare it with current instance using getTimeInMillis()
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.DATE, 1);
cal.set(Calendar.MONTH, 9);
cal.set(Calendar.YEAR, 2012);
long difference = cal.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();

How to check If the system Date is 30 days back

How to check in java whether the system Date is 30 days back
Means for example if today is May 26 then if i pass April 26 , it should tell that this is of Last Month Data
If(SystemDate-30)
http://joda-time.sourceforge.net/faq.html#datediff
Calendar cal = Calendar.getInstance();
cal.setTime(startDate);
cal.add(Calendar.DATE, -30);
cal.set(HOUR, 0);
cal.set(MINUTE, 0);
cal.set(SECOND, 0);
cal.set(MILLISECOND, 0);
Date dateBefore30DayFromStartDate = cal.getDate();
Now you can compare

Why does GregorianCalendar.getInstance contain a calsys and cdate of type Julian Calendar

I tried to do set date value to a PreparedStatement with default value but the value is sometimes returned as a JulianValue. For example (Assume spanBegin and spanEnd are null)
Calendar cal = new GregorianCalendar();
if (spanBegin == null) {
cal.set(0000, Calendar.JANUARY, 1);
spanBegin = cal.getTime();
}
if (spanEnd == null)
{
cal.set(9999, Calendar.DECEMBER, 31);
spanEnd = cal.getTime();
}
On line number 3, since the date January 1, 0000 is scoped by a Julian Calendar, the CDate becomes a Julian Calendar. However, the next Date even if it is in the year 9999, its CDate becomes a Julian Calendar still. I had to create another instance of Gregorian Calendar to fix the issue.
Calendar cal = new GregorianCalendar();
if (spanBegin == null) {
cal.set(0000, Calendar.JANUARY, 1);
spanBegin = cal.getTime();
}
Calendar cal = new GregorianCalendar();
if (spanEnd == null)
{
cal.set(9999, Calendar.DECEMBER, 31);
spanEnd = cal.getTime();
}
The question is, is the this an expected behavior or a bug on the date object? Actually using GregorianCalendar.getInstance() shows that the cdate is sometimes set to JulianCalendar.
There was no Gregorian Calendar until 1582. The Julian calendar was in use all over Europe, until minor problems started to appear caused by the fact the solar year is not exactly 365.25 days, but a little less than that. In order to fix things, pope Gregory XIII ordered to change the calendar to what we know today - every year that divides by 100 is not a leap year, unless it divides by 400. In October 1582 there was the transition - the day after 4 Oct was 15 Oct. This means that until October 1582, the Gregorian and Julian Calendars are the same. You can read more about it here
This is why dates prior to Oct 1582 are converted to use the Julian system. According to the API If you actually need to represent an historical event (which seems not to by the case here) you can do it only from 1st march, 4AD
What version of Java are you using and on what OS? Do you really need to store dates in the years 0 and 9999, or are you just using these as "negative infinity" and "positive infinity" values? How exactly do you see that the calendar is a Julian calendar?
I tried this:
Calendar cal = Calendar.getInstance();
cal.set(0, Calendar.JANUARY, 1);
Date d1 = cal.getTime();
cal.set(9999, Calendar.DECEMBER, 31);
Date d2 = cal.getTime();
System.out.println(d1);
System.out.println(d2);
Output (on Windows XP, using Sun Java 1.6.0_16):
Thu Jan 01 09:53:56 CET 1 java.util.Date
Tue Dec 31 09:53:56 CET 9999 java.util.Date
It changes the year 0 to the year 1. Changing the code to use a second Calendar object for the second date:
Calendar cal = Calendar.getInstance();
cal.set(0, Calendar.JANUARY, 1);
Date d1 = cal.getTime();
Calendar cal2 = Calendar.getInstance();
cal2.set(9999, Calendar.DECEMBER, 31);
Date d2 = cal2.getTime();
System.out.println(d1);
System.out.println(d2);
This does not change anything to the output or the content of the two Date objects.
Note: Beware that integer literals that start with a 0, such as 0000 in your code, will be interpreted as octal numbers by the Java compiler. That doesn't matter in this case because the number is 0, but you should not prepend integer literals with zeroes if you don't mean them as octal numbers.
Thhere is no year 0 in Julian calendar. It goes from 1 BC to 1 AD.

Categories