Shareque
Shareque

Reputation: 361

How to calculate next birthday using Joda time libaray

I have two dates in format like Date of birth suppose 1995/04/09 and current date 2016/07/24 so how can I get Months and Days remaining to next birthday

public String getNextBirthdayMonths() {
     LocalDate dateOfBirth = new LocalDate(startYear, startMonth, startDay);
     LocalDate currentDate = new LocalDate();

     Period period = new Period(dateOfBirth, currentDate);
     PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
                              .appendMonths().appendSuffix(" Months ")
                              .appendDays().appendSuffix(" Days ")
                              .printZeroNever().toFormatter();

        String nextBirthday = periodFormatter.print(period);
        return "" + nextBirthday;
}

Please anyone help me Thanks in advance

Upvotes: 2

Views: 1388

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338775

java.time

The Joda-Time team advises migration to the java.time classes.

Parsing

Your input value is close to standard ISO 8601 format. We can convert it by replacing the slashes with hyphens.

String input = "1995/04/09".replace ( "/" , "-" );

The java.time classes use ISO 8601 formats by default for parsing and generating strings representing date-time values. So no need to define a formatting pattern. The LocalDate class can directly parse the input.

LocalDate

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

LocalDate dateOfBirth = LocalDate.parse ( input );

MonthDay

All we need for recurring annual events such as birthday is the month and the day. The java.time classes include MonthDay for this purpose.

MonthDay monthDayOfBirth = MonthDay.from ( dateOfBirth );

Next we need the current date. Note that while a LocalDate does not store a time zone internally, we need a time zone to determine today’s date. For any given moment the date varies around the world by time zone. For example, a few minutes after midnight is a new day in Paris while still “yesterday” in Montréal.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
int year = today.getYear ();

With the current year in hand, we can create that year’s birthday by asking the MonthDay instance.

LocalDate nextBirthday = monthDayOfBirth.atYear ( year );

Verify that determined date is indeed the next birthday. May have already passed, in which case we need to add a year.

if ( nextBirthday.isBefore ( today ) ) {
    nextBirthday = nextBirthday.plusYears ( 1 );
}

Dump to console.

System.out.println ( "input: " + input + " | dateOfBirth: " + dateOfBirth + " | today: " + today + " | nextBirthday: " + nextBirthday );

input: 1995-04-09 | dateOfBirth: 1995-04-09 | today: 2016-07-24 | nextBirthday: 2017-04-09

Period

Now we move on to calculate the time to elapse until that next birthday. The Period class represents a span of time in terms of years, months and days.

 Period period = Period.between ( today ,  nextBirthday ).normalized ();

We can interrogate for the months part and the days part.

int months = period.getMonths();
int days = period.getDays();

Strings

As for reporting these values in a string, for data exchange and possibly for some reports to humans, I suggest using the standard ISO 8601 format for a span of time not tied to the timeline: PnYnMnDTnHnMnS. The P marks beginning, and T separates the hours-minutes-seconds part (if any). So one month and six days would be P1M6D.

The Period and Duration classes in java.time use this format by default in their toString methods.

String output = period.toString();

Or create your own string.

String message = months + " Months " + days + " Days";
System.out.println ( "period: " + period.toString () + " | message: " + message );

period: P8M16D | message: 8 Months 16 Days

I wish I knew a way to use DateTimeFormatter to automatically localize to a human language and cultural norms specified by a Locale as we can with other java.time types. But this does not seem to be possible with Period and Duration objects, unfortunately.

TemporalAdjuster

It might be possible to package this code up into a class implementing TemporalAdjuster. Then you could use it with the simple with syntax.

LocalDate nextBirthday = dateOfBirth.with( MyTemporalAdjusters.nextRecurringMonthDay( myYearMonth ) );

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?

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.

Upvotes: 0

Unknown
Unknown

Reputation: 2137

As per your question, You want to calculate the next birthday using Joda. The below code will help you to give the coming birthday months.

   LocalDate dateOfBirth = new LocalDate(1995, 4, 9);
   LocalDate currentDate = new LocalDate();
   // Take birthDay  and birthMonth  from dateOfBirth 
   int birthDay = dateOfBirth.getDayOfMonth();
   int birthMonth = dateOfBirth.getMonthOfYear();
   // Current year's birthday
   LocalDate currentYearBirthDay = new LocalDate().withDayOfMonth(birthDay)
                        .withMonthOfYear(birthMonth);
   PeriodType monthDay = PeriodType.yearMonthDayTime().withYearsRemoved();
   PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
        .appendMonths().appendSuffix(" Months ").appendDays()
        .appendSuffix(" Days ").printZeroNever().toFormatter();
   if (currentYearBirthDay.isAfter(currentDate)) {
       Period period = new Period(currentDate, currentYearBirthDay,monthDay );
       String currentBirthday = periodFormatter.print(period);
       System.out.println(currentBirthday );
   } else {
        LocalDate nextYearBirthDay =currentYearBirthDay.plusYears(1);
        Period period = new Period(currentDate, nextYearBirthDay ,monthDay );
        String nextBirthday = periodFormatter.print(period);
        System.out.println(nextBirthday);
   }

Output:

8 Months 16 Days

Upvotes: 3

Nazarii Bardiuk
Nazarii Bardiuk

Reputation: 4342

I would find next birthday date

LocalDate today = new LocalDate();
LocalDate birthDate = new LocalDate(1900, 7, 12);

int age = new Period(birthDate, today).getYears();

LocalDate nextBirthday = birthDate.plusYears(age + 1);

Then count how long it left to that date in months and days

PeriodType monthsAndDays = PeriodType.yearMonthDay().withYearsRemoved();
Period leftToBirthday = new Period(today, nextBirthday, monthsAndDays);

PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
        .appendMonths().appendSuffix(" Months ")
        .appendDays().appendSuffix(" Days ")
        .toFormatter();

return periodFormatter.print(leftToBirthday);

Upvotes: 1

Related Questions