Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Date earlier than a month ago

Tags:

java

date

How to check whether the given date is earlier than a month ago? What is the fastest algorithm? I have to take into account that different months have different numbers of days.

like image 311
Michał Ziober Avatar asked Jan 15 '10 22:01

Michał Ziober


3 Answers

Updated to Java 8

The class LocalDate class can be used:

LocalDate aDate = LocalDate.parse("2017-01-01");
return aDate.isBefore( LocalDate.now().minusMonths(1));

For previous versions, the Calendar class would work.

Calendar calendar = Calendar.getInstance();
calendar.add( Calendar.MONTH ,  -1 );
return aDate.compareTo( calendar.getTime() ) < 0;

Sample code:

import static java.lang.System.out;
import java.time.LocalDate;

public class Sample {
    public static void main( String [] args ) {
        LocalDate aMonthAgo = LocalDate.now().minusMonths(1);
        out.println( LocalDate.parse("2009-12-16").isBefore(aMonthAgo));
        out.println( LocalDate.now().isBefore(aMonthAgo));
        out.println( LocalDate.parse("2017-12-24").isBefore(aMonthAgo));
    }
}

Prints

true
false
false
like image 77
OscarRyz Avatar answered Nov 14 '22 20:11

OscarRyz


Using Joda Time:

DateTime dt1 = new DateTime(); //Now
DateTime dt2 = new DateTime(2009,9,1,0,0,0,0); //Other date
if (dt1.plusMonths(-1) > dt2) {
    //Date is earlier than a month ago
}
like image 43
Vinko Vrsalovic Avatar answered Nov 14 '22 22:11

Vinko Vrsalovic


tl;dr

LocalDate.now( ZoneId.of( "America/Montreal"  )
         .minusMonths( 1 )
         .isAfter( LocalDate.parse( "2017-01-23" ) )

java.time

The modern approach uses the java.time classes rather than the troublesome legacy classes such as Date & Calendar.

Today

First get the current date. The LocalDate class represents a date-only value without time-of-day and without 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.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-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 );

Calculating month-ago

Next, determine the date a month ago.

LocalDate monthAgo = today.minusMonths( 1 ) ;

Here are the rules used by LocalDate::minusMonths, quoted from Java 8 class doc:

This method subtracts the specified amount from the months field in three steps:

  1. Subtract the input months from the month-of-year field

  2. Check if the resulting date would be invalid

  3. Adjust the day-of-month to the last valid day if necessary

For example, 2007-03-31 minus one month would result in the invalid date 2007-02-31. Instead of returning an invalid result, the last valid day of the month, 2007-02-28, is selected instead.

Or, perhaps in your business rules you meant "30 days" instead of a calendar month.

LocalDate thirtyDaysAgo = today.minusDays( 30 ) ;

Input

You are given a date. That should be passed to your code as a LocalDate object.

LocalDate ld = LocalDate.of( 2017 , Month.JANUARY , 23 ) ;

If coming from a String, use the standard ISO 8601 formats. For other formats, search Stack Overflow for DateTimeFormatter class.

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

Comparison

Now compare. Call the isBefore, isEqual, isAfter methods.

Boolean outdated = ld.isBefore( monthAgo ) ;

Performance

As for the issue of performance raised in the Question: Don't worry about it. This month-ago calculation and comparison is very unlikely to be a bottleneck in your app. Avoid premature optimization.


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.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • 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
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • 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.

like image 2
Basil Bourque Avatar answered Nov 14 '22 22:11

Basil Bourque