Joda-Time - Как найти "Второй четверг месяца"
Я не вижу хорошего способа установить дату для определенного дня недели для определенной недели месяца. LocalDate Joda-Time не имеет метода withWeekOfMonth. Я вижу возможный алгоритм, но он кажется слишком сложным, поэтому я предполагаю, что что-то упустил. Что мне нужно, это определить следующую дату, когда кому-то платят. И если им платят во второй четверг месяца, какая это дата?
Кто-нибудь уже решил эту проблему?
Хорошо, я смог придумать это, который, кажется, работает нормально.
/**
* Finds a date such as 2nd Tuesday of a month.
*/
public static LocalDate calcDayOfWeekOfMonth( final DayOfWeek pDayOfWeek, final int pWeekOfMonth, final LocalDate pStartDate )
{
LocalDate result = pStartDate;
int month = result.getMonthOfYear();
result = result.withDayOfMonth( 1 );
result = result.withDayOfWeek( pDayOfWeek.ordinal() );
if ( result.getMonthOfYear() != month )
{
result = result.plusWeeks( 1 );
}
result = result.plusWeeks( pWeekOfMonth - 1 );
return result;
}
3 ответа
Лично я не знаю ни одного сверхпростого способа сделать это, вот что я использую, чтобы получить его:
/**
* Calculates the nth occurrence of a day of the week, for a given month and
* year.
*
* @param dayOfWeek
* The day of the week to calculate the day for (In the range of
* [1,7], where 1 is Monday.
* @param month
* The month to calculate the day for.
* @param year
* The year to calculate the day for.
* @param n
* The occurrence of the weekday to calculate. (ie. 1st, 2nd,
* 3rd)
* @return A {@link LocalDate} with the nth occurrence of the day of week,
* for the given month and year.
*/
public static LocalDate nthWeekdayOfMonth(int dayOfWeek, int month, int year, int n) {
LocalDate start = new LocalDate(year, month, 1);
LocalDate date = start.withDayOfWeek(dayOfWeek);
return (date.isBefore(start)) ? date.plusWeeks(n) : date.plusWeeks(n - 1);
}
Пример:
System.out.println(nthWeekdayOfMonth(4, 1, 2012, 2));
Выход:
2012-01-12
Решение с использованием Java-8
java.time
API
С современным API даты и времени Java вы можете передать <tcode id="8818263"></tcode> в качестве аргумента <tcode id="8818264"></tcode> для достижения этой цели.
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
// Test with today's date, 26-Dec-2020
System.out.println(
localDateOnNthDayOfWeekOfMonth(DayOfWeek.THURSDAY, 2, LocalDate.now())
);
}
public static LocalDate localDateOnNthDayOfWeekOfMonth
(
final DayOfWeek dayOfWeek,
final int ordinal,
final LocalDate startDate
) {
return startDate.with(
TemporalAdjusters.dayOfWeekInMonth(ordinal, dayOfWeek)
);
}
}
Выход:
2020-12-10
Узнайте об API даты и времени Java-8 из Trail: Date Time .
Примечание для пользователей Java 6 или 7:
По любой причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать <em><strong>ThreeTen-Backport,</strong></em> который поддерживает большую часть функций java.time для Java 6 и 7. Если вы работаете над проектом Android и на своем уровне Android API по-прежнему не совместим с Java-8, проверьте API-интерфейсы Java 8+, доступные через десугаринг, и Как использовать ThreeTenABP в Android Project .
Пример определения 2-го понедельника
val DateTime.is2ndMonday
get() = dayOfWeek == 1 && dayOfMonth > 7