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
Другие вопросы по тегам