2016-09-16 229 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()); 
    } 
} 

或許我們還應該提到的是這個代碼是計算的期權到期日,以便搜索引擎可以把它撿起來。

相關問題