获得一个月的第三个星期五

时间:2016-09-16 09:42:52

标签: java calendar

我正在为我的应用程序开发本地日历。但这是每月重复事件(星期几)的问题。

当我创建一个从16-9-2016(16 SEP 2016 FRIDAY)开始并重复每个月的第三个星期五的活动时。但是下个月它会创造第二个     2016年10月14日星期五(这是问题)。下个月它将在第三个星期五。

我的代码是

public Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone);
        calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
        calendar.set(Calendar.WEEK_OF_MONTH, week);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.YEAR, year);
        return calendar.getTime();
    }

我知道这个问题。但我不知道如何解决它..有什么方法可以解决它吗?

9 个答案:

答案 0 :(得分:3)

你的代码似乎工作得很好,没有什么是我能看到的错误,可能是你的参数错了。

请务必注意,MONTHDAY是基于0的,0 = January0 = Sunday因此,获取第三个星期五的参数应如下所示:

nthWeekdayOfMonth(6, 9, 2016, 3, TimeZone.getTimeZone("Europe/London"));

返回以下输出:

Fri Oct 21 11:06:33 BST 2016

要打破它:

  1. 星期几是6,因为星期日= 0。
  2. 月份是9 - 即10月
  3. 一年是正常的 - 2016
  4. 周不是基于0,所以第3周将是索引3
  5. TimeZone正常
  6. 请参阅Calendar documentation以供参考。

    修改

    所以出于某种原因,它可以在我的机器上运行,但它不会在其他机器上运行;我不知道问题是什么,但使用DAY_OF_WEEK_IN_MONTH似乎是一个更好的选择:

    public static Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone);
        calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
        //calendar.set(Calendar.WEEK_OF_MONTH, week);
        calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, week);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.YEAR, year);
        return calendar.getTime();
    }
    

    我通常使用GregorianCalendar,但Calendar应该可以正常使用。

    这个应该(希望)大部分工作,我已经在其他机器和ideone上测试了它。

答案 1 :(得分:2)

我可以提出下一个决定:

public Date nthWeekdayOfMonth(int dayOfWeek, int month, int year, int week, TimeZone timeZone) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(timeZone);
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    // add +1 to week if first weekday of mounth > dayOfWeek
    int localWeek = week;
    if (calendar.get(calendar.DAY_OF_WEEK) > dayOfWeek) {
        localWeek++;
    }
    calendar.set(Calendar.WEEK_OF_MONTH, localWeek);
    calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
    return calendar.getTime();
}

有:

System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.SEPTEMBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));
System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.OCTOBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));
System.out.println(nthWeekdayOfMonth(Calendar.FRIDAY, Calendar.NOVEMBER, 2016, 3, TimeZone.getTimeZone("Europe/London")));

它返回:

Fri Sep 16 19:41:23 YEKT 2016
Fri Oct 21 19:41:23 YEKT 2016
Fri Nov 18 20:41:23 YEKT 2016

答案 2 :(得分:1)

Java 8

LocalDate thirdFriday = java.time.LocalDate.now()
                        .with(TemporalAdjusters.firstDayOfMonth())
                        .with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
                        .plusDays(14)

答案 3 :(得分:0)

采取不同的方法。如果该月的第一天是星期六,则第三个星期五是该月的第21个星期五。延长这七天:

  • 周六1日 - >星期五21日。
  • 周日1日 - >星期五20日。
  • 周一1日 - >星期五19日
  • 星期二1日 - >星期五18日
  • 周三1日 - >星期五17日
  • 周四1日 - >星期五16日
  • 星期五1日 - >星期五15日

您只需要检查一个月的第一天是哪一天。

答案 4 :(得分:0)

Java 8这样做的方法如下:

LocalDate thirdFriday = LocalDate
                            .now()
                            .with(lastDayOfMonth())
                            .with(previous(DayOfWeek.FRIDAY)).minusDays(7);

答案 5 :(得分:0)

这是一个正常运行的Java 8实现。 KayV的例子在2017年9月没有用,但它帮助我朝着正确的方向前进。

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class OptionExpirationDates {

    public static void main(String[] args) {

        LocalDate startDate = LocalDate.of(2017, Month.FEBRUARY, 15);
        List<LocalDate> optionExDates = optionExpirationDates(startDate, 20);

        for (LocalDate temp : optionExDates) {
            System.out.println(temp);
        } 
    }

    public static List<LocalDate> optionExpirationDates(LocalDate startDate, int limit) {
        return Stream.iterate(startDate, date -> date.plusDays(1))
                .map(LocalDate -> LocalDate.with(TemporalAdjusters.firstDayOfMonth()).minusDays(1)
                        .with(TemporalAdjusters.next(DayOfWeek.FRIDAY)).plusWeeks(2))
                .distinct()
                .limit(limit)
                .collect(Collectors.toList());
    }
}

也许我们还应该提一下,这段代码是为了计算一个选项到期日期,以便搜索引擎可以选择它。

答案 6 :(得分:0)

以下功能可用于使用joda时间计算月的第三个星期五。为了清晰起见,这个功能很冗长。

   public static DateTime thirdFridayOfMonth(int year, int month) {
         DateTime firstDayOfMonth = new DateTime(year, month, 1, 0, 0);
         MutableDateTime mFirstDayOfMonth = new MutableDateTime(firstDayOfMonth);

         //Now calculate days to 1st friday from 1st day of month
         int daysToFirstFridayOfMonth = mFirstDayOfMonth.dayOfWeek().get() <= 5 ? (5 - mFirstDayofMonth.dayOfWeek().get()) : (7 - mFirstDayofMonth.dayOfWeek().get() + 5);

         //move to first 1st friday of month
         mFirstDayOfMonth.addDays(daysToFirstFridayOfMonth);

        //move to 3rd friday of month
        mFirstDayOfMonth.addWeeks(2);
        return mFirstDayOfMonth.toDateTime();
    }

答案 7 :(得分:0)

使用Java LocalDateTime

LocalDateTime firstDayOfMonth = LocalDateTime.of(year, Month.of(month), 1, 0, 0);
// Returns 1-7 (NOT 0-6)
int firstDayValue = firstDayOfMonth.getDayOfWeek().getValue();
int thirdFriday = 20 + firstDayValue / 6 * 7 - firstDayValue;    
return LocalDateTime.of(year, Month.of(month), thirdFriday, 0, 0);

答案 8 :(得分:0)

java.time

java.time,现代的Java日期和时间API,对此具有内置的调节器:

public LocalDate nthWeekdayOfMonth(DayOfWeek dayOfWeek, Month month, int year, int week) {
    return LocalDate.of(year, month, 15)
            .with(TemporalAdjusters.dayOfWeekInMonth(week, dayOfWeek));
}

尝试一下:

    System.out.println(nthWeekdayOfMonth(DayOfWeek.FRIDAY, Month.OCTOBER, 2016, 3));

输出:

  

2016-10-21

还请注意,我传递给该方法的参数更能说明问题。

链接: Oracle tutorial: Date Time解释了如何使用java.time。