【问题标题】:Joda-Time - How to find "Second Thursday of Month"Joda-Time - 如何找到“每月的第二个星期四”
【发布时间】:2021-03-17 22:38:59
【问题描述】:

我没有看到将日期设置为一个月中某一周的某一天的好方法。 Joda-TimeLocalDate 没有 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;  
}  

【问题讨论】:

  • 如果没有 cmets 应该做什么,您的代码很难阅读(几周后您可能会发现同样难以阅读)。现在签名已经很清楚了。 DayOfWeek 是什么?

标签: java jodatime


【解决方案1】:

我个人不知道有什么超级简单的方法,这是我用来获取它的:

/**
 * 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

【讨论】:

  • 谢谢。我最终做了以下事情:
  • @RayVanEperen 您好,我在评论中看不到您的代码。如果您有自己喜欢的解决方案,请将其作为另一个答案发布。谢谢。
  • 对不起,我把上面的解决方法放在了原帖里。
  • @DanielArdnt :很难确定哪些硬编码整数是常量,哪些是变量(函数的参数)。也许你可以把它重写为一个函数?
  • @leonbloy 好点。我的答案已被重写为一个函数,并且我提供了一个简单的示例。
【解决方案2】:

使用 Java-8 java.time API 的解决方案

使用Java 的modern date-time API,您可以将TemporalAdjusters#dayOfWeekInMonth 作为参数传递给LocalDate#with 来实现此目的。

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

Trail: Date Time 了解 Java-8 日期时间 API。

Java 6 或 7 用户注意事项:

无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7。如果您是为 Android 项目工作,而您的 Android API 级别仍不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

    【解决方案3】:

    如何检测第二个星期一的示例

    val DateTime.is2ndMonday
        get() = dayOfWeek == 1 && dayOfMonth > 7
    

    【讨论】:

    • 这是什么语言?
    • 这是一个 Java 问题,不是 JavaScript。
    • 科特林。顺便说一句,你理解答案的概念并不重要。如果您确实需要,可以将其转换为 Java。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多