0

Basically I want to see if someones birthday is within 3 months of todays date. I am going to use Days to do this and just say "90" days.
My thoughts are as follows:

  • I will set a new datetime as todays date and then grab the DOB of the person in question.
  • I will then want to take the day and month from the DOB and the year from Todays date.
  • Then these days, months and years will be merged into one new date.

For example:

DOB 04/05/1987
Today 10/05/2013
NewBirth 04/05/2013

How can I achieve the part where I grab the days/months from one date, years from another, and put these into one date?

(Only key factors, im aware this rule wouldn't run)

import org.joda.time.ReadableInstant;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.Years;

rule"Blah"
salience 1
when
Proposer($dob : dateOfBirth)
then
DateTime NewBirth = new DateTime()
DateTime today = new DateTime();
#grab DOB day and month
#grab Todays year
#turn "NewBirth" into a combination of the above 2 lines
int $birthday = (Days.daysBetween((ReadableInstant)today,(ReadableInstant)NewBirth).getDays());
If ($birthday <= 90){
logger.info("HURRRAAAYYYYYY");
}
end
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • so where is the problem? ^_^ – Ankit May 10 '13 at 12:10
  • 1
    To those voting me down, read what i said before you vote, the site was treating dates as codes and i had to identify what was causing the site not to post. now i figured out what was causing the problem, information is updated. and my question can (hopefully) be answered. Thanks for being so eager to react so negatively though. – Jonathan Spickernell May 10 '13 at 12:10
  • create two `calendar`s out of your current date. Add three months to the second one. the check if the dob `isAfter` the first calendar and if the dob `isBefore` the second calendar – Marco Forberg May 10 '13 at 12:10
  • I wish to know what code i need to put in place to grab the day, month and year. and then compile those in a new date as shown above :) – Jonathan Spickernell May 10 '13 at 12:10
  • @MarcoForberg would this not cause a problem as the year of today and year of DOB would vary by lets say 26 years? – Jonathan Spickernell May 10 '13 at 12:13

4 Answers4

2

I would do it with the standard JDK Calendar

boolean isWithin3Month(int y, int m, int d) {
    Calendar now = Calendar.getInstance();
    Calendar birthday = new GregorianCalendar(y, m, d);
    int currentMonth = now.get(Calendar.MONTH);
    int birthDayMonth = birthday.get(Calendar.MONTH);
    int monthDiff;
    if (birthDayMonth < currentMonth) { // eg birth = Jan (0) and curr = Dec (11) 
        monthDiff = 12 - currentMonth +  birthDayMonth;
    } else {
        monthDiff = birthDayMonth - currentMonth;
    }
    if (monthDiff < 0 || monthDiff > 3) {
        return false;
    } else if (monthDiff == 0) {
        return birthday.get(Calendar.DATE) >= now.get(Calendar.DATE);
    }
    return true;
}
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 1
    considering we already have 2013 this will always return false. Jonthan is right with his comment under the question: you have to reduce the calender you got from `getInstance()` by the difference in years between the current date and the dob. And reduce by another year if still `birthday.isBefore(now)` – Marco Forberg May 10 '13 at 12:28
  • Currently trying to get my head around the above (never used calender before, but it seems the same sort of concept as datetime) The only problem i can see with the above is. If today was 01/09/2013 and the birthday was 31/12/1987, this would return saying it was within 3 months, however it would actually be 3months and 30days away. Thus drastically reducing the accuracy of the calculation – Jonathan Spickernell May 10 '13 at 13:01
  • @Jonathan Spickernell I guess there still a bug in my solution will come back later – Evgeniy Dorofeev May 10 '13 at 13:10
  • @Jonathan Spickernell fixed, hope it's OK at least in principle, if JodaTime gives you a shorter solution go with it – Evgeniy Dorofeev May 10 '13 at 13:27
  • I ended up doing this with jodatime just before you posted this! but i will keep this in mind and i can see some benefits to using it instead of jodatime.~ i could probably reduce this by a couple of lines however below is how i did it – Jonathan Spickernell May 10 '13 at 13:32
1

java.time

The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.

LocalDate

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.

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

You apparently want to know if the birthday anniversary lands between today and 90 days from today. So determine that 90 day limit.

LocalDate ninetyDaysFromToday = today.plusDays( 90 );

Get the birthdate.

LocalDate birthdate = LocalDate.of( 1987 , Month.APRIL , 5 ) ;

MonthDay

The MonthDay class represents, well, a month and a day-of-month, without any year. You can adjust into a year to get a date. Perfect for adjusting that birthday into this year.

If the birthday of this year is already past, then we need to consider next year’s birthday, as the 90 day limit may wrap over into the new year.

MonthDay mdBirthday = MonthDay.from( birthdate );
MonthDay mdToday = MonthDay.from( today );
int y = mdBirthday.isBefore( mdToday ) ? ( today.getYear()+1 ) : today.getYear() ;
LocalDate nextBirthday = mdBirthday.atYear( y );
Boolean nextBirthdayIsWithinNextNinetyDays = nextBirthday.isBefore( ninetyDaysFromToday );

Or another way to do the same.

LocalDate nextBirthday = MonthDay.from( birthdate ).atYear( today.getYear() ) ;  // Possibly the next birthday, not yet sure.
if( nextBirthday.isBefore( today ) ) {
    // This year’s birthday is past, so increment the year to get next birthday.
    nextBirthday = nextBirthday.plusYears( 1 );
}
Boolean nextBirthdayIsWithinNextNinetyDays = nextBirthday.isBefore( ninetyDaysFromToday );

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, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

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 and 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 SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android

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.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

Try DateTime newBirth = new DateTime(today.year(), $dob.monthOfYear(), $dob.dayOfMonth(), 00, 00); instead of the parameterless constructer at the beginning of your then statement.

jschabs
  • 562
  • 4
  • 20
0

Ended up managing to do it with Jodatime,

    rule"Less than 3months before Birthday Discount"
when
    Proposer($dob : dateOfBirth)
then
    DateTime today = new DateTime();
    DateTime newBirth = new DateTime(today.year().get()+"-"+$dob.monthOfYear().get()+"-"+$dob.dayOfMonth().get());
    int $birthday = (Days.daysBetween((ReadableInstant)today,(ReadableInstant)newBirth).getDays());
    if($birthday <=90 && $birthday>0){
    logger.info("discount applied");
    }
end
  • Why construct the `newBirth` value with a string? That can lead to errors. Since you are using JodaTime, you can just start with your `$dob` and use the `withYear` method to apply the current year. [see these docs](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#withYear(int)) – Matt Johnson-Pint May 10 '13 at 15:01