在Java中获取本月的最后一个星期五

时间:2020-03-05 18:56:59  来源:igfitidea点击:

我正在一个项目中,要求将日期计算为给定月份的最后一个星期五。我认为我有一个仅使用标准Java的解决方案,但我想知道是否有人知道更简洁或者更有效的方法。以下是我今年测试的内容:

for (int month = 0; month < 13; month++) {
        GregorianCalendar d = new GregorianCalendar();
        d.set(d.MONTH, month);
        System.out.println("Last Week of Month in " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + d.getLeastMaximum(d.WEEK_OF_MONTH));
        d.set(d.DAY_OF_WEEK, d.FRIDAY);
        d.set(d.WEEK_OF_MONTH, d.getActualMaximum(d.WEEK_OF_MONTH));
        while (d.get(d.MONTH) > month || d.get(d.MONTH) < month) {
            d.add(d.WEEK_OF_MONTH, -1);
        }
        Date dt = d.getTime();
        System.out.println("Last Friday of Last Week in  " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + dt.toString());
    }

解决方案

回答

有许多有用的方法可以计算星期几。加上一点代数,其中之一应该适合问题。

回答

这看起来是一个完全可以接受的解决方案。如果可行,请使用它。那是最少的代码,除非有必要,否则没有理由对其进行优化。

回答

那行不通。循环将循环13次(0到12)。

回答

稍微简单易读的暴力方法:

public int getLastFriday(int month, int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
    cal.set(Calendar.MILLISECOND, 0);

    int friday = -1;
    while (cal.get(Calendar.MONTH) == month) { 
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { // is it a friday?
            friday = cal.get(Calendar.DAY_OF_MONTH);
            cal.add(Calendar.DAY_OF_MONTH, 7); // skip 7 days
        } else {
            cal.add(Calendar.DAY_OF_MONTH, 1); // skip 1 day
        }
    }
    return friday;
}

回答

我会使用像Jodatime这样的库。它具有非常有用的API,并且使用正常的月份数。最重要的是,它是线程安全的。

我认为我们可以采用以下解决方案(但可能不是最短的解决方案,但肯定更具可读性):

DateTime now = new DateTime();      
DateTime dt = now.dayOfMonth().withMaximumValue().withDayOfWeek(DateTimeConstants.FRIDAY);
if (dt.getMonthOfYear() != now.getMonthOfYear()) {
  dt = dt.minusDays(7);
}       
System.out.println(dt);

回答

我们无需循环就可以找到答案。要确定本月的"最后星期五"日期,请从下个月的第一天开始。减去适当的天数,具体取决于该月的第一天是星期几(数字)。有你的"上周五"。我很确定它可以简化为冗长的单行代码,但是我不是Java开发人员。因此,我将其留给其他人。

回答

尽管我同意scubabbl,但这是一个没有时间的版本。

int year = 2008;
for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; m++) {
    Calendar cal = new GregorianCalendar(year, m, 1);
    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
    int diff = Calendar.FRIDAY - cal.get(Calendar.DAY_OF_WEEK);
    if (diff > 0) {
        diff -= 7;
    }
    cal.add(Calendar.DAY_OF_MONTH, diff);
    System.out.println(cal.getTime());
}

回答

我们需要知道月中天数和月中第一天的工作日这两件事。

如果该月的第一天是

  • 星期日,然后最后一个星期五始终是27日。
  • 星期一,然后最后一个星期五始终是26日。
  • 星期二,那么最后一个星期五始终是25日。
  • 星期三,然后最后一个星期五是第24个,除非一个月中有31天,那么它是第31个
  • 星期四,然后最后一个星期五是23日,除非一个月中有30天或者更多,则为30日。
  • 星期五,最后一个星期五是22日,除非一个月中有29天或者更多,则为29日。
  • 星期六,然后最后一个星期五始终是28日。

只有三种特殊情况。一个switch语句和三个if语句(如果我们希望每种情况都只有一行,则为三元运算符...)

在纸上解决。不需要任何特殊的库,函数,朱利安转换等(嗯,除了获得1日的工作日,还有该月的天数...)

Aaron用Java实现了它。

-亚当

回答

根据marked23的建议:

public Date getLastFriday( int month, int year ) {
   Calendar cal = Calendar.getInstance();
   cal.set( year, month + 1, 1 );
   cal.add( Calendar.DAY_OF_MONTH, -( cal.get( Calendar.DAY_OF_WEEK ) % 7 + 1 ) );
   return cal.getTime();
}

回答

ColinD的解决方案不起作用:尝试在2008年12月运行它,并尝试设置每年的第13个月。但是,用" cal.add(Calendar.MONTH,1)"替换" cal.set(...)"应该可以正常工作。

回答

亚当·戴维斯算法的代码

public static int getLastFriday(int month, int year)
{
Calendar cal = Calendar.getInstance();
cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
cal.set(Calendar.MILLISECOND, 0);

int firstDay = cal.get(Calendar.DAY_OF_WEEK);
int daysOfMonth = cal.getMaximum(Calendar.DAY_OF_MONTH);

switch (firstDay)
{
    case Calendar.SUNDAY :
        return 27;
    case Calendar.MONDAY :
        return 26;
    case Calendar.TUESDAY :
        return 25;
    case Calendar.WEDNESDAY :
        if (daysOfMonth == 31) return 31;
        return 24;
    case Calendar.THURSDAY :
        if (daysOfMonth >= 30) return 30;
        return 23;
    case Calendar.FRIDAY :
        if (daysOfMonth >= 29) return 29;
        return 22;
    case Calendar.SATURDAY :
        return 28;
}
throw new RuntimeException("what day of the month?");
}}

回答

希望这可以帮助..

public static void getSundaysInThisMonth(int monthNumber, int yearNumber){
    //int year =2009;
    //int dayOfWeek = Calendar.SUNDAY;
    // instantiate Calender and set to first Sunday of 2009
    Calendar cal = new GregorianCalendar();
    cal.set(Calendar.MONTH, monthNumber-1);
    cal.set(Calendar.YEAR, yearNumber);
    cal.set(Calendar.DATE, 1);
    int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
    int dateOfWeek = cal.get(Calendar.DATE);
    while (dayOfWeek  != Calendar.SUNDAY) {
       cal.set(Calendar.DATE, ++dateOfWeek);
       dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
      }
    cal.set(Calendar.DATE, dateOfWeek);

    int i = 1;
    while (cal.get(Calendar.YEAR) == yearNumber && cal.get(Calendar.MONTH)==monthNumber-1)
    {
            System.out.println("Sunday " + " " + i + ": " + cal.get(Calendar.DAY_OF_MONTH));
            cal.add(Calendar.DAY_OF_MONTH, 7);
            i++;
    }

  }
  public static void main(String args[]){
    getSundaysInThisMonth(1,2009);
  }

回答

让Calendar.class为我们做魔术;)

pCal.set(GregorianCalendar.DAY_OF_WEEK,Calendar.FRIDAY);
pCal.set(GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);