Months elapsed function not giving proper result - java

I have two dates: (YYYY-dd-mm)
1)1960-11-11
2)1986-04-02
I have the following function which intends to calculate the months elapsed since arbitary dates, the above two are my test conditions. This function calculates months without considering the current month. That is a month is only added once its a complete month.
The function is:
public static final int months(Date date1) {// tricky
Calendar calFirst = Calendar.getInstance();
calFirst.setTime(date1);
System.out.println(""+calFirst.getTime());
Calendar calNow = Calendar.getInstance();
calNow.setTime(getCurrentDate());
System.out.println(calNow.getTime());
int m2 = calNow.get(Calendar.YEAR) * 12 + calNow.get((Calendar.MONTH));
System.out.println(calNow.get(Calendar.YEAR) * 12 );
System.out.println(calNow.get(Calendar.MONTH));
//23832
int m1 = calFirst.get(Calendar.YEAR) * 12 + (calFirst.get(Calendar.MONTH));
System.out.println(calFirst.get(Calendar.YEAR) * 12 );
System.out.println(calFirst.get(Calendar.MONTH));
//24168
return Math.abs(m2 - (m1));
}
Result for 1986-04-02:
Wed Apr 02 00:00:00 IST 1986
Wed Jan 08 00:00:00 IST 2014
24168
0
23832
3
333
Which is correct
Result for 1960-11-11:
Fri Nov 11 00:00:00 IST 1960
Wed Jan 08 00:00:00 IST 2014
24168
0
23520
10
638
Which is wrong.
Any hints where I am going wrong?
Benchmark

I think that 333 and 638 are both good answers...
Let me explain :
April included to December 1986 = 9 months + 27 full years + 0 months in 2014 = 333.
Same thinking applied to the other :
November included to december 1960 = 2 months + 53 full years + 0 months in 2014 = 638.
Both numbers are right from the point of view : first month included, last month excluded

Why not use Joda Period instead as discussed here:
Period p = new Period(from, to, PeriodType.months().withDaysRemoved());
int months = p.getMonths() + 1;

Related

Java simpledateformat.format is giving incorrect date for last week of year [duplicate]

This question already has answers here:
Java Date year calculation is off by year for two days
(5 answers)
Closed 6 years ago.
This is actually a duplicate of Y returns 2012 while y returns 2011 in SimpleDateFormat I'll take the ding for duplicate on this one not the one listed below. I read the answer on that and I still think there is an error there. The first day of the week in my system is Sunday so by the description from the java.doc This should have been the 53rd week of 2017 not the 1st week of 2018, if I was going to get an error January 1st through the 6th should have returned 2017.
This is not a duplicate of Calendar return incorrect date, the calendar is working fine. see additional information below I was trying to simplify my code for display purposes at EOD as I was hopeing to get out of the door
When using SimpleDateFormat.Format to convert a Calendar date of 12/31/2017 (2017,11,31,0,0) (Sunday first day of the week, last week of the year) SimpleDateFormat returns 12/31/2018. I have tried this with java 6,7,8 and get the same results, I tried it on two different versions of eclipse I tried it on another developers computer all this the same result. This is pulled from my actual junit code.
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class SimpleDateTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calendar t_calendar = Calendar.getInstance();
Calendar m_calc_calendar = Calendar.getInstance();
int rc=0;
int testDays=20;
Date rDate;
SimpleDateFormat ssaDateFormat= new SimpleDateFormat("YYMMdd");
SimpleDateFormat logDateFormat= new SimpleDateFormat("E MM/dd/YYYY");
ArrayList<Date> testDates = new ArrayList<Date>();
t_calendar.set(2017,11,20,0,0); // start date
//t_calendar.set(2018,11,20,0,0); // start date
t_calendar.setLenient(false);
// builds 2600 dates for test run reason for Date (24 bytes) vs Calendar (423 bytes)
for(int days=0; days<testDays;days++){
t_calendar.add(Calendar.DATE, 1);
testDates.add(t_calendar.getTime());
}
for(Date testDate: testDates){
String test = testDate.toString();
System.out.println("toString: " + test);
t_calendar.setTimeInMillis(testDate.getTime());
test = ssaDateFormat.format(t_calendar.getTime());
System.out.println(" Cal.year " + t_calendar.get(Calendar.YEAR) + " Cal.month " + t_calendar.get(Calendar.MONTH) + " Cal.day " + t_calendar.get(Calendar.DATE) + " Cal.week " + t_calendar.get(Calendar.WEEK_OF_YEAR) );
System.out.println("ssa conversion: " + test);
test = logDateFormat.format(t_calendar.getTime());
System.out.println("log conversion: " + test);
System.out.println(t_calendar.toString());
System.out.println("");
// call to method under test
//rDate=rsl.calculateSSATransDate(ssaDateFormat.format(testDate),new BigDecimal(1.0));
// result validation.
}
}
Test Results
toString: Sat Dec 29 00:00:53 PST 2018 <-- input date
Cal.year 2018 Cal.month 11 Cal.day 29 Cal.week 52
ssa conversion: 181229
log conversion: Sat 12/29/2018 <-- result is good
java.util.GregorianCalendar[time=1546070453716,areFieldsSet=true,areAllFieldsSet=true,lenient=false,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=5,DAY_OF_MONTH=29,DAY_OF_YEAR=363,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=53,MILLISECOND=716,ZONE_OFFSET=-28800000,DST_OFFSET=0]
toString: Sun Dec 30 00:00:53 PST 2018 <-- Input date
Cal.year 2018 Cal.month 11 Cal.day 30 Cal.week 1
ssa conversion: 191230 <-- Result is bad
log conversion: Sun 12/30/2019
java.util.GregorianCalendar[time=1546156853716,areFieldsSet=true,areAllFieldsSet=true,lenient=false,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=6,DAY_OF_MONTH=30,DAY_OF_YEAR=364,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=53,MILLISECOND=716,ZONE_OFFSET=-28800000,DST_OFFSET=0]
toString: Mon Dec 31 00:00:53 PST 2018 <-- Input date
Cal.year 2018 Cal.month 11 Cal.day 31 Cal.week 1
ssa conversion: 191231
log conversion: Mon 12/31/2019 <-- Result is bad
java.util.GregorianCalendar[time=1546243253716,areFieldsSet=true,areAllFieldsSet=true,lenient=false,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=6,DAY_OF_MONTH=31,DAY_OF_YEAR=365,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=53,MILLISECOND=716,ZONE_OFFSET=-28800000,DST_OFFSET=0]
toString: Tue Jan 01 00:00:53 PST 2019 <-- input date
Cal.year 2019 Cal.month 0 Cal.day 1 Cal.week 1
ssa conversion: 190101
log conversion: Tue 01/01/2019 <-- Result is good
java.util.GregorianCalendar[time=1546329653716,areFieldsSet=true,areAllFieldsSet=true,lenient=false,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=1,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=53,MILLISECOND=716,ZONE_OFFSET=-28800000,DST_OFFSET=0]
As I look forward to the dates I see the issue repeat in this pattern
- in 2018 12/30 (Sun) and 12/31(Mon) in 2018,
- in 2019 I have issues with 12/29(Sun), 12/30(Mon) and 12/31 (Tues)
- in 2020 12/27(Sun), 12/28(Mon), 12/29(Tues), 12/30 (Wed) 12/31(Thurs)
- in 2021 12/26(Sun) - 12/31(Fri)
- 2022 is correct
- 2023 restarts the loop.
It has to do with the last incomplete week of the year but I haven't been able to solve the issue.
Months are 0 based i.e. January is 0 December is 11
try
c.set(2017, 11, 31, 0, 0);

Filling in Empty dates using Calendar

i am trying to create a list of dates that is based of the user's start and end dates. This is the infomation that I have in my array:
Calendar start = new GregorianCalendar(2015, 01, 01);
Calendar end = new GregorianCalendar(2015, 05, 01);
//User defined start and end time simulation
List<Calendar> datesinDB = new ArrayList<Calendar>();
datesinDB.add(new GregorianCalendar(2015,02,15));
datesinDB.add(new GregorianCalendar(2015,02,16));
datesinDB.add(new GregorianCalendar(2015,02,17));
datesinDB.add(new GregorianCalendar(2015,02,19));
datesinDB.add(new GregorianCalendar(2015,02,20));
datesinDB.add(new GregorianCalendar(2015,02,22));
datesinDB.add(new GregorianCalendar(2015,03,10));
datesinDB.add(new GregorianCalendar(2015,03,25));
datesinDB.add(new GregorianCalendar(2015,03,27));
//This is the data that I have in my simulated database
My code:
Calendar c = datesinDB.get(count-1);
for(int i = 1; i < datesinDB.get(0).getActualMaximum(datesinDB.get(0).DAY_OF_MONTH); i++){
if(i == c.get(5) && count < datesinDB.size())
{
revised.add(new GregorianCalendar(c.YEAR, c.MONTH, c.get(5)));
System.out.println(c.get(5));
c = datesinDB.get(count++);
}
else
{
revised.add(new GregorianCalendar(c.YEAR, c.MONTH, i));
}
}
Output:
Tue Feb 01 00:00:00 SGT 1
Wed Feb 02 00:00:00 SGT 1
Thu Feb 03 00:00:00 SGT 1
Fri Feb 04 00:00:00 SGT 1
Sat Feb 05 00:00:00 SGT 1
Sun Feb 06 00:00:00 SGT 1
Mon Feb 07 00:00:00 SGT 1
Tue Feb 08 00:00:00 SGT 1
Wed Feb 09 00:00:00 SGT 1
Thu Feb 10 00:00:00 SGT 1
Fri Feb 11 00:00:00 SGT 1
Sat Feb 12 00:00:00 SGT 1
Sun Feb 13 00:00:00 SGT 1
Mon Feb 14 00:00:00 SGT 1
Tue Feb 15 00:00:00 SGT 1
Wed Feb 16 00:00:00 SGT 1
Thu Feb 17 00:00:00 SGT 1
Fri Feb 18 00:00:00 SGT 1
Sat Feb 19 00:00:00 SGT 1
Sun Feb 20 00:00:00 SGT 1
Mon Feb 21 00:00:00 SGT 1
Tue Feb 22 00:00:00 SGT 1
Wed Feb 23 00:00:00 SGT 1
Thu Feb 24 00:00:00 SGT 1
Fri Feb 25 00:00:00 SGT 1
Sat Feb 26 00:00:00 SGT 1
Sun Feb 27 00:00:00 SGT 1
Mon Feb 28 00:00:00 SGT 1
My issue is that my code only can do this for a single month and not any longer. Is there a way to fix this?
It's bad form to use constant numbers, look in the Calendar class for symbolic names for the constant you want to use.
Here's what I think you want:
final Calendar start = Calendar.getInstance(2015, 1, 1);
final Calendar end = Calendar.getInstance(2015, 5, 1);
final List<Calendar> dates = new ArrayList<>(128); // 128: fewer reallocations
for (Calendar date = start; !date.after(end); date.add(Calendar.DATE, 1)) {
dates.add(date);
}
The Question and its code are confusing. The author does not state exactly what the problem is. And I cannot quite follow the logic of the code. Your output does not map to your code. Are you trying to get a count of how many rows in the database fall on each day of the date range? Are you trying to get a subset of database rows that occur within the date range? So I cannot give a perfect-fit answer, but I'll get you closer to a solution.
Octal
Do not pad a numeric literal with a leading zero; that tells Java to interpret the literal as an Octal (base-8) rather than as a Decimal (base-10). So, ( 2015 , 02 , 15 ) should be ( 2015 , 2 , 15 ).
Avoid old date-time classes
You should not be using the old date-time classes bundled with the earliest versions of Java. They have proven to be poorly designed, confusing, and troublesome.
java.time
The old classes are supplanted by the java.time framework built into Java 8 and later. See Tutorial.
LocalDate
The java.time classes include java.time.LocalDate to truly represent a date-only value without time-of-day and without time zone. Seems to be what you need. To fetch those from the database, use the java.sql.Date class via JDBC. Minimize your use of java.sql; immediately convert from the java.sql type to java.time as you continue with your business logic and presentation to user. In your database define the column as DATE type.
List < LocalDate > datesInQuestion = new ArrayList <> ( );
datesInQuestion.add ( LocalDate.of ( 2015, 2, 20 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 2, 22 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 3, 10 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 12, 31 ) );
YearMonth
For the boundaries (start - stop), if using only whole months then pass objects of the java.time.YearMonth class.
YearMonth startYearMonth = YearMonth.of ( 2016, Month.JANUARY );
YearMonth stopYearMonth = YearMonth.of ( 2016, Month.JUNE );
Half-Open
In date-time work, a span of time is often represented using the Half-Open approach. The beginning is inclusive while the ending is exclusive. Following the Question’s example, we will run from months of January to June so as to include all of May.
LocalDate start = startYearMonth.atDay ( 1 );
LocalDate stop = stopYearMonth.atDay ( 1 ); // Half-open approach, running up to but not including this date.
Prepare a pair of lists to store the dates found to be within our range and to store the dates that have no matches found in our target list.
List < LocalDate > datesInRange = new ArrayList <> ( );
List < LocalDate > datesVoid = new ArrayList <> ( );
Loop each date within our range. Search our target list for any matches.
LocalDate localDate = start;
while ( localDate.isBefore ( stop ) ) { // Loop through our date range from 'start' to 'stop', with 'stop' being exclusive.
if ( datesInQuestion.contains ( localDate ) ) {
datesInRange.add ( localDate );
} else {
datesVoid.add ( localDate );
}
Perhaps you want to know how many times this date appears in the collection 'datesInQuestion'. The Collections.frequency utility class (notice the ending 's')
int frequency = Collections.frequency ( datesInQuestion, localDate );
Set up next loop. Increment to the next date.
localDate = localDate.plusDays ( 1 );
}
The looping is complete at this point.
Perhaps you want to know the target dates that fell outside our range. Duplicate the list of dates-in-question. Remove the ones found to be within our range. The remaining must be outside the range.
List < LocalDate > datesOutsideRange = new ArrayList <> ( datesInQuestion ); // Duplicate the collection of dates-in-question.
boolean anyRemoved = datesOutsideRange.removeAll ( datesInRange ); // Then remove the ones found to be within our range.
Dump to console.
System.out.println ( "datesInQuestion: " + datesInQuestion );
System.out.println ( "datesInRange: " + datesInRange );
System.out.println ( "datesOutsideRange: " + datesOutsideRange );
System.out.println ( "datesVoid: " + datesVoid );
datesInQuestion: [2015-02-20, 2015-02-22, 2015-03-10, 2015-12-31]
datesInRange: [2015-02-20, 2015-02-22, 2015-03-10]
datesOutsideRange: [2015-12-31]
Note that our three dates of February 20 & 22 and March 10 do not appear in this longer list of datesVoid.
datesVoid: [2015-01-01, 2015-01-02, 2015-01-03, 2015-01-04, 2015-01-05, 2015-01-06, 2015-01-07, 2015-01-08, 2015-01-09, 2015-01-10, 2015-01-11, 2015-01-12, 2015-01-13, 2015-01-14, 2015-01-15, 2015-01-16, 2015-01-17, 2015-01-18, 2015-01-19, 2015-01-20, 2015-01-21, 2015-01-22, 2015-01-23, 2015-01-24, 2015-01-25, 2015-01-26, 2015-01-27, 2015-01-28, 2015-01-29, 2015-01-30, 2015-01-31, 2015-02-01, 2015-02-02, 2015-02-03, 2015-02-04, 2015-02-05, 2015-02-06, 2015-02-07, 2015-02-08, 2015-02-09, 2015-02-10, 2015-02-11, 2015-02-12, 2015-02-13, 2015-02-14, 2015-02-15, 2015-02-16, 2015-02-17, 2015-02-18, 2015-02-19, 2015-02-21, 2015-02-23, 2015-02-24, 2015-02-25, 2015-02-26, 2015-02-27, 2015-02-28, 2015-03-01, 2015-03-02, 2015-03-03, 2015-03-04, 2015-03-05, 2015-03-06, 2015-03-07, 2015-03-08, 2015-03-09, 2015-03-11, 2015-03-12, 2015-03-13, 2015-03-14, 2015-03-15, 2015-03-16, 2015-03-17, 2015-03-18, 2015-03-19, 2015-03-20, 2015-03-21, 2015-03-22, 2015-03-23, 2015-03-24, 2015-03-25, 2015-03-26, 2015-03-27, 2015-03-28, 2015-03-29, 2015-03-30, 2015-03-31, 2015-04-01, 2015-04-02, 2015-04-03, 2015-04-04, 2015-04-05, 2015-04-06, 2015-04-07, 2015-04-08, 2015-04-09, 2015-04-10, 2015-04-11, 2015-04-12, 2015-04-13, 2015-04-14, 2015-04-15, 2015-04-16, 2015-04-17, 2015-04-18, 2015-04-19, 2015-04-20, 2015-04-21, 2015-04-22, 2015-04-23, 2015-04-24, 2015-04-25, 2015-04-26, 2015-04-27, 2015-04-28, 2015-04-29, 2015-04-30, 2015-05-01, 2015-05-02, 2015-05-03, 2015-05-04, 2015-05-05, 2015-05-06, 2015-05-07, 2015-05-08, 2015-05-09, 2015-05-10, 2015-05-11, 2015-05-12, 2015-05-13, 2015-05-14, 2015-05-15, 2015-05-16, 2015-05-17, 2015-05-18, 2015-05-19, 2015-05-20, 2015-05-21, 2015-05-22, 2015-05-23, 2015-05-24, 2015-05-25, 2015-05-26, 2015-05-27, 2015-05-28, 2015-05-29, 2015-05-30, 2015-05-31]
I actually figured it out after looking at joda-time after posting the question so here goes:
The solution is to count the day of the year using joda-time instead of my original way using date, month and year.
My actual aim is to pad in missing dates that are not in the simulated ArrayList that simulates data grabbed from a actual database somewhere. So it might look something like this:
Date | Value
15/02/15 | 1
16/02/15 | 2
18/02/15 | 3
19/02/15 | 6
My aim was to create a arraylist that has all the dates of the month with values 0 if the date did not exist in my original db. The amount of months to fill in is identified by the start and end date so assuming in this case, i am asking to do for a month.
Date | Value
01/02/2015 | 0
02/02/2015 | 0
03/02/2015 | 0
04/02/2015 | 0
05/02/2015 | 0
06/02/2015 | 0
07/02/2015 | 0
08/02/2015 | 0
09/02/2015 | 0
10/02/2015 | 0
11/02/2015 | 0
12/02/2015 | 0
13/02/2015 | 0
14/02/2015 | 0
15/02/2015 | 1
16/02/2015 | 2
17/02/2015 | 0
18/02/2015 | 3
19/02/2015 | 6
20/02/2015 | 0
21/02/2015 | 0
22/02/2015 | 0
23/02/2015 | 0
24/02/2015 | 0
25/02/2015 | 0
26/02/2015 | 0
27/02/2015 | 0
28/02/2015 | 0
So here are my revised codes:
DateTimeFormatter sdf = DateTimeFormat.forPattern("dd/MM/yyyy");//formatter for display
LocalDate start = new LocalDate(2015, 01, 01);
LocalDate end = new LocalDate(2015, 06, 01);
List<Dates> revised = new ArrayList<Dates>(); //populated array
List<Dates> datesinDB = new ArrayList<Dates>(); //
int count = 1; //index for arrays
datesinDB.add(new Dates(new LocalDate(2015,02,15), 1)); //data
datesinDB.add(new Dates(new LocalDate(2015,02,16), 2));
datesinDB.add(new Dates(new LocalDate(2015,02,17),22));
datesinDB.add(new Dates(new LocalDate(2015,02,19),14));
LocalDate c = datesinDB.get(count-1).getDate(); //initial data
int values = datesinDB.get(count-1).getValue(); //initial data
for(int i = start.getDayOfYear(); i <=end.getDayOfYear() ; i++){
if(i == c.getDayOfYear())
{
if(count < datesinDB.size()){
revised.add(new Dates(c, values));
c = datesinDB.get(count).getDate();
values = datesinDB.get(count++).getValue();
}
else if(count == datesinDB.size()){
revised.add(new Dates(c, values));
count++;
}
}
else
{
if(i != 59){//some issues with 28/2/2015 due to leap year i guess
revised.add(new Dates(new LocalDate().withDayOfYear(i).withYear(2015), 0));
}
}
}
System.out.println("Date | Values");
for(int i = 0; i< revised.size(); i++){
System.out.println(sdf.print(revised.get(i).getDate())+ " | "+ revised.get(i).getValue());
}
All in all, this nets me what I need with some slight errors that I will fix. Thanks to those that answered.
Fyi, Dates is my LinkedList class that looks like this:
public class Dates {
public LocalDate date;
public int value;
public Dates(LocalDate date, int value){
this.date = date;
this.value = value;
}
public LocalDate getDate(){
return this.date;
}
public int getValue(){
return this.value;
}
}
I hope this helps someone else if they are in the same waters as me. Holy hell 365 days is so hard to master.

How does Calendar class calculate months?

I got a really annoying problem with calendar class. I have two JTextFields to enter a period of date (txtStart & txtEnd). If start date begins at the first day of month (01.), I set the end date to "last day of month".
Now the user can change change the period by clicking a plus or minus button, then I want to increase or decrease only the month of start & end date.
Calendar tempStart = Calendar.getInstance();
Calendar tempEnd = Calendar.getInstance();
if (txtStart.getText().trim().startsWith("01.")) {
System.out.println("get dates typed by user, and set \"last day of month\" to txtEnd");
tempStart = convStringToDate(txtStart.getText().trim(), false);
System.out.println(tempStart.getTime() + " #+#+###++ ");
tempEnd = getLastDayOfMonth(txtStart.getText().trim());
System.out.println(tempEnd.getTime() + " #+#+###++ ");
System.out.println(" ");
System.out.println("multi is either +1 or -1, increasing or decreasing only the month !");
tempStart.set(Calendar.MONTH, tempStart.get(Calendar.MONTH) + multi);
System.out.println(tempStart.getTime() + " #+#+###++ ");
tempEnd.set(Calendar.MONTH, tempEnd.get(Calendar.MONTH) + multi);
System.out.println(tempEnd.getTime() + " #+#+###++ ");
System.out.println(" ");
}
My methods are working correctly. Now I got some bewildering output.
If I enter 01.11.2015 at txtStart (dd.MM.yyy) I got following output:
get dates typed by user, and set "last day of month" to txtEnd
Sun Nov 01 00:00:01 GMT 2015 #+#+###++
Mon Nov 30 23:59:59 GMT 2015 #+#+###++
multi is either +1 or -1, increasing or decreasing only the month !
Tue Dec 01 00:00:01 GMT 2015 #+#+###++
Wed Dec 30 23:59:59 GMT 2015 #+#+###++
Looks pretty nice and everthing seems to work correctly, but if I enter 01.10.2015 at txtStart (dd.MM.yyy) I got following output:
get dates typed by user, and set "last day of month" to txtEnd
Thu Oct 01 00:00:01 GMT 2015 #+#+###++
Sat Oct 31 23:59:59 GMT 2015 #+#+###++
multi is either +1 or -1, increasing or decreasing only the month !
Sun Nov 01 00:00:01 GMT 2015 #+#+###++
Tue Dec 01 23:59:59 GMT 2015 #+#+###++
May anyone have an idea why my end date is wrong at output 2.
EDIT:
multi = +1 or -1 (see in output1 or output2 comment)
private Calendar getLastDayOfMonth(String sDate) {
Calendar cal = convStringToDate(sDate, true);
// passing month-1 because 0-->jan, 1-->feb... 11-->dec
// calendar.set(year, month - 1, 1);
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
cal.set(Calendar.HOUR_OF_DAY, MAX_ZEIT[0]); // 23
cal.set(Calendar.MINUTE, MAX_ZEIT[1]); // 59
cal.set(Calendar.SECOND, MAX_ZEIT[2]); // 59
cal.set(Calendar.MILLISECOND, MAX_ZEIT[3]); // 0
// Time: 23:59:59:0
return cal;
}
############## SOLUTION: ####################.
if (txtStart.getText().trim().startsWith("01.")) {
tempStart = convStringToDate(txtStart.getText().trim(), false);
tempEnd = (Calendar) tempStart.clone(); // set the date somewhere at the same month ( e.g. at start date )
tempStart.set(Calendar.MONTH, tempStart.get(Calendar.MONTH) + multi); // inc- or decrease the month first
tempEnd.set(Calendar.MONTH, tempEnd.get(Calendar.MONTH) + multi); // inc- or decrease the month first ( now there is no overflow due to the 30th or 31th day )
tempEnd = getLastDayOfMonth(df2.format(tempEnd.getTime())); // finally setting the "last day of month"
}
The solution is to do first of all to increase or decrease the month, after that I can set the last day of month without getting any overflow problems.
Output:
get dates typed by user, and set "last day of month" to txtEnd
Thu Oct 01 00:00:01 GMT 2015 #+#+###++
Thu Oct 01 00:00:01 GMT 2015 #+#+###++
multi is either +1 or -1, increasing or decreasing only the month !
Sun Nov 01 00:00:01 GMT 2015 #+#+###++
Sun Nov 01 00:00:01 GMT 2015 #+#+###++
FINALLY
Sun Nov 01 00:00:01 GMT 2015 #+#+###++
Mon Nov 30 23:59:59 GMT 2015 #+#+###++
I thank you all for your help !!!
The end date is incorrect in the first example, as well. It shows 30/12 whereas the last day of December is the 31st. When you add +1 to the month you don't check whether the following month has the same number of days.
November has 30 days. Therefore, incrementing October 31st gives November "31st" which is actually December 1st.
Lots of programmers need to do arithmetic on dates. That's why java.util.Calendar class has a method add() that you can use that encapsulates all the calculations you need. Check the JavaDocs: http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#add(int,%20int)
After you have incremented or decremented the month of the start date, use
int lastDayOfMonth = startDate.getActualMaximum(Calendar.DAY_OF_MONTH);
and use startDate in combination with day-of-month set to this value as the endDate.
Calendar sd = new GregorianCalendar( 2015, 1, 1 );
int last = sd.getActualMaximum(Calendar.DAY_OF_MONTH);
Calendar ed = new GregorianCalendar( sd.get(Calendar.YEAR),
sd.get(Calendar.MONTH),
last );
System.out.println( sd.getTime() + " " + ed.getTime() );
sd.add( Calendar.MONTH, 1 );
last = sd.getActualMaximum(Calendar.DAY_OF_MONTH);
ed = new GregorianCalendar( sd.get(Calendar.YEAR),
sd.get(Calendar.MONTH),
last );
System.out.println( sd.getTime() + " " + ed.getTime() );

get the last updated time of variable - java

I want to get the last updated time of a variable.
static Date ti;
for (int i = 0; i <= attachedControllers.length; i++ )
{ ti = null;
controllers tempc = attachedControllers[i];
ti = tempc.getLastUpdated(); // return the last updated time of each controllers object.
System.out.println("last updated of \t" + tempc.getControllerName() +"is \t"+ti);
Date t2 = new Date();
System.out.println("Time now \t" + t2);
long s = (t2.getTime() - ti.getTime())/(1000 * 60 );
System.out.println("difference is \t"+s);
}
the problem is the variable ti stores all previous values of the last updated time of each controllers object. and I want to get the last value only.
the output here is:
last updated of 0.0.0.0/0.0.0.0:6632is Sun Jun 21 03:38:59 AST 2015
Time now Sun Jun 21 03:39:14 AST 2015
difference is 0
last updated of 0.0.0.0/0.0.0.0:6633is Sun Jun 21 03:39:04 AST 2015
Time now Sun Jun 21 03:39:19 AST 2015
difference is 0
last updated of 0.0.0.0/0.0.0.0:6632is Sun Jun 21 03:38:59 AST 2015
Time now Sun Jun 21 03:40:14 AST 2015
difference is 1
last updated of 0.0.0.0/0.0.0.0:6633is Sun Jun 21 03:39:04 AST 2015
Time now Sun Jun 21 03:40:19 AST 2015
difference is 1
last updated of 0.0.0.0/0.0.0.0:6632is Sun Jun 21 03:40:59 AST 2015
Time now Sun Jun 21 03:41:14 AST 2015
difference is 0
last updated of 0.0.0.0/0.0.0.0:6632is Sun Jun 21 03:38:59 AST 2015 // here it retrieve the first value of last updated time which is my problem.
Time now Sun Jun 21 03:41:14 AST 2015
difference is 2
last updated of 0.0.0.0/0.0.0.0:6633is Sun Jun 21 03:39:04 AST 2015
Time now Sun Jun 21 03:41:19 AST 2015
difference is 2
I call this this function like this:
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable()
{
public void run()
{
checkControllerHealth ();
}
}, 15, 60, TimeUnit.SECONDS);
Then put outside of your loop the System.out.println. Like this:
static Date ti;
for (int i = 0; i <= attachedControllers.length; i++ )
{ ti = null;
controllers tempc = attachedControllers[i];
ti = tempc.getLastUpdated(); // return the last updated time of each controllers object.
}
System.out.println("last updated of \t" + tempc.getControllerName() +"is \t"+ti);
Date t2 = new Date();
System.out.println("Time now \t" + t2);
long s = (t2.getTime() - ti.getTime())/(1000 * 60 );
System.out.println("difference is \t"+s);
Then it will show only the last iteration that you have in your loop.
I expect it will be helpful for you!

Conversion from Gregorian to Hijri/Islamic date in Pakistan

I need to show Hijri date for a client's website in Pakistan. I cannot use a web service because internet might not be always available at client's site.
I have been using joda-time (java), but a javascript solution would also work.
Joda-time is currently calculating it as 5th day of 5th month
(Jamaadi-ul-Awal), while in Pakistan it is 4th of Jammadi-ul-Awal
Following is my code:
public class HijriDate {
/**
* #param args
*/
public static void main(String[] args) {
Date date=new Date();
SimpleDateFormat frmt=new SimpleDateFormat("yyyy-MM-dd");
String currenDate=frmt.format(date);
System.out.println(currenDate);
String[] dt=currenDate.split("-");
DateTimeZone defaultZone = DateTimeZone.getDefault();
DateTimeZone.setDefault(defaultZone);
DateTime dtISO = new DateTime(Integer.parseInt((dt[0])),Integer.parseInt((dt[1])), Integer.parseInt((dt[2])), 0, 0, 0, 0);
DateTimeZone tzPakistan = DateTimeZone.forID(TimeZone.getDefault().getID());
DateTime dtIslamic =dtISO.withChronology(IslamicChronology.getInstance(tzPakistan,IslamicChronology.LEAP_YEAR_15_BASED));
String [] hmonths= {"","Muharram", "Safar", "Rabi al-Awwal", "Rabi al-Akhir", "Jamadi al-Awwal", "Jamadi al-Akhir", "Rajab", "Shabaan", "Ramadhan", "Shawwal", "Zilqad", "Zilhajj"};
int mnth=dtIslamic.getMonthOfYear();
String hijriMonth="";
for(int i=0;i<hmonths.length;i++){
if(hmonths[mnth] != null){
hijriMonth=hmonths[mnth];
break;
}
}
String dat=dtIslamic.toString();
String a[]= dat.split("-");
int count=2;
String day="";
String year="";
for(int d=2;d>=0;d=d-2){
count--;
if(count==0){
year=a[d];
}
if(count==1){
day=a[d].substring(0,2);
}
}
System.out.println(hijriMonth+" "+day+","+year);
System.out.println(TimeZone.getDefault().getID());
}
}
I have also tried by modifying the leap year parameter, to each of the 4 available.
Jumada al-awwal month's days are starting from 20 February 2015 and ending at 20 March 2015.
AH First day (CE / AD) Last day (CE / AD)
1431 15 April 2010 14 May 2010
1432 5 April 2011 3 May 2011
1433 24 March 2012 21 April 2012
1434 13 March 2013 10 April 2013
1435 2 March 2014 31 March 2014
**1436 20 February 2015 20 March 2015**
1437 10 February 2016 9 March 2016
when I executed your code, output is ;
2015-02-25
Jamadi al-Awwal 06,1436
And it is true, year must be 1436 and the day starts from 20 and today is the 6th day.
1 2 3 4 5 6
Feb 20 Feb 21 Feb 22 Feb 23 Feb 24 Feb 25
For February 2015 C.E. you can look here.

Categories