Comparing date with next object date in Arraylist not working as expected










-1















I've a list of records, where each record has date objects inside it. I'm checking that the first record should have previous dates than the second, and second record dates should be less than 3rd record and so on.. Here is my code..



for(int i = 0; i < machines.size(); i++) 
for(int j = i + 1; j < machines.size(); j++)
(machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt())
* machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt()) >= 0))

throw new Exception("Dates are not as per criteria..");







My dates that are coming from the database is:



 STRT_DT END_DT
---------- ----------
2014-01-01 2014-12-31
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2016-12-31
2017-01-01 2017-12-31
2018-01-01 2018-02-01


Am I missing anything? Any help would be greatly appreciated..










share|improve this question



















  • 1





    Cannot understand why your if statement has the same condition ORed twice?

    – robot_alien
    Nov 14 '18 at 10:25











  • i * i > 0, even if i = -1.

    – 孙兴斌
    Nov 14 '18 at 10:26











  • Because my first record i would be checking with second record j

    – Syed
    Nov 14 '18 at 10:27











  • Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

    – Ole V.V.
    Nov 14 '18 at 11:39











  • Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

    – LuCio
    Nov 14 '18 at 11:47















-1















I've a list of records, where each record has date objects inside it. I'm checking that the first record should have previous dates than the second, and second record dates should be less than 3rd record and so on.. Here is my code..



for(int i = 0; i < machines.size(); i++) 
for(int j = i + 1; j < machines.size(); j++)
(machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt())
* machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt()) >= 0))

throw new Exception("Dates are not as per criteria..");







My dates that are coming from the database is:



 STRT_DT END_DT
---------- ----------
2014-01-01 2014-12-31
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2016-12-31
2017-01-01 2017-12-31
2018-01-01 2018-02-01


Am I missing anything? Any help would be greatly appreciated..










share|improve this question



















  • 1





    Cannot understand why your if statement has the same condition ORed twice?

    – robot_alien
    Nov 14 '18 at 10:25











  • i * i > 0, even if i = -1.

    – 孙兴斌
    Nov 14 '18 at 10:26











  • Because my first record i would be checking with second record j

    – Syed
    Nov 14 '18 at 10:27











  • Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

    – Ole V.V.
    Nov 14 '18 at 11:39











  • Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

    – LuCio
    Nov 14 '18 at 11:47













-1












-1








-1


0






I've a list of records, where each record has date objects inside it. I'm checking that the first record should have previous dates than the second, and second record dates should be less than 3rd record and so on.. Here is my code..



for(int i = 0; i < machines.size(); i++) 
for(int j = i + 1; j < machines.size(); j++)
(machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt())
* machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt()) >= 0))

throw new Exception("Dates are not as per criteria..");







My dates that are coming from the database is:



 STRT_DT END_DT
---------- ----------
2014-01-01 2014-12-31
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2016-12-31
2017-01-01 2017-12-31
2018-01-01 2018-02-01


Am I missing anything? Any help would be greatly appreciated..










share|improve this question
















I've a list of records, where each record has date objects inside it. I'm checking that the first record should have previous dates than the second, and second record dates should be less than 3rd record and so on.. Here is my code..



for(int i = 0; i < machines.size(); i++) 
for(int j = i + 1; j < machines.size(); j++)
(machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt())
* machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt()) >= 0))

throw new Exception("Dates are not as per criteria..");







My dates that are coming from the database is:



 STRT_DT END_DT
---------- ----------
2014-01-01 2014-12-31
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2016-12-31
2017-01-01 2017-12-31
2018-01-01 2018-02-01


Am I missing anything? Any help would be greatly appreciated..







java date






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 22:51









Basil Bourque

111k27378542




111k27378542










asked Nov 14 '18 at 10:17









SyedSyed

83072048




83072048







  • 1





    Cannot understand why your if statement has the same condition ORed twice?

    – robot_alien
    Nov 14 '18 at 10:25











  • i * i > 0, even if i = -1.

    – 孙兴斌
    Nov 14 '18 at 10:26











  • Because my first record i would be checking with second record j

    – Syed
    Nov 14 '18 at 10:27











  • Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

    – Ole V.V.
    Nov 14 '18 at 11:39











  • Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

    – LuCio
    Nov 14 '18 at 11:47












  • 1





    Cannot understand why your if statement has the same condition ORed twice?

    – robot_alien
    Nov 14 '18 at 10:25











  • i * i > 0, even if i = -1.

    – 孙兴斌
    Nov 14 '18 at 10:26











  • Because my first record i would be checking with second record j

    – Syed
    Nov 14 '18 at 10:27











  • Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

    – Ole V.V.
    Nov 14 '18 at 11:39











  • Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

    – LuCio
    Nov 14 '18 at 11:47







1




1





Cannot understand why your if statement has the same condition ORed twice?

– robot_alien
Nov 14 '18 at 10:25





Cannot understand why your if statement has the same condition ORed twice?

– robot_alien
Nov 14 '18 at 10:25













i * i > 0, even if i = -1.

– 孙兴斌
Nov 14 '18 at 10:26





i * i > 0, even if i = -1.

– 孙兴斌
Nov 14 '18 at 10:26













Because my first record i would be checking with second record j

– Syed
Nov 14 '18 at 10:27





Because my first record i would be checking with second record j

– Syed
Nov 14 '18 at 10:27













Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

– Ole V.V.
Nov 14 '18 at 11:39





Is it enough that start dates come in the right order? Or do you need to check for overlaps in time too? I mean where one end date would come after the following start date.

– Ole V.V.
Nov 14 '18 at 11:39













Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

– LuCio
Nov 14 '18 at 11:47





Since you have an ArrayList you could also use a listIterator() to get compare the next() and the previous() date-pairs.

– LuCio
Nov 14 '18 at 11:47












3 Answers
3






active

oldest

votes


















3














You’re over-complicating it. It’s enough to check pairwise entries since if a < b are in the right order and b < c are in the right order, then you already know that a < c are also in the right order.



for(int i = 0; i < machines.size() - 1; i++) 
if (! machines.get(i).getEnd_Dt().before(machines.get(i + 1).getStrt_Dt()))
throw new IllegalStateException("Dates are not in chronological order");




I am using “not before” to mean “on or after”. Or to put it another way, I am requiring each start date to come stricty before the next start date, and if it doesn’t, I throw the exception. Edit: I didn’t know how to get the end date from your object type, so please substitute the correct getter call where I wrote getEnd_Dt().



If you additionally need to check that each machine has start date and end date in the right order (using the enhanced for loop):



for (Machine m : machines) 
if (m.getEnd_Dt().before(m.getStrt_Dt()))
throw new IllegalStateException("Dates are not in chronological order");




As an aside, Java naming conventions don’t use underscores in names (except in a CONSTANT_NAME), so prefer getStrtDt over getStrt_Dt. Or even better, getStartDate.



That said, Embid123 is correct, you should see if you can replace Date with LocalDate. The Date class has design problems and is long outdated. And despite its name it doesn’t represent a date, but a point in time. LocalDate is part of java.time, the modern Java date and time API, which is so much nicer to work with.



The other thing you need is to have your database query sort the entries by start date, then you know you get them in the right order.



What went wrong in your code?



First, your code is complicated on the border of the unreadable.



Next, when two entries i and j have start dates in the wrong order, that is, the j date is earlier than the i date, then machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt()) is negative and machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt() is positive. It’s really the same comparison, only reversed. So the product will be negative, your >= 0 condition will be false and you will not throw the exception.



Only if two entries have the exact same date (down to the millisecond), compareTo returns 0, the product is 0, >= 0 will be true and your exception will be thrown.






share|improve this answer

























  • Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

    – Syed
    Nov 15 '18 at 12:27











  • Can you please modify the example if possible .. I'm not able to get it..

    – Syed
    Nov 15 '18 at 13:47











  • Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

    – Syed
    Nov 16 '18 at 2:29











  • Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

    – Ole V.V.
    Nov 16 '18 at 7:53


















2














tl;dr



Use the modern java.time.LocalDate and org.threeten.extra.LocalDateRange classes to simplify your business logic to basically one line asking if the prior item in the list is not before the current item.



if ( 
!
prior
.getDateRange()
.isBefore(
current.getDateRange()
)
) … handle rule violation …


See also the correct Answer by Ole V.V.



Avoid legacy date-time classes



Never use the badly-designed legacy classes. The java.util.Date class, despite its name, represents a moment, a date with a time-of-day in UTC. The java.sql.Date class pretends to represent a date-only but actually involves a time-of-day and offset as well.



java.time



The modern approach uses the java.time classes.



LocalDate



The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.



You may set the month by a number, with sane numbering 1-12 for January-December.



LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.



LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


You can directly parse strings in standard ISO 8601 format: YYYY-MM-DD



LocalDate ld = LocalDate.parse( "2018-01-23" ) ; 


For parsing other formats, search Stack Overflow to learn about DateTimeFormatter.



LocalDateRange



You seem to using a pair of dates, a start and stop date, in your Machine class.



There is a class for that. Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class has some very useful methods for comparing. Using this class greatly simplifies your code, and makes the intent of your business logic more obvious.



Store your stop/start dates as a LocalDateRange object on your Machine object.



private LocalDateRange dateRange; 


Half-Open



Generally the best approach to tracking a span of time is the Half-Open approach. The beginning is inclusive while the ending is exclusive.



So a week is defined as starting on one day, such as Monday, and running up to, but not including, the same day of the following week, the next Monday for example. A year starts on January 1 of one year and runs up to, but does include, January 1 of the following year.



Using Half-Open approach would mean defining your example date like the following. Notice how changing the ending date to the year-long values in rows 1, 3, and 4 matches up with your own definition of the apparent month-long values of rows 2 & 5.





 STRT_DT END_DT
---------- ----------
2014-01-01 2015-01-01
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2017-01-01
2017-01-01 2018-01-01
2018-01-01 2018-02-01


Example class: Machine



Here is some example code for your class Machine.



package com.basilbourque.example;

import org.threeten.extra.LocalDateRange;

import java.time.LocalDate;
import java.util.List;
import java.util.Objects;

public class Machine --------------------------

public String getName ( )
return this.name;


public LocalDateRange getDateRange ( )
return this.dateRange;



// -------


Let's try this class by writing a main method.



 public static void main ( String args ) 
List < Machine > machines =
List.of(
new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
);
// Compare
for ( int i = 1 ; i < machines.size() ; i++ ) // Using annoying zero-based index counting.
Machine prior = machines.get( i - 1 );
Machine current = machines.get( i );
if ( ! prior.getDateRange().isBefore( current.getDateRange() ) )
System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );





When run.




BAD: Machine at index 0 is not before Machine at index 1 ➙ 2014-01-01/2015-01-01 versus 2013-01-01/2013-02-01




JDBC 4.2



As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.



LocalDate start = myResultSet.getObject( "start_date" , LocalDate.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.



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.






share|improve this answer
































    0














    Are you using LocalDate? I think it is a good choice for comparing dates. It is since Java 8.



     package sample;

    import java.time.LocalDate;
    import java.time.temporal.ChronoUnit;

    public class LocalDateTest

    public static void main(String args)


    //of(year, month, day)
    LocalDate date1 = LocalDate.of(2018, 11, 11);

    LocalDate date2 = LocalDate.of(2018, 11, 14);

    long daysBetween = ChronoUnit.DAYS.between(date1, date2);

    System.out.println(daysBetween);




    LocalDate hasn't got any public constructor, you create an object via static factory method.
    By the use of enum ChronoUnit, you get a long value representing days, weeks, or years from one date do second date. If you want to e.g. calculate weeks between, simply replace DAYS with WEEKS.



    Now comparing dates is simple, if the value is negative, the first date exceeds the second one.



    Documentation of LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html






    share|improve this answer























    • I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

      – Syed
      Nov 14 '18 at 10:38











    • This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

      – Basil Bourque
      Nov 14 '18 at 23:15











    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297784%2fcomparing-date-with-next-object-date-in-arraylist-not-working-as-expected%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    You’re over-complicating it. It’s enough to check pairwise entries since if a < b are in the right order and b < c are in the right order, then you already know that a < c are also in the right order.



    for(int i = 0; i < machines.size() - 1; i++) 
    if (! machines.get(i).getEnd_Dt().before(machines.get(i + 1).getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    I am using “not before” to mean “on or after”. Or to put it another way, I am requiring each start date to come stricty before the next start date, and if it doesn’t, I throw the exception. Edit: I didn’t know how to get the end date from your object type, so please substitute the correct getter call where I wrote getEnd_Dt().



    If you additionally need to check that each machine has start date and end date in the right order (using the enhanced for loop):



    for (Machine m : machines) 
    if (m.getEnd_Dt().before(m.getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    As an aside, Java naming conventions don’t use underscores in names (except in a CONSTANT_NAME), so prefer getStrtDt over getStrt_Dt. Or even better, getStartDate.



    That said, Embid123 is correct, you should see if you can replace Date with LocalDate. The Date class has design problems and is long outdated. And despite its name it doesn’t represent a date, but a point in time. LocalDate is part of java.time, the modern Java date and time API, which is so much nicer to work with.



    The other thing you need is to have your database query sort the entries by start date, then you know you get them in the right order.



    What went wrong in your code?



    First, your code is complicated on the border of the unreadable.



    Next, when two entries i and j have start dates in the wrong order, that is, the j date is earlier than the i date, then machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt()) is negative and machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt() is positive. It’s really the same comparison, only reversed. So the product will be negative, your >= 0 condition will be false and you will not throw the exception.



    Only if two entries have the exact same date (down to the millisecond), compareTo returns 0, the product is 0, >= 0 will be true and your exception will be thrown.






    share|improve this answer

























    • Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

      – Syed
      Nov 15 '18 at 12:27











    • Can you please modify the example if possible .. I'm not able to get it..

      – Syed
      Nov 15 '18 at 13:47











    • Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

      – Syed
      Nov 16 '18 at 2:29











    • Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

      – Ole V.V.
      Nov 16 '18 at 7:53















    3














    You’re over-complicating it. It’s enough to check pairwise entries since if a < b are in the right order and b < c are in the right order, then you already know that a < c are also in the right order.



    for(int i = 0; i < machines.size() - 1; i++) 
    if (! machines.get(i).getEnd_Dt().before(machines.get(i + 1).getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    I am using “not before” to mean “on or after”. Or to put it another way, I am requiring each start date to come stricty before the next start date, and if it doesn’t, I throw the exception. Edit: I didn’t know how to get the end date from your object type, so please substitute the correct getter call where I wrote getEnd_Dt().



    If you additionally need to check that each machine has start date and end date in the right order (using the enhanced for loop):



    for (Machine m : machines) 
    if (m.getEnd_Dt().before(m.getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    As an aside, Java naming conventions don’t use underscores in names (except in a CONSTANT_NAME), so prefer getStrtDt over getStrt_Dt. Or even better, getStartDate.



    That said, Embid123 is correct, you should see if you can replace Date with LocalDate. The Date class has design problems and is long outdated. And despite its name it doesn’t represent a date, but a point in time. LocalDate is part of java.time, the modern Java date and time API, which is so much nicer to work with.



    The other thing you need is to have your database query sort the entries by start date, then you know you get them in the right order.



    What went wrong in your code?



    First, your code is complicated on the border of the unreadable.



    Next, when two entries i and j have start dates in the wrong order, that is, the j date is earlier than the i date, then machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt()) is negative and machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt() is positive. It’s really the same comparison, only reversed. So the product will be negative, your >= 0 condition will be false and you will not throw the exception.



    Only if two entries have the exact same date (down to the millisecond), compareTo returns 0, the product is 0, >= 0 will be true and your exception will be thrown.






    share|improve this answer

























    • Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

      – Syed
      Nov 15 '18 at 12:27











    • Can you please modify the example if possible .. I'm not able to get it..

      – Syed
      Nov 15 '18 at 13:47











    • Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

      – Syed
      Nov 16 '18 at 2:29











    • Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

      – Ole V.V.
      Nov 16 '18 at 7:53













    3












    3








    3







    You’re over-complicating it. It’s enough to check pairwise entries since if a < b are in the right order and b < c are in the right order, then you already know that a < c are also in the right order.



    for(int i = 0; i < machines.size() - 1; i++) 
    if (! machines.get(i).getEnd_Dt().before(machines.get(i + 1).getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    I am using “not before” to mean “on or after”. Or to put it another way, I am requiring each start date to come stricty before the next start date, and if it doesn’t, I throw the exception. Edit: I didn’t know how to get the end date from your object type, so please substitute the correct getter call where I wrote getEnd_Dt().



    If you additionally need to check that each machine has start date and end date in the right order (using the enhanced for loop):



    for (Machine m : machines) 
    if (m.getEnd_Dt().before(m.getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    As an aside, Java naming conventions don’t use underscores in names (except in a CONSTANT_NAME), so prefer getStrtDt over getStrt_Dt. Or even better, getStartDate.



    That said, Embid123 is correct, you should see if you can replace Date with LocalDate. The Date class has design problems and is long outdated. And despite its name it doesn’t represent a date, but a point in time. LocalDate is part of java.time, the modern Java date and time API, which is so much nicer to work with.



    The other thing you need is to have your database query sort the entries by start date, then you know you get them in the right order.



    What went wrong in your code?



    First, your code is complicated on the border of the unreadable.



    Next, when two entries i and j have start dates in the wrong order, that is, the j date is earlier than the i date, then machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt()) is negative and machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt() is positive. It’s really the same comparison, only reversed. So the product will be negative, your >= 0 condition will be false and you will not throw the exception.



    Only if two entries have the exact same date (down to the millisecond), compareTo returns 0, the product is 0, >= 0 will be true and your exception will be thrown.






    share|improve this answer















    You’re over-complicating it. It’s enough to check pairwise entries since if a < b are in the right order and b < c are in the right order, then you already know that a < c are also in the right order.



    for(int i = 0; i < machines.size() - 1; i++) 
    if (! machines.get(i).getEnd_Dt().before(machines.get(i + 1).getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    I am using “not before” to mean “on or after”. Or to put it another way, I am requiring each start date to come stricty before the next start date, and if it doesn’t, I throw the exception. Edit: I didn’t know how to get the end date from your object type, so please substitute the correct getter call where I wrote getEnd_Dt().



    If you additionally need to check that each machine has start date and end date in the right order (using the enhanced for loop):



    for (Machine m : machines) 
    if (m.getEnd_Dt().before(m.getStrt_Dt()))
    throw new IllegalStateException("Dates are not in chronological order");




    As an aside, Java naming conventions don’t use underscores in names (except in a CONSTANT_NAME), so prefer getStrtDt over getStrt_Dt. Or even better, getStartDate.



    That said, Embid123 is correct, you should see if you can replace Date with LocalDate. The Date class has design problems and is long outdated. And despite its name it doesn’t represent a date, but a point in time. LocalDate is part of java.time, the modern Java date and time API, which is so much nicer to work with.



    The other thing you need is to have your database query sort the entries by start date, then you know you get them in the right order.



    What went wrong in your code?



    First, your code is complicated on the border of the unreadable.



    Next, when two entries i and j have start dates in the wrong order, that is, the j date is earlier than the i date, then machines.get(j).getStrt_Dt().compareTo(machines.get(i).getStrt_Dt()) is negative and machines.get(i).getStrt_Dt().compareTo(machines.get(j).getStrt_Dt() is positive. It’s really the same comparison, only reversed. So the product will be negative, your >= 0 condition will be false and you will not throw the exception.



    Only if two entries have the exact same date (down to the millisecond), compareTo returns 0, the product is 0, >= 0 will be true and your exception will be thrown.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 15 '18 at 19:42

























    answered Nov 14 '18 at 11:45









    Ole V.V.Ole V.V.

    28.8k63352




    28.8k63352












    • Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

      – Syed
      Nov 15 '18 at 12:27











    • Can you please modify the example if possible .. I'm not able to get it..

      – Syed
      Nov 15 '18 at 13:47











    • Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

      – Syed
      Nov 16 '18 at 2:29











    • Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

      – Ole V.V.
      Nov 16 '18 at 7:53

















    • Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

      – Syed
      Nov 15 '18 at 12:27











    • Can you please modify the example if possible .. I'm not able to get it..

      – Syed
      Nov 15 '18 at 13:47











    • Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

      – Syed
      Nov 16 '18 at 2:29











    • Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

      – Ole V.V.
      Nov 16 '18 at 7:53
















    Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

    – Syed
    Nov 15 '18 at 12:27





    Thank you. But, I need to validate both start date as well as end date should be less than the next object date.. Do I need to add multiple conditions?

    – Syed
    Nov 15 '18 at 12:27













    Can you please modify the example if possible .. I'm not able to get it..

    – Syed
    Nov 15 '18 at 13:47





    Can you please modify the example if possible .. I'm not able to get it..

    – Syed
    Nov 15 '18 at 13:47













    Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

    – Syed
    Nov 16 '18 at 2:29





    Thanks first of all.. But You are just checking the start date should be less than end date.. I requested you that the start date and end date of the first day should be less than start day and end day of the next object in the list. Hence both should be compared with the next level.

    – Syed
    Nov 16 '18 at 2:29













    Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

    – Ole V.V.
    Nov 16 '18 at 7:53





    Just use the second loop too. When you have checked that the start date of the first date is not later than the end date, and the end date is before the next start date, and that start date is also before or on the corresponding end date, then if follows that both start and end date of the first thingie are before both start and end date of the second thingie. And so forth for the entire list.

    – Ole V.V.
    Nov 16 '18 at 7:53













    2














    tl;dr



    Use the modern java.time.LocalDate and org.threeten.extra.LocalDateRange classes to simplify your business logic to basically one line asking if the prior item in the list is not before the current item.



    if ( 
    !
    prior
    .getDateRange()
    .isBefore(
    current.getDateRange()
    )
    ) … handle rule violation …


    See also the correct Answer by Ole V.V.



    Avoid legacy date-time classes



    Never use the badly-designed legacy classes. The java.util.Date class, despite its name, represents a moment, a date with a time-of-day in UTC. The java.sql.Date class pretends to represent a date-only but actually involves a time-of-day and offset as well.



    java.time



    The modern approach uses the java.time classes.



    LocalDate



    The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.



    You may set the month by a number, with sane numbering 1-12 for January-December.



    LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


    Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.



    LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


    You can directly parse strings in standard ISO 8601 format: YYYY-MM-DD



    LocalDate ld = LocalDate.parse( "2018-01-23" ) ; 


    For parsing other formats, search Stack Overflow to learn about DateTimeFormatter.



    LocalDateRange



    You seem to using a pair of dates, a start and stop date, in your Machine class.



    There is a class for that. Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class has some very useful methods for comparing. Using this class greatly simplifies your code, and makes the intent of your business logic more obvious.



    Store your stop/start dates as a LocalDateRange object on your Machine object.



    private LocalDateRange dateRange; 


    Half-Open



    Generally the best approach to tracking a span of time is the Half-Open approach. The beginning is inclusive while the ending is exclusive.



    So a week is defined as starting on one day, such as Monday, and running up to, but not including, the same day of the following week, the next Monday for example. A year starts on January 1 of one year and runs up to, but does include, January 1 of the following year.



    Using Half-Open approach would mean defining your example date like the following. Notice how changing the ending date to the year-long values in rows 1, 3, and 4 matches up with your own definition of the apparent month-long values of rows 2 & 5.





     STRT_DT END_DT
    ---------- ----------
    2014-01-01 2015-01-01
    2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
    2016-01-01 2017-01-01
    2017-01-01 2018-01-01
    2018-01-01 2018-02-01


    Example class: Machine



    Here is some example code for your class Machine.



    package com.basilbourque.example;

    import org.threeten.extra.LocalDateRange;

    import java.time.LocalDate;
    import java.util.List;
    import java.util.Objects;

    public class Machine --------------------------

    public String getName ( )
    return this.name;


    public LocalDateRange getDateRange ( )
    return this.dateRange;



    // -------


    Let's try this class by writing a main method.



     public static void main ( String args ) 
    List < Machine > machines =
    List.of(
    new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
    new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
    new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
    new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
    new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
    );
    // Compare
    for ( int i = 1 ; i < machines.size() ; i++ ) // Using annoying zero-based index counting.
    Machine prior = machines.get( i - 1 );
    Machine current = machines.get( i );
    if ( ! prior.getDateRange().isBefore( current.getDateRange() ) )
    System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );





    When run.




    BAD: Machine at index 0 is not before Machine at index 1 ➙ 2014-01-01/2015-01-01 versus 2013-01-01/2013-02-01




    JDBC 4.2



    As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.



    LocalDate start = myResultSet.getObject( "start_date" , LocalDate.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.



    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.






    share|improve this answer





























      2














      tl;dr



      Use the modern java.time.LocalDate and org.threeten.extra.LocalDateRange classes to simplify your business logic to basically one line asking if the prior item in the list is not before the current item.



      if ( 
      !
      prior
      .getDateRange()
      .isBefore(
      current.getDateRange()
      )
      ) … handle rule violation …


      See also the correct Answer by Ole V.V.



      Avoid legacy date-time classes



      Never use the badly-designed legacy classes. The java.util.Date class, despite its name, represents a moment, a date with a time-of-day in UTC. The java.sql.Date class pretends to represent a date-only but actually involves a time-of-day and offset as well.



      java.time



      The modern approach uses the java.time classes.



      LocalDate



      The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.



      You may set the month by a number, with sane numbering 1-12 for January-December.



      LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


      Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.



      LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


      You can directly parse strings in standard ISO 8601 format: YYYY-MM-DD



      LocalDate ld = LocalDate.parse( "2018-01-23" ) ; 


      For parsing other formats, search Stack Overflow to learn about DateTimeFormatter.



      LocalDateRange



      You seem to using a pair of dates, a start and stop date, in your Machine class.



      There is a class for that. Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class has some very useful methods for comparing. Using this class greatly simplifies your code, and makes the intent of your business logic more obvious.



      Store your stop/start dates as a LocalDateRange object on your Machine object.



      private LocalDateRange dateRange; 


      Half-Open



      Generally the best approach to tracking a span of time is the Half-Open approach. The beginning is inclusive while the ending is exclusive.



      So a week is defined as starting on one day, such as Monday, and running up to, but not including, the same day of the following week, the next Monday for example. A year starts on January 1 of one year and runs up to, but does include, January 1 of the following year.



      Using Half-Open approach would mean defining your example date like the following. Notice how changing the ending date to the year-long values in rows 1, 3, and 4 matches up with your own definition of the apparent month-long values of rows 2 & 5.





       STRT_DT END_DT
      ---------- ----------
      2014-01-01 2015-01-01
      2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
      2016-01-01 2017-01-01
      2017-01-01 2018-01-01
      2018-01-01 2018-02-01


      Example class: Machine



      Here is some example code for your class Machine.



      package com.basilbourque.example;

      import org.threeten.extra.LocalDateRange;

      import java.time.LocalDate;
      import java.util.List;
      import java.util.Objects;

      public class Machine --------------------------

      public String getName ( )
      return this.name;


      public LocalDateRange getDateRange ( )
      return this.dateRange;



      // -------


      Let's try this class by writing a main method.



       public static void main ( String args ) 
      List < Machine > machines =
      List.of(
      new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
      new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
      new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
      new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
      new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
      );
      // Compare
      for ( int i = 1 ; i < machines.size() ; i++ ) // Using annoying zero-based index counting.
      Machine prior = machines.get( i - 1 );
      Machine current = machines.get( i );
      if ( ! prior.getDateRange().isBefore( current.getDateRange() ) )
      System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );





      When run.




      BAD: Machine at index 0 is not before Machine at index 1 ➙ 2014-01-01/2015-01-01 versus 2013-01-01/2013-02-01




      JDBC 4.2



      As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.



      LocalDate start = myResultSet.getObject( "start_date" , LocalDate.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.



      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.






      share|improve this answer



























        2












        2








        2







        tl;dr



        Use the modern java.time.LocalDate and org.threeten.extra.LocalDateRange classes to simplify your business logic to basically one line asking if the prior item in the list is not before the current item.



        if ( 
        !
        prior
        .getDateRange()
        .isBefore(
        current.getDateRange()
        )
        ) … handle rule violation …


        See also the correct Answer by Ole V.V.



        Avoid legacy date-time classes



        Never use the badly-designed legacy classes. The java.util.Date class, despite its name, represents a moment, a date with a time-of-day in UTC. The java.sql.Date class pretends to represent a date-only but actually involves a time-of-day and offset as well.



        java.time



        The modern approach uses the java.time classes.



        LocalDate



        The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.



        You may set the month by a number, with sane numbering 1-12 for January-December.



        LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


        Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.



        LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


        You can directly parse strings in standard ISO 8601 format: YYYY-MM-DD



        LocalDate ld = LocalDate.parse( "2018-01-23" ) ; 


        For parsing other formats, search Stack Overflow to learn about DateTimeFormatter.



        LocalDateRange



        You seem to using a pair of dates, a start and stop date, in your Machine class.



        There is a class for that. Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class has some very useful methods for comparing. Using this class greatly simplifies your code, and makes the intent of your business logic more obvious.



        Store your stop/start dates as a LocalDateRange object on your Machine object.



        private LocalDateRange dateRange; 


        Half-Open



        Generally the best approach to tracking a span of time is the Half-Open approach. The beginning is inclusive while the ending is exclusive.



        So a week is defined as starting on one day, such as Monday, and running up to, but not including, the same day of the following week, the next Monday for example. A year starts on January 1 of one year and runs up to, but does include, January 1 of the following year.



        Using Half-Open approach would mean defining your example date like the following. Notice how changing the ending date to the year-long values in rows 1, 3, and 4 matches up with your own definition of the apparent month-long values of rows 2 & 5.





         STRT_DT END_DT
        ---------- ----------
        2014-01-01 2015-01-01
        2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
        2016-01-01 2017-01-01
        2017-01-01 2018-01-01
        2018-01-01 2018-02-01


        Example class: Machine



        Here is some example code for your class Machine.



        package com.basilbourque.example;

        import org.threeten.extra.LocalDateRange;

        import java.time.LocalDate;
        import java.util.List;
        import java.util.Objects;

        public class Machine --------------------------

        public String getName ( )
        return this.name;


        public LocalDateRange getDateRange ( )
        return this.dateRange;



        // -------


        Let's try this class by writing a main method.



         public static void main ( String args ) 
        List < Machine > machines =
        List.of(
        new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
        new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
        new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
        new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
        new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
        );
        // Compare
        for ( int i = 1 ; i < machines.size() ; i++ ) // Using annoying zero-based index counting.
        Machine prior = machines.get( i - 1 );
        Machine current = machines.get( i );
        if ( ! prior.getDateRange().isBefore( current.getDateRange() ) )
        System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );





        When run.




        BAD: Machine at index 0 is not before Machine at index 1 ➙ 2014-01-01/2015-01-01 versus 2013-01-01/2013-02-01




        JDBC 4.2



        As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.



        LocalDate start = myResultSet.getObject( "start_date" , LocalDate.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.



        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.






        share|improve this answer















        tl;dr



        Use the modern java.time.LocalDate and org.threeten.extra.LocalDateRange classes to simplify your business logic to basically one line asking if the prior item in the list is not before the current item.



        if ( 
        !
        prior
        .getDateRange()
        .isBefore(
        current.getDateRange()
        )
        ) … handle rule violation …


        See also the correct Answer by Ole V.V.



        Avoid legacy date-time classes



        Never use the badly-designed legacy classes. The java.util.Date class, despite its name, represents a moment, a date with a time-of-day in UTC. The java.sql.Date class pretends to represent a date-only but actually involves a time-of-day and offset as well.



        java.time



        The modern approach uses the java.time classes.



        LocalDate



        The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.



        You may set the month by a number, with sane numbering 1-12 for January-December.



        LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


        Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.



        LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


        You can directly parse strings in standard ISO 8601 format: YYYY-MM-DD



        LocalDate ld = LocalDate.parse( "2018-01-23" ) ; 


        For parsing other formats, search Stack Overflow to learn about DateTimeFormatter.



        LocalDateRange



        You seem to using a pair of dates, a start and stop date, in your Machine class.



        There is a class for that. Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class has some very useful methods for comparing. Using this class greatly simplifies your code, and makes the intent of your business logic more obvious.



        Store your stop/start dates as a LocalDateRange object on your Machine object.



        private LocalDateRange dateRange; 


        Half-Open



        Generally the best approach to tracking a span of time is the Half-Open approach. The beginning is inclusive while the ending is exclusive.



        So a week is defined as starting on one day, such as Monday, and running up to, but not including, the same day of the following week, the next Monday for example. A year starts on January 1 of one year and runs up to, but does include, January 1 of the following year.



        Using Half-Open approach would mean defining your example date like the following. Notice how changing the ending date to the year-long values in rows 1, 3, and 4 matches up with your own definition of the apparent month-long values of rows 2 & 5.





         STRT_DT END_DT
        ---------- ----------
        2014-01-01 2015-01-01
        2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
        2016-01-01 2017-01-01
        2017-01-01 2018-01-01
        2018-01-01 2018-02-01


        Example class: Machine



        Here is some example code for your class Machine.



        package com.basilbourque.example;

        import org.threeten.extra.LocalDateRange;

        import java.time.LocalDate;
        import java.util.List;
        import java.util.Objects;

        public class Machine --------------------------

        public String getName ( )
        return this.name;


        public LocalDateRange getDateRange ( )
        return this.dateRange;



        // -------


        Let's try this class by writing a main method.



         public static void main ( String args ) 
        List < Machine > machines =
        List.of(
        new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
        new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
        new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
        new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
        new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
        );
        // Compare
        for ( int i = 1 ; i < machines.size() ; i++ ) // Using annoying zero-based index counting.
        Machine prior = machines.get( i - 1 );
        Machine current = machines.get( i );
        if ( ! prior.getDateRange().isBefore( current.getDateRange() ) )
        System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );





        When run.




        BAD: Machine at index 0 is not before Machine at index 1 ➙ 2014-01-01/2015-01-01 versus 2013-01-01/2013-02-01




        JDBC 4.2



        As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.



        LocalDate start = myResultSet.getObject( "start_date" , LocalDate.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.



        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 15 '18 at 20:52

























        answered Nov 14 '18 at 23:10









        Basil BourqueBasil Bourque

        111k27378542




        111k27378542





















            0














            Are you using LocalDate? I think it is a good choice for comparing dates. It is since Java 8.



             package sample;

            import java.time.LocalDate;
            import java.time.temporal.ChronoUnit;

            public class LocalDateTest

            public static void main(String args)


            //of(year, month, day)
            LocalDate date1 = LocalDate.of(2018, 11, 11);

            LocalDate date2 = LocalDate.of(2018, 11, 14);

            long daysBetween = ChronoUnit.DAYS.between(date1, date2);

            System.out.println(daysBetween);




            LocalDate hasn't got any public constructor, you create an object via static factory method.
            By the use of enum ChronoUnit, you get a long value representing days, weeks, or years from one date do second date. If you want to e.g. calculate weeks between, simply replace DAYS with WEEKS.



            Now comparing dates is simple, if the value is negative, the first date exceeds the second one.



            Documentation of LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html






            share|improve this answer























            • I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

              – Syed
              Nov 14 '18 at 10:38











            • This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

              – Basil Bourque
              Nov 14 '18 at 23:15
















            0














            Are you using LocalDate? I think it is a good choice for comparing dates. It is since Java 8.



             package sample;

            import java.time.LocalDate;
            import java.time.temporal.ChronoUnit;

            public class LocalDateTest

            public static void main(String args)


            //of(year, month, day)
            LocalDate date1 = LocalDate.of(2018, 11, 11);

            LocalDate date2 = LocalDate.of(2018, 11, 14);

            long daysBetween = ChronoUnit.DAYS.between(date1, date2);

            System.out.println(daysBetween);




            LocalDate hasn't got any public constructor, you create an object via static factory method.
            By the use of enum ChronoUnit, you get a long value representing days, weeks, or years from one date do second date. If you want to e.g. calculate weeks between, simply replace DAYS with WEEKS.



            Now comparing dates is simple, if the value is negative, the first date exceeds the second one.



            Documentation of LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html






            share|improve this answer























            • I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

              – Syed
              Nov 14 '18 at 10:38











            • This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

              – Basil Bourque
              Nov 14 '18 at 23:15














            0












            0








            0







            Are you using LocalDate? I think it is a good choice for comparing dates. It is since Java 8.



             package sample;

            import java.time.LocalDate;
            import java.time.temporal.ChronoUnit;

            public class LocalDateTest

            public static void main(String args)


            //of(year, month, day)
            LocalDate date1 = LocalDate.of(2018, 11, 11);

            LocalDate date2 = LocalDate.of(2018, 11, 14);

            long daysBetween = ChronoUnit.DAYS.between(date1, date2);

            System.out.println(daysBetween);




            LocalDate hasn't got any public constructor, you create an object via static factory method.
            By the use of enum ChronoUnit, you get a long value representing days, weeks, or years from one date do second date. If you want to e.g. calculate weeks between, simply replace DAYS with WEEKS.



            Now comparing dates is simple, if the value is negative, the first date exceeds the second one.



            Documentation of LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html






            share|improve this answer













            Are you using LocalDate? I think it is a good choice for comparing dates. It is since Java 8.



             package sample;

            import java.time.LocalDate;
            import java.time.temporal.ChronoUnit;

            public class LocalDateTest

            public static void main(String args)


            //of(year, month, day)
            LocalDate date1 = LocalDate.of(2018, 11, 11);

            LocalDate date2 = LocalDate.of(2018, 11, 14);

            long daysBetween = ChronoUnit.DAYS.between(date1, date2);

            System.out.println(daysBetween);




            LocalDate hasn't got any public constructor, you create an object via static factory method.
            By the use of enum ChronoUnit, you get a long value representing days, weeks, or years from one date do second date. If you want to e.g. calculate weeks between, simply replace DAYS with WEEKS.



            Now comparing dates is simple, if the value is negative, the first date exceeds the second one.



            Documentation of LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 14 '18 at 10:34









            Embid123Embid123

            25410




            25410












            • I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

              – Syed
              Nov 14 '18 at 10:38











            • This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

              – Basil Bourque
              Nov 14 '18 at 23:15


















            • I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

              – Syed
              Nov 14 '18 at 10:38











            • This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

              – Basil Bourque
              Nov 14 '18 at 23:15

















            I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

            – Syed
            Nov 14 '18 at 10:38





            I'm not using LocalDate..Its Java.util.Date and this comparision should happen between list of objects

            – Syed
            Nov 14 '18 at 10:38













            This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

            – Basil Bourque
            Nov 14 '18 at 23:15






            This Answer does not address the Question. The Question asked about working a with a list of items, each having a pair of dates. The Question asked about comparing the pairs of dates, not elapsed days.

            – Basil Bourque
            Nov 14 '18 at 23:15


















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297784%2fcomparing-date-with-next-object-date-in-arraylist-not-working-as-expected%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            How to read a connectionString WITH PROVIDER in .NET Core?

            In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

            Museum of Modern and Contemporary Art of Trento and Rovereto