Как рассчитать следующий день рождения, используя Joda Time Libaray
У меня есть две даты в формате, например, Дата рождения, предположим, 1995/04/09 и текущая дата 2016/07/24, так как я могу получить месяцы и дни, оставшиеся до следующего дня рождения?
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;
}
Пожалуйста, кто-нибудь, помогите мне Спасибо заранее
3 ответа
java.time
Команда Joda-Time советует перейти на классы java.time.
анализ
Ваше входное значение близко к стандартному формату ISO 8601. Мы можем преобразовать его, заменив косую черту дефисами.
String input = "1995/04/09".replace ( "/" , "-" );
Классы java.time по умолчанию используют форматы ISO 8601 для анализа и генерации строк, представляющих значения даты и времени. Поэтому нет необходимости определять шаблон форматирования. LocalDate
Класс может напрямую анализировать ввод.
LocalDate
LocalDate
класс представляет значение только для даты без времени суток и без часового пояса.
LocalDate dateOfBirth = LocalDate.parse ( input );
MonthDay
Все, что нам нужно для повторяющихся ежегодных мероприятий, таких как день рождения, - это месяц и день. Классы java.time включают MonthDay
для этого.
MonthDay monthDayOfBirth = MonthDay.from ( dateOfBirth );
Далее нам нужна текущая дата. Обратите внимание, что в то время как LocalDate
не хранит часовой пояс внутри, нам нужен часовой пояс, чтобы определить сегодняшнюю дату. В любой момент времени дата меняется по всему миру в зависимости от часового пояса. Например, через несколько минут после полуночи в Париже новый день, а в Монреале все еще "вчера".
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
int year = today.getYear ();
С текущим годом мы можем создать день рождения в этом году, задав MonthDay
пример.
LocalDate nextBirthday = monthDayOfBirth.atYear ( year );
Убедитесь, что определенная дата действительно является следующим днем рождения. Возможно, уже прошло, и в этом случае нам нужно добавить год.
if ( nextBirthday.isBefore ( today ) ) {
nextBirthday = nextBirthday.plusYears ( 1 );
}
Дамп на консоль.
System.out.println ( "input: " + input + " | dateOfBirth: " + dateOfBirth + " | today: " + today + " | nextBirthday: " + nextBirthday );
вход: 1995-04-09 | дата рождения: 1995-04-09 | сегодня: 2016-07-24 | следующий день рождения: 2017-04-09
Period
Теперь мы переходим к подсчету времени до следующего дня рождения. Period
класс представляет промежуток времени в терминах лет, месяцев и дней.
Period period = Period.between ( today , nextBirthday ).normalized ();
Мы можем опросить часть месяцев и часть дней.
int months = period.getMonths();
int days = period.getDays();
Струны
Что касается сообщения этих значений в строке, для обмена данными и, возможно, для некоторых отчетов людям, я предлагаю использовать стандартный формат ISO 8601 для промежутка времени, не привязанного к временной шкале: PnYnMnDTnHnMnS
, P
отмечает начало и T
отделяет часть часов-минут-секунд (если есть). Таким образом, один месяц и шесть дней будут P1M6D
,
Period
а также Duration
классы в java.time используют этот формат по умолчанию в своих toString
методы.
String output = period.toString();
Или создайте свою собственную строку.
String message = months + " Months " + days + " Days";
System.out.println ( "period: " + period.toString () + " | message: " + message );
период: P8M16D | сообщение: 8 месяцев 16 дней
Я хотел бы знать, как использовать DateTimeFormatter
автоматически локализовать на человеческий язык и культурные нормы, определенные Locale
как мы можем с другими типами java.time. Но это не представляется возможным с Period
а также Duration
объекты, к сожалению.
TemporalAdjuster
Может быть возможно упаковать этот код в класс, реализующий TemporalAdjuster
, Тогда вы можете использовать его с простым with
синтаксис.
LocalDate nextBirthday = dateOfBirth.with( MyTemporalAdjusters.nextRecurringMonthDay( myYearMonth ) );
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Где взять классы java.time?
- Java SE 8 и SE 9 и позже
- Встроенный.
- Часть стандартного Java API со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше) специально для Android.
- Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
По вашему вопросу, Вы хотите рассчитать следующий день рождения, используя Йоду. Приведенный ниже код поможет вам определить ближайшие дни рождения.
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);
}
Выход:
8 месяцев 16 дней
Я бы нашел следующую дату рождения
LocalDate today = new LocalDate();
LocalDate birthDate = new LocalDate(1900, 7, 12);
int age = new Period(birthDate, today).getYears();
LocalDate nextBirthday = birthDate.plusYears(age + 1);
Затем посчитайте, сколько времени осталось до этой даты в месяцах и днях.
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);