Filling in Empty dates using Calendar - java
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.
Related
ZonedDateTime timezone inconsistency issue?
I need to write one function which will create the future installments for the invoice. Below is the function which creates the list of future installment dates :- public List<Date> getInstallmentDates(Invoice objectWithInvoiceDateField, int noOfInstallments, String instFreq) { //objectWithInvoiceDateField.getInvoiceDate this will return java.util.Date instance ZonedDateTime invoiceDate = objectWithInvoiceDateField.getInvoiceDate.toInstant().atZone(ZoneId.systemDefault()); ZonedDateTime firstInstallment = ZonedDateTime.of( invoiceDate.getYear(), invoiceDate.getMonthValue() , invoiceDate.getDayOfMonth() , 0 , 0 , 0, 0 , ZoneId.systemDefault()); List<Date> installmentDates = new ArrayList(); installmentDates.add(Date.from(firstInstallment.toInstant()));//First Installment /*Code for the subsequent installments*/ for (int i = 1; i < noOfInstallments; i++) { ZonedDateTime subsequentInstallments = null; if(instFreq.equalsIgnoreCase("Quarterly")) { subsequentInstallments = firstInstallment.plusMonths(3*i); } else if(instFreq.equalsIgnoreCase("Semi-annual")){ subsequentInstallments = firstInstallment.plusMonths(6*i); } else subsequentInstallments = firstInstallment.plusMonths(i); installmentDates.add(Date.from(subsequentInstallments.toInstant())); } return installmentDates; } This works as expected except for the last iteration. Below is the output if I run this method from main method for getInstallmentDates(invoice, 5, "Monthly"); Thu Jul 30 00:00:00 EDT 2020 Sun Aug 30 00:00:00 EDT 2020 Wed Sep 30 00:00:00 EDT 2020 Fri Oct 30 00:00:00 EDT 2020 Mon Nov 30 00:00:00 ***EST*** 2020 Can some one please help me understand why the timezone for last instance is changed to EST ? Thanks in advance!
Presumably because you have used the timezone to be ZoneId.systemDefault(), and your system defaults to a timezone that honours daylight saving time. Assuming EDT is Eastern Daylight Time and EST is Eastern Standard Time, in 2020 the end of daylight saving happens on 1 November and therefore the timezone name changes.
Java timezone what transitions mean?
I live in Venezuela in the last 10 years we faced 2 GMT changes. This code was run in Java 7 update 76 System.out.println(TimeZone.getTimeZone("America/Caracas")); Which prints sun.util.calendar.ZoneInfo[id="America/Caracas",offset=-16200000,dstSavings=0,useDaylight=false,transitions=5,lastRule=null] And this with the latest JDK Java 8 Update 121 of course in the end of the 2016 we have the latest change. sun.util.calendar.ZoneInfo[id="America/Caracas",offset=-14400000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null] I was wonder what transitions means the documentation says something like. No daylight saving time transition schedule can be specified with a custom time zone ID But in Venezuela not day saving are made I wonder what transitions means for this particular case does mean like the total of gmt change in history or so?
The ZoneInfo class has this comment on the transitions field: This array describes transitions of GMT offsets of this time zone, including both raw offset changes and daylight saving time changes. A long integer consists of four bit fields. Although Venezuela doesn't have DST, it did have some changes in its offset from GMT. Using the Linux command zdump -v America/Caracas, you get the following output: America/Caracas -9223372036854775808 = NULL America/Caracas -9223372036854689408 = NULL America/Caracas Wed Jan 1 04:27:43 1890 UT = Tue Dec 31 23:59:59 1889 LMT isdst=0 gmtoff=-16064 America/Caracas Wed Jan 1 04:27:44 1890 UT = Wed Jan 1 00:00:04 1890 CMT isdst=0 gmtoff=-16060 America/Caracas Mon Feb 12 04:27:39 1912 UT = Sun Feb 11 23:59:59 1912 CMT isdst=0 gmtoff=-16060 America/Caracas Mon Feb 12 04:27:40 1912 UT = Sun Feb 11 23:57:40 1912 VET isdst=0 gmtoff=-16200 America/Caracas Fri Jan 1 04:29:59 1965 UT = Thu Dec 31 23:59:59 1964 VET isdst=0 gmtoff=-16200 America/Caracas Fri Jan 1 04:30:00 1965 UT = Fri Jan 1 00:30:00 1965 VET isdst=0 gmtoff=-14400 America/Caracas Sun Dec 9 06:59:59 2007 UT = Sun Dec 9 02:59:59 2007 VET isdst=0 gmtoff=-14400 America/Caracas Sun Dec 9 07:00:00 2007 UT = Sun Dec 9 02:30:00 2007 VET isdst=0 gmtoff=-16200 America/Caracas Sun May 1 06:59:59 2016 UT = Sun May 1 02:29:59 2016 VET isdst=0 gmtoff=-16200 America/Caracas Sun May 1 07:00:00 2016 UT = Sun May 1 03:00:00 2016 VET isdst=0 gmtoff=-14400 America/Caracas 9223372036854689407 = NULL America/Caracas 9223372036854775807 = NULL Watch the gmtoff column on the right. Each pair of lines represents one transition. You can see there were more transitions, more than 10 years ago. Java does this a little differently, actually. It only records transitions since 1900, so the 1890 offset is not included. But it adds one dummy transition in the future. You can see the actual transitions with the following code (Java 8): import java.lang.reflect.Field; import java.time.Instant; import java.util.TimeZone; public class SimpleTest { public static void main(String[] args) { TimeZone tz = TimeZone.getTimeZone("America/Caracas"); Field f = null; try { f = tz.getClass().getDeclaredField("transitions"); f.setAccessible(true); long[] transitions = (long[]) f.get(tz); f = tz.getClass().getDeclaredField("offsets"); f.setAccessible(true); int[] offsets = (int[]) f.get(tz); for ( long transition : transitions ) { Instant transitionInstant = Instant.ofEpochMilli(transition >> 12); int offset = offsets[(int)transition & 0xF]; System.out.println( transitionInstant + " : " + offset); } } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } The output is: 1900-01-01T00:00:00Z : -16060000 1912-02-12T04:27:40Z : -16200000 1965-01-01T04:30:00Z : -14400000 2007-12-09T07:00:00Z : -16200000 2016-05-01T07:00:00Z : -14400000 2037-01-01T04:00:00Z : -14400000
Transitions is an Array and you get only the lenght of it (in this case 6) I quote: This array describes transitions of GMT offsets of this time zone, including both raw offset changes and daylight saving time changes. A long integer consists of four bit fields. The most significant 52-bit field represents transition time in milliseconds from Gregorian January 1 1970, 00:00:00 GMT. The next 4-bit field is reserved and must be 0. The next 4-bit field is an index value to offsets[] for the amount of daylight saving at the transition. If this value is zero, it means that no daylight saving, not the index value zero. The least significant 4-bit field is an index value to offsets[] for total GMT offset at the transition. If this time zone doesn't observe daylight saving time and has never changed any GMT offsets in the past, this value is null. and here the quelle
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!
Months elapsed function not giving proper result
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;