我正在为我的应用程序开发本地日历。但这是每月重复事件(星期几)的问题。
当我创建一个从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();
}
我知道这个问题。但我不知道如何解决它..有什么方法可以解决它吗?
答案 0 :(得分:3)
你的代码似乎工作得很好,没有什么是我能看到的错误,可能是你的参数错了。
请务必注意,MONTH
和DAY
是基于0的,0 = January
和0 = Sunday
因此,获取第三个星期五的参数应如下所示:
nthWeekdayOfMonth(6, 9, 2016, 3, TimeZone.getTimeZone("Europe/London"));
返回以下输出:
Fri Oct 21 11:06:33 BST 2016
要打破它:
请参阅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个星期五。延长这七天:
您只需要检查一个月的第一天是哪一天。
答案 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日期和时间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。