2011-10-30 131 views
13

我對此有些困難。Java:我如何得到一個月中x天的日期(例如2012年2月的第三個星期一)

我想設置我的日曆,讓我們說:第三個星期一2012年2月 我沒有發現這樣做使用Java這樣的任何方式。

例如,如果我想設置我的日曆在2011年聖誕節,我可以做到這一點很容易,這樣一來:

Calendar when = Calendar.getInstance(); 
when.set (Calendar.MONTH, Calendar.DECEMBER); 
when.set (Calendar.DAY_OF_MONTH, 25) 
when.set (Calendar.YEAR, 2011); 

但我失去了對於如何將其設置爲假設紀念日2012年,這是五月的最後一個星期一。這是我的代碼,但它顯然是錯誤的,因爲我根本不能假設五月的最後一個星期一將在五月第四周這一年:

Calendar when = Calendar.getInstance(); 
when.set (Calendar.DAY_OF_WEEK,Calendar.MONDAY); 
when.set (Calendar.MONTH, Calendar.MAY); 
when.set (Calendar.WEEK_OF_MONTH, 4) 
when.set (Calendar.YEAR, 2012); 

任何建議,我怎麼能編程找到在2012年5月的哪一週(上例中)是最後一個星期一?假設我可以得到這些信息,我應該能夠得到我的代碼上面的工作。

我需要的東西基本上可以用於任何其他示例。有些東西可以爲相同的場景提供確切的一天。例子:

哪個日期是:

  • 5月3日星期四2015年
  • 月的第一個星期一2050
  • 月4日星期二2012
  • 2000年7月的第二個星期三

我真的需要這個對於我的項目,我相信這很簡單,但我沒有任何真正的結果來展示:)而且在網上也找不到任何東西。


補充:

好吧,這是我一直在一個月內得到了最後一個星期一:

when.set (GregorianCalendar.MONTH, GregorianCalendar.MAY); 
when.set (GregorianCalendar.DAY_OF_WEEK, Calendar.MONDAY); 
when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1); 
when.set (Calendar.YEAR, 2012); 

但我不知道我將如何去這樣做,例如在同一個月的星期一,像這樣?

when.set (GregorianCalendar.DAY_OF_WEEK_IN_MONTH, 2); 

有什麼建議嗎?

回答

10

做日期計算在Java中(在一般情況下,做日期時間任何東西,除了最瑣碎的事情)Joda-Time就是答案:

public static LocalDate getNDayOfMonth(int dayweek,int nthweek,int month,int year) { 
    LocalDate d = new LocalDate(year, month, 1).withDayOfWeek(dayweek); 
    if(d.getMonthOfYear() != month) d = d.plusWeeks(1); 
    return d.plusWeeks(nthweek-1); 
} 

public static LocalDate getLastWeekdayOfMonth(int dayweek,int month,int year) { 
    LocalDate d = new LocalDate(year, month, 1).plusMonths(1).withDayOfWeek(dayweek); 
    if(d.getMonthOfYear() != month) d = d.minusWeeks(1); 
    return d; 
} 

public static void main(String[] args) { 
    // second wednesday of oct-2011 
    LocalDate d = getNDayOfMonth(DateTimeConstants.WEDNESDAY, 2, 10, 2011); 
    System.out.println(d); 
    // last wednesday of oct-2011 
    LocalDate dlast = getLastWeekdayOfMonth(DateTimeConstants.WEDNESDAY, 10, 2011); 
    System.out.println(dlast); 
} 

編輯:由於Java 8(2014)新的日期API(包java.time),其靈感來自於/類似於Jodatime,should be preferred

+0

我喜歡這個代碼很多,它實際上工作。我只是不知道如何在本月指定上個星期三(在這種情況下)。你能幫我嗎。 – jjj

+0

我想嘗試類似於:LocalDate d = getNDayOfMonth(DateTimeConstants.WEDNESDAY,-1,10,2011);但它不起作用。 – jjj

+0

@jjj:爲了獲得最後一個星期三的月份需要稍作修改,我爲此添加了一個方法。您也可以使用第一種方法:例如,獲取2001年10月的最後一個星期三,獲取2011年11月的第一個星期三,並減少一週。 – leonbloy

4

我不知道「簡單」的方式,但我可以建議你以下。

  1. 將日曆設置爲本月的第一天。
  2. 檢索其星期幾
  3. 計算月份的第一個星期一的日期。
  4. 使用calendar.add()方法添加14天。你會得到第三個星期一。
0

您正在使用的機會是什麼Quartz scheduler? (?)

public Date date(String cronExpression) { 
    return new org.quartz.CronExpression(cronExpression). 
     getNextValidTimeAfter(new Date(0)); 
} 

System.out.println(date("0 0 0 ? May Thu#3 2015")); 
System.out.println(date("0 0 0 ? Jun Mon#1 2050")); 
System.out.println(date("0 0 0 ? Dec Tue#4 2012")); 
System.out.println(date("0 0 0 ? Jul Wed#2 2000")); 

這個簡單的代碼打印正確的結果:

Thu May 21 00:00:00 CEST 2015 
Mon Jun 06 00:00:00 CEST 2050 
Tue Dec 25 00:00:00 CET 2012 
Wed Jul 12 00:00:00 CEST 2000 

所需CronExpression不會對石英的其他任何相關性,所以你可能會考慮將它複製到你的項目(手錶出許可證)

邊注:內部實行getNextValidTimeAfter()是400行代碼...

1

所有你需要的是一個循環:

public class CalculateDate { 

public static void main(String ... args) { 

    Calendar c = Calendar.getInstance(); 
    c.set(Calendar.YEAR, 2012); 
    c.set(Calendar.MONTH , Calendar.MAY); 
    c.set(Calendar.DAY_OF_MONTH, 0); 
    c.add(Calendar.DAY_OF_MONTH, -1); 

    System.out.println(c.getTime()); 

    int mondaysCount = 0; 

    while (mondaysCount != 4) { 
     c.add(Calendar.DAY_OF_MONTH, 1); 
     if (c.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { 
      mondaysCount++; 
     }  
    } 

    System.out.printf("The fourth monday of may is %s", c.getTime());  

} 

} 
-2

這裏是一個另類。它所做的是:獲取你想要的星期(n)和其他參數,並返回當週的日期。由於日曆給出了上個月的日期(例如2月29日而不是3月7日,因爲3月的第一週與2月的上週相沖突),因此函數計算第二週,如果日期超過了7的倍數或它的每一週。希望有所幫助。

public static int getNthWeekDay (int n, int day, int month, int year) { 
    Calendar calendar = Calendar.getInstance(); 

    calendar.set(Calendar.DAY_OF_WEEK, day); 
    calendar.set(Calendar.MONTH, month); 
    calendar.set(Calendar.WEEK_OF_MONTH,n); 
    calendar.set(Calendar.YEAR, year); 
    if (calendar.get(Calendar.DATE) > n * 7) { 
     calendar.set(Calendar.DAY_OF_WEEK,day); 
     calendar.set(Calendar.MONTH, month); 
     calendar.set(Calendar.WEEK_OF_MONTH,day+1); 

    } 
    return calendar.get(Calendar.DATE); 
} 
+0

也許我不明白你想要做什麼。 2012年,我通過(2012年2月2日,2012年)的方法。結果我得到星期一,2012-03-05。這個月很清楚:Java枚舉爲0,所以對於第2個月我會進行 - 很好。但今天是幾號?根據地區情況,星期日(我想在美國)和星期一的其他地方計算星期幾。但是,它是如何計算的 - 通過1或2?因此,我們可以將星期日設爲0,1或6,7以及星期一設爲0,1或2.因此,星期一在這裏有一個要點。但是星期一到五月的第二個星期一怎麼可能?這看起來不正確。 –

5

下面的代碼測試成功,在2013年和2014年所有節日我知道這並沒有真正回答原來的問題,但我認爲這可能是誰,希望遇到這個帖子的人有用瞭解如何使用日曆處理假日問題。

public static boolean isMajorHoliday(java.util.Date date) { 
    Calendar cal = Calendar.getInstance(); 
    cal.setTime(date); 

    // check if New Year's Day 
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY 
     && cal.get(Calendar.DAY_OF_MONTH) == 1) { 
     return true; 
    } 

    // check if Christmas 
    if (cal.get(Calendar.MONTH) == Calendar.DECEMBER 
     && cal.get(Calendar.DAY_OF_MONTH) == 25) { 
     return true; 
    } 

    // check if 4th of July 
    if (cal.get(Calendar.MONTH) == Calendar.JULY 
     && cal.get(Calendar.DAY_OF_MONTH) == 4) { 
     return true; 
    } 

    // check Thanksgiving (4th Thursday of November) 
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER 
     && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 4 
     && cal.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) { 
     return true; 
    } 

    // check Memorial Day (last Monday of May) 
    if (cal.get(Calendar.MONTH) == Calendar.MAY 
     && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY 
     && cal.get(Calendar.DAY_OF_MONTH) > (31 - 7)) { 
     return true; 
    } 

    // check Labor Day (1st Monday of September) 
    if (cal.get(Calendar.MONTH) == Calendar.SEPTEMBER 
     && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1 
     && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { 
     return true; 
    } 

    // check President's Day (3rd Monday of February) 
    if (cal.get(Calendar.MONTH) == Calendar.FEBRUARY 
     && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3 
     && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { 
     return true; 
    } 

    // check Veterans Day (November 11) 
    if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER 
     && cal.get(Calendar.DAY_OF_MONTH) == 11) { 
     return true; 
    } 

    // check MLK Day (3rd Monday of January) 
    if (cal.get(Calendar.MONTH) == Calendar.JANUARY 
     && cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3 
     && cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { 
     return true; 
    } 

    return false; 

} 
0

TL;博士

LocalDate thirdMondayInFebruary2012 = 
    YearMonth.of(2012 , Month.FEBRUARY) 
      .atDay(1) 
      .with(TemporalAdjusters.dayOfWeekInMonth(3 , DayOfWeek.MONDAY)); 

......還有......

LocalDate lastMondayInMay2012 = 
    YearMonth.of(2012 , Month.MAY) 
      .atDay(1); 
      .with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY)); 

java.time

非常容易使用java.time類,現在取代雙方Joda-做時間和與最早版本的Java捆綁在一起的麻煩的舊日期時間類。

首先我們需要指定所需的月份。 YearMonth類可以做到這一點。從那裏我們得到一個LocalDate,一個沒有時間和沒有時區的日期。

YearMonth ym = YearMonth.of(2012 , Month.FEBRUARY); // Or pass '2' for 'February'. 
LocalDate ld = ym.atDay(1); 

TemporalAdjuster接口提供用於調整日期時間值到另一個日期時間值。 TemporalAdjusters類提供的實現(注意複數的')。使用方便的DayOfWeek枚舉指定星期幾。

int ordinal = 3 ; // Use '3' for 'third occurrence in month' such as '3rd Monday'. 
LocalDate thirdMondayInFebruary2012 = ld.with(TemporalAdjusters.dayOfWeekInMonth(ordinal , DayOfWeek.MONDAY)); 

提示:而不是通過對年份和月份的整數僅僅在你的代碼庫,通過物體,如YearMonthYearMonthDayOfWeek。這樣做消除了歧義,使您的代碼更加自我記錄,提供types-safety,並確保有效的值。

關於java.time

java.time框架是建立在Java 8和更高版本。這些類代替了令人討厭的舊日期時間類,例如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time項目現在位於maintenance mode,建議遷移到java.time。請參閱Oracle Tutorial。並搜索堆棧溢出了很多例子和解釋。

大部分的java.time功能後移植到Java 6 和ThreeTenABP還適於Android(見How to use…)。

ThreeTen-Extra項目擴展java.time與其他類。這個項目是未來可能增加java.time的一個試驗場。您可以在這裏找到一些有用的類,如Interval,YearWeek,YearQuartermore

0
public String nDow(int year, int month, int nweek, int nday) 
{ 
    Calendar cdt = Calendar.getInstance(); 
    cdt.set(year, month -1, 1); 
    return year + "-" + month + "-" + (getPosOfWeekday(cdt.get(Calendar.DAY_OF_WEEK), nday) + ((nweek - 1) *7)); 
} 

private int getPosOfWeekday(int startday, int nday) 
{ 
    nday = weekDayValue(nday); 
    return constructCircularArray(startday).indexOf(nday) + 1; 
} 

private ArrayList<Integer> constructCircularArray(int weekday) 
{ 
    ArrayList<Integer> circularArray = new ArrayList<Integer>(); 
    for(int i = 0; i < 7; i++) 
    { 
     circularArray.add(i, weekDayValue(weekday++)); 
    } 
    return circularArray; 
} 

private int weekDayValue(int x) 
{ 
    return ((x-1) % 7) + 1; 
} 
+0

nDow(2017,11,1,1)將於2017年11月的第一個星期日顯示。nweek是一個月中的第n個星期,而第n天是第n個星期中的第n個星期 – Kishore

相關問題