How to get the difference between two dates in Java including the last day?












1















I'm writing automated bdds for a rest API. And the API returns a date. I want to get the difference between the returned date from the API and the current date today.



So for example, the API returns "March 13, 2018 12:00 pm"



And today's date is "March 11, 2018 12:00pm"



The times are always the same, it's only the days that change. And the API will also return a date that's in the future.



I have this piece of code:



Date currentDate = Date.from(Instant.now());
// endDate comes from the API
long diff = endDate.getTime() - currentDate.getTime();
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);


This returns 1, but I want it to include the last day. I can just add +1 at the end of endDate.getTime() - currentDate.getTime(); but I'm not sure if that's the right approach.



I also read that this is not a good solution in general, because it doesn't account for daylight savings time. I'm not sure how or if it would affect my automated bdds when daylight savings comes. What's the best way to capture the difference in days?



Think of it as how many days do I have left until expiration










share|improve this question


















  • 1





    I would use the LocalDate API which is designed to work in days.

    – Peter Lawrey
    Nov 23 '18 at 18:57











  • you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

    – Abhinav Suman
    Nov 23 '18 at 19:02






  • 1





    What are “bdds”?

    – Basil Bourque
    Nov 23 '18 at 19:04











  • You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

    – MC Emperor
    Nov 23 '18 at 19:09













  • Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

    – user10639668
    Nov 23 '18 at 19:14
















1















I'm writing automated bdds for a rest API. And the API returns a date. I want to get the difference between the returned date from the API and the current date today.



So for example, the API returns "March 13, 2018 12:00 pm"



And today's date is "March 11, 2018 12:00pm"



The times are always the same, it's only the days that change. And the API will also return a date that's in the future.



I have this piece of code:



Date currentDate = Date.from(Instant.now());
// endDate comes from the API
long diff = endDate.getTime() - currentDate.getTime();
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);


This returns 1, but I want it to include the last day. I can just add +1 at the end of endDate.getTime() - currentDate.getTime(); but I'm not sure if that's the right approach.



I also read that this is not a good solution in general, because it doesn't account for daylight savings time. I'm not sure how or if it would affect my automated bdds when daylight savings comes. What's the best way to capture the difference in days?



Think of it as how many days do I have left until expiration










share|improve this question


















  • 1





    I would use the LocalDate API which is designed to work in days.

    – Peter Lawrey
    Nov 23 '18 at 18:57











  • you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

    – Abhinav Suman
    Nov 23 '18 at 19:02






  • 1





    What are “bdds”?

    – Basil Bourque
    Nov 23 '18 at 19:04











  • You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

    – MC Emperor
    Nov 23 '18 at 19:09













  • Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

    – user10639668
    Nov 23 '18 at 19:14














1












1








1








I'm writing automated bdds for a rest API. And the API returns a date. I want to get the difference between the returned date from the API and the current date today.



So for example, the API returns "March 13, 2018 12:00 pm"



And today's date is "March 11, 2018 12:00pm"



The times are always the same, it's only the days that change. And the API will also return a date that's in the future.



I have this piece of code:



Date currentDate = Date.from(Instant.now());
// endDate comes from the API
long diff = endDate.getTime() - currentDate.getTime();
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);


This returns 1, but I want it to include the last day. I can just add +1 at the end of endDate.getTime() - currentDate.getTime(); but I'm not sure if that's the right approach.



I also read that this is not a good solution in general, because it doesn't account for daylight savings time. I'm not sure how or if it would affect my automated bdds when daylight savings comes. What's the best way to capture the difference in days?



Think of it as how many days do I have left until expiration










share|improve this question














I'm writing automated bdds for a rest API. And the API returns a date. I want to get the difference between the returned date from the API and the current date today.



So for example, the API returns "March 13, 2018 12:00 pm"



And today's date is "March 11, 2018 12:00pm"



The times are always the same, it's only the days that change. And the API will also return a date that's in the future.



I have this piece of code:



Date currentDate = Date.from(Instant.now());
// endDate comes from the API
long diff = endDate.getTime() - currentDate.getTime();
long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);


This returns 1, but I want it to include the last day. I can just add +1 at the end of endDate.getTime() - currentDate.getTime(); but I'm not sure if that's the right approach.



I also read that this is not a good solution in general, because it doesn't account for daylight savings time. I'm not sure how or if it would affect my automated bdds when daylight savings comes. What's the best way to capture the difference in days?



Think of it as how many days do I have left until expiration







java date






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 18:51









RonApple1996RonApple1996

627




627








  • 1





    I would use the LocalDate API which is designed to work in days.

    – Peter Lawrey
    Nov 23 '18 at 18:57











  • you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

    – Abhinav Suman
    Nov 23 '18 at 19:02






  • 1





    What are “bdds”?

    – Basil Bourque
    Nov 23 '18 at 19:04











  • You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

    – MC Emperor
    Nov 23 '18 at 19:09













  • Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

    – user10639668
    Nov 23 '18 at 19:14














  • 1





    I would use the LocalDate API which is designed to work in days.

    – Peter Lawrey
    Nov 23 '18 at 18:57











  • you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

    – Abhinav Suman
    Nov 23 '18 at 19:02






  • 1





    What are “bdds”?

    – Basil Bourque
    Nov 23 '18 at 19:04











  • You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

    – MC Emperor
    Nov 23 '18 at 19:09













  • Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

    – user10639668
    Nov 23 '18 at 19:14








1




1





I would use the LocalDate API which is designed to work in days.

– Peter Lawrey
Nov 23 '18 at 18:57





I would use the LocalDate API which is designed to work in days.

– Peter Lawrey
Nov 23 '18 at 18:57













you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

– Abhinav Suman
Nov 23 '18 at 19:02





you can use android.text.format.DateUtils.getRelativeTimeSpanString() to get the remaining time like 1 Hours/minutes ago, yesterday & MMM DD, YY format.

– Abhinav Suman
Nov 23 '18 at 19:02




1




1





What are “bdds”?

– Basil Bourque
Nov 23 '18 at 19:04





What are “bdds”?

– Basil Bourque
Nov 23 '18 at 19:04













You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

– MC Emperor
Nov 23 '18 at 19:09







You should use the new Java Date and Time API from the java.time package. With the Period or Duration classes, you can easily calculate the difference, using the between method. It takes DST into consideration, when you provide a timezone.

– MC Emperor
Nov 23 '18 at 19:09















Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

– user10639668
Nov 23 '18 at 19:14





Using your code, the difference between "March 13, 2018 12:00 pm" and "March 11, 2018 12:00 pm" is exactly 2. How did you get 1?

– user10639668
Nov 23 '18 at 19:14












1 Answer
1






active

oldest

votes


















1














Your real problem is that your backend REST service is poorly designed.



ISO 8601



First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.



The standard formats are used by default in the java.time classes when parsing/generating text.



java.time



Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.




Date.from(Instant.now())




Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.



The java.time classes entirely replace their predecessors.




The times are always the same, it's only the days that change. And the API will also return a date that's in the future.




If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.




long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);




Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.



If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.



So your entire problem could be reduced to this one-liner.



ChronoUnit.DAYS.between(
LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
) // Returns a `long` integer number of days elapsed.


Unzoned



If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.



First fix the am/pm which should be in uppercase.



 String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );


Define a formatting pattern to match your input string.



Specify a Locale to determine the human language and cultural norms to use in translating the text.



Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );


Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.



LocalDateTime ldt = LocalDateTime.parse( input , f );



ldt.toString(): 2018-03-13T12:00




A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.



If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.



Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).



A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.



If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.



Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).



ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;


If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.



ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


Get noon on that date, in no particular time zone.



LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;


Count days elapsed.



long daysElapsed = 
ChronoUnit.DAYS.between(
ldtTodayNoon ,
ldt
)
;


Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.



Notice that in your given example, the string represents a date in the past. So our number of days will be negative.



Zoned



If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.



ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;


Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.



LocalDate today = LocalDate.now( z ) ;
ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;


Calculate elapsed time either based in fractional seconds, or in whole calendar days.



Duration d = Duration.between( zdtTodayNoon , zdt ) ;  // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.


If you insist on tracking by a count of milliseconds, call Duration::toMillis.



long millisecondsElapsed = d.toMillis() ;  // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.


All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.





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

























    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%2f53451696%2fhow-to-get-the-difference-between-two-dates-in-java-including-the-last-day%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Your real problem is that your backend REST service is poorly designed.



    ISO 8601



    First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.



    The standard formats are used by default in the java.time classes when parsing/generating text.



    java.time



    Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.




    Date.from(Instant.now())




    Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.



    The java.time classes entirely replace their predecessors.




    The times are always the same, it's only the days that change. And the API will also return a date that's in the future.




    If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.




    long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);




    Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.



    If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.



    So your entire problem could be reduced to this one-liner.



    ChronoUnit.DAYS.between(
    LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
    LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
    ) // Returns a `long` integer number of days elapsed.


    Unzoned



    If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.



    First fix the am/pm which should be in uppercase.



     String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );


    Define a formatting pattern to match your input string.



    Specify a Locale to determine the human language and cultural norms to use in translating the text.



    Locale locale = Locale.US;
    DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );


    Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.



    LocalDateTime ldt = LocalDateTime.parse( input , f );



    ldt.toString(): 2018-03-13T12:00




    A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.



    If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.



    Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).



    A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.



    If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.



    Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).



    ZoneId z = ZoneId.of( "America/Montreal" ) ;  
    LocalDate today = LocalDate.now( z ) ;


    If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.



    ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


    Get noon on that date, in no particular time zone.



    LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;


    Count days elapsed.



    long daysElapsed = 
    ChronoUnit.DAYS.between(
    ldtTodayNoon ,
    ldt
    )
    ;


    Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.



    Notice that in your given example, the string represents a date in the past. So our number of days will be negative.



    Zoned



    If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.



    ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
    ZonedDateTime zdt = ldt.atZone( z ) ;
    ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;


    Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.



    LocalDate today = LocalDate.now( z ) ;
    ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;


    Calculate elapsed time either based in fractional seconds, or in whole calendar days.



    Duration d = Duration.between( zdtTodayNoon , zdt ) ;  // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
    Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.


    If you insist on tracking by a count of milliseconds, call Duration::toMillis.



    long millisecondsElapsed = d.toMillis() ;  // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.


    All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.





    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






























      1














      Your real problem is that your backend REST service is poorly designed.



      ISO 8601



      First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.



      The standard formats are used by default in the java.time classes when parsing/generating text.



      java.time



      Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.




      Date.from(Instant.now())




      Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.



      The java.time classes entirely replace their predecessors.




      The times are always the same, it's only the days that change. And the API will also return a date that's in the future.




      If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.




      long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);




      Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.



      If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.



      So your entire problem could be reduced to this one-liner.



      ChronoUnit.DAYS.between(
      LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
      LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
      ) // Returns a `long` integer number of days elapsed.


      Unzoned



      If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.



      First fix the am/pm which should be in uppercase.



       String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );


      Define a formatting pattern to match your input string.



      Specify a Locale to determine the human language and cultural norms to use in translating the text.



      Locale locale = Locale.US;
      DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );


      Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.



      LocalDateTime ldt = LocalDateTime.parse( input , f );



      ldt.toString(): 2018-03-13T12:00




      A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.



      If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.



      Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).



      A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.



      If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.



      Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).



      ZoneId z = ZoneId.of( "America/Montreal" ) ;  
      LocalDate today = LocalDate.now( z ) ;


      If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.



      ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


      Get noon on that date, in no particular time zone.



      LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;


      Count days elapsed.



      long daysElapsed = 
      ChronoUnit.DAYS.between(
      ldtTodayNoon ,
      ldt
      )
      ;


      Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.



      Notice that in your given example, the string represents a date in the past. So our number of days will be negative.



      Zoned



      If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.



      ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
      ZonedDateTime zdt = ldt.atZone( z ) ;
      ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;


      Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.



      LocalDate today = LocalDate.now( z ) ;
      ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;


      Calculate elapsed time either based in fractional seconds, or in whole calendar days.



      Duration d = Duration.between( zdtTodayNoon , zdt ) ;  // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
      Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.


      If you insist on tracking by a count of milliseconds, call Duration::toMillis.



      long millisecondsElapsed = d.toMillis() ;  // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.


      All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.





      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




























        1












        1








        1







        Your real problem is that your backend REST service is poorly designed.



        ISO 8601



        First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.



        The standard formats are used by default in the java.time classes when parsing/generating text.



        java.time



        Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.




        Date.from(Instant.now())




        Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.



        The java.time classes entirely replace their predecessors.




        The times are always the same, it's only the days that change. And the API will also return a date that's in the future.




        If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.




        long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);




        Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.



        If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.



        So your entire problem could be reduced to this one-liner.



        ChronoUnit.DAYS.between(
        LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
        LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
        ) // Returns a `long` integer number of days elapsed.


        Unzoned



        If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.



        First fix the am/pm which should be in uppercase.



         String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );


        Define a formatting pattern to match your input string.



        Specify a Locale to determine the human language and cultural norms to use in translating the text.



        Locale locale = Locale.US;
        DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );


        Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.



        LocalDateTime ldt = LocalDateTime.parse( input , f );



        ldt.toString(): 2018-03-13T12:00




        A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.



        If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.



        Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).



        A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.



        If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.



        Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).



        ZoneId z = ZoneId.of( "America/Montreal" ) ;  
        LocalDate today = LocalDate.now( z ) ;


        If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.



        ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


        Get noon on that date, in no particular time zone.



        LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;


        Count days elapsed.



        long daysElapsed = 
        ChronoUnit.DAYS.between(
        ldtTodayNoon ,
        ldt
        )
        ;


        Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.



        Notice that in your given example, the string represents a date in the past. So our number of days will be negative.



        Zoned



        If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.



        ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
        ZonedDateTime zdt = ldt.atZone( z ) ;
        ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;


        Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.



        LocalDate today = LocalDate.now( z ) ;
        ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;


        Calculate elapsed time either based in fractional seconds, or in whole calendar days.



        Duration d = Duration.between( zdtTodayNoon , zdt ) ;  // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
        Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.


        If you insist on tracking by a count of milliseconds, call Duration::toMillis.



        long millisecondsElapsed = d.toMillis() ;  // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.


        All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.





        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















        Your real problem is that your backend REST service is poorly designed.



        ISO 8601



        First of all, date-time values exchanged should be in standard ISO 8601 format, not some localized presentation string.



        The standard formats are used by default in the java.time classes when parsing/generating text.



        java.time



        Never use the terrible Date class. That class, along with Calendar, SimpleDateFormat, and such, was supplanted years ago by the java.time classes defined in JSR 310.




        Date.from(Instant.now())




        Never mix the terrible legacy date-time classes (Date) with their replacements (Instant), the modern java.time classes. Mixing these is unnecessary and confusing.



        The java.time classes entirely replace their predecessors.




        The times are always the same, it's only the days that change. And the API will also return a date that's in the future.




        If you only want to exchange date values, without a time-of-day and without a time zone or offset, use LocalDate class, and exchange the ISO 8601 format YYYY-MM-DD such as 2018-03-11. Call LocalDate.parse and LocalDate::toString.




        long differenceInDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);




        Representing a count of days as a count of milliseconds without the context of a time zone or offset-from-UTC is reckless. Days are not always 24 hours long. They can be 23, 23.5, 25, or some other number of hours.



        If you mean to use UTC so as to always have 24-hour days, say so. Represent your date-time with an indication of time zone or offset. For example, the standard format: 2018-03-11T00:00Z where the Z on the end means UTC and is pronounced “Zulu”.



        So your entire problem could be reduced to this one-liner.



        ChronoUnit.DAYS.between(
        LocalDate.now( ZoneId.of( "America/Montreal" ) ) , // Get the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
        LocalDate.parse( "2019-01-23" ) // Parse a string in standard ISO 8601 format for a date-only value.
        ) // Returns a `long` integer number of days elapsed.


        Unzoned



        If you are not in a position to clean up all those messy design problems, then let's forge ahead, trying to use this messy data.



        First fix the am/pm which should be in uppercase.



         String input = "March 13, 2018 12:00 pm".replace( " am" , " AM" ).replace( " pm" , " PM" );


        Define a formatting pattern to match your input string.



        Specify a Locale to determine the human language and cultural norms to use in translating the text.



        Locale locale = Locale.US;
        DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMMM d, uuuu HH:mm a" );


        Parse as a LocalDateTime because your input lacks an indicator of time zone or offset-from-UTC.



        LocalDateTime ldt = LocalDateTime.parse( input , f );



        ldt.toString(): 2018-03-13T12:00




        A LocalDateTime purposely has no concept of time zone or offset-from-UTC. So this class cannot represent a moment, is not a point on the timeline.



        If you want generic 24-hour days without regard to the reality of anomalies in wall-clock time used by various people in various places, such as Daylight Saving Time (DST), we can continue to use this class.



        Get the current date as seen in the wall-clock time used the people to whom your app is aimed (a time zone).



        A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.



        If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.



        Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).



        ZoneId z = ZoneId.of( "America/Montreal" ) ;  
        LocalDate today = LocalDate.now( z ) ;


        If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.



        ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


        Get noon on that date, in no particular time zone.



        LocalDateTime ldtTodayNoon = LocalDateTime.of( today , LocalTime.NOON ) ;


        Count days elapsed.



        long daysElapsed = 
        ChronoUnit.DAYS.between(
        ldtTodayNoon ,
        ldt
        )
        ;


        Of course we could just as well have done this using only LocalDate rather than LocalDateTime, but I followed your problem statement as written.



        Notice that in your given example, the string represents a date in the past. So our number of days will be negative.



        Zoned



        If you did want to account for anomalies seen on some dates in some zones, then you should have represented a moment properly, as discussed above, with an indicator of time zone or offset-from-UTC.



        ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
        ZonedDateTime zdt = ldt.atZone( z ) ;
        ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;


        Or perhaps you want noon today in the desired time zone. If noon is not a valid time-of-day on this date in this zone, the ZonedDateTime class will adjust. Be sure to read the ZonedDateTime.of JavaDoc to understand the algorithm of that adjustment.



        LocalDate today = LocalDate.now( z ) ;
        ZonedDateTime zdtTodayNoon = ZonedDateTime.of( today , LocalTime.NOON , z ) ;


        Calculate elapsed time either based in fractional seconds, or in whole calendar days.



        Duration d = Duration.between( zdtTodayNoon , zdt ) ;  // For a calculation based in whole seconds plus a fractional second in nanoseconds without regard for a calendar, just using generic 24-hour days.
        Period p = Period.between( zdtTodayNoon , zdt ) ; // For a calculation based in whole days, for a number of years-months-days based on calendar dates.


        If you insist on tracking by a count of milliseconds, call Duration::toMillis.



        long millisecondsElapsed = d.toMillis() ;  // Entire duration as a total number of milliseconds, ignoring any microseconds or nanos.


        All of this has been covered many times already on Stack Overflow. You can learn more and see more examples by searching for these java.time class names.





        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 23 '18 at 20:09

























        answered Nov 23 '18 at 19:18









        Basil BourqueBasil Bourque

        108k25369534




        108k25369534






























            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%2f53451696%2fhow-to-get-the-difference-between-two-dates-in-java-including-the-last-day%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







            Popular posts from this blog

            Sphinx de Gizeh

            Dijon

            Guerrita