2016-09-16 230 views
1

我正在为我的应用程序开发本地日历。但每月重复事件(星期几)是个问题。获取月份的第三个星期五

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

我的代码是

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

提示:如果可能,请使用Java8 Date/Time Apis而不是好日历。日历只是s ***的大时间。 – GhostCat

+0

@GhostCat对不起,我们的系统使用Java7。有没有办法通过使用Java7日历来解决它 –

+0

如果你在Java7上,你可以试试[Joda Time](http://www.joda.org/joda-time/)然后[这个答案](http: //stackoverflow.com/questions/20527998/get-all-fridays-in-a-date-range-in-java)包含一个示例代码。 – DVarga

回答

3

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

需要注意的是MONTHDAY是基础功能,因此,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 - 即十月
  3. 年是正常的 - 2016
  4. 周不为0,所以基于第3周,将是指数3
  5. 时区正常

请参阅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(); 
} 

我通常使用GregorianCalendarCalendar应该只是罚款。

应该大部分(希望)的工作,我已经测试了其他机器和ideone

+0

Fri Oct 14 20:16:10 IST 2016我得到了 –

+0

对不起,你能澄清这是什么?我不明白... – px06

+0

我正在使用java7日历。和时区印度时区(格林尼治标准时间+5:30) –

0

采取不同的方法。如果一个月的第一天是星期六,那么第三个星期五是那个月的第二十一天。延长这七天:

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

你只需要检查一个星期的哪一天是本月的第一天。

1

我可以提出一个决策:

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 
+1

它的工作对我很好..谢谢..我做了一点修改。 –

0

的Java 8的方法如下:

LocalDate thirdFriday = LocalDate 
          .now() 
          .with(lastDayOfMonth()) 
          .with(previous(DayOfWeek.FRIDAY)).minusDays(7); 
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()); 
    } 
} 

或许我们还应该提到的是这个代码是计算的期权到期日,以便搜索引擎可以把它捡起来。

相关问题