18

我想获取当前月份的周数。包括上周的上个月天数和下个月的第一周天数。

像这样的东西:

简单是不是?

我想在android上的某个gridview适配器中使用它,并试图操纵这个代码块:

            //FIRST_DAY_OF_WEEK =0;
    int lastDay = month.getActualMaximum(Calendar.DAY_OF_MONTH);
    int firstDay = (int) month.get(Calendar.DAY_OF_WEEK);
    int firstDayNextMonth = nextMonth.get(Calendar.DAY_OF_WEEK);
    int lastDayNextMonth=nextMonth.getActualMaximum(Calendar.DAY_OF_MONTH);
    int nextMonthdays=nextMonth.getMinimalDaysInFirstWeek();

    // figure size of the array
    if (firstDay == 1) {
        days = new String[lastDay + (FIRST_DAY_OF_WEEK * 6)];
    }

    else {
        days = new String[lastDay + firstDay - (FIRST_DAY_OF_WEEK + 1)];
    }
4

7 回答 7

11

Calendar 类的 WEEK_OF_YEAR 属性对您很有用。参考:日历类

创建一个新日期,该日期将是某个月份的第一天。获取这一天的一年中的一周,假设您获得了起始值。

创建一个新日期,该日期将是给定月份的最后一天。获取这一天的一年中的一周,所以现在你得到了最终值。

现在 end - start + 1 应该是你想要的。

当一周与另一年或类似的时间重叠时,您可能必须处理一些极端情况。但我认为一旦你做对了,你就可以用简单的逻辑做到这一点。

这是简单的示例代码。我认为你可以让它发挥作用并传递你想要的任何东西。

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        int start = cal.get(Calendar.WEEK_OF_YEAR);
        Log.d("BLA BLA", "Value is " + start);
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 28);
        int end = cal.get(Calendar.WEEK_OF_YEAR);
        //Above line will not work for December Month, use following line for this
        int end = isDecember?53:cal.get(Calendar.WEEK_OF_YEAR);
        Log.d("BLA BLA", "Value is " + end);
        Log.d("BLA BLA", "Num weeks:: " + (end - start +1 ));

对于角落案例:

极端情况只会发生在 Januaray 月份(例如 2010 年 1 月、2000 年 1 月),在这些情况下,大部分时间都是上一年最后一周的一部分,因此开始值将是 52,结束值将是 5。发生这种情况检查是否,

          if(start > end) {
                numweeks = end + 1;
             }

PS:把它放到你得到的不同的测试输入中。如果您发现任何错误,请告诉我是否可以改进。

甚至更简单的解决方案:

        Calendar cal = Calendar.getInstance();
        for(int i = 0 ; i < 11;i++){
            cal.set(Calendar.YEAR, 2013);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, i);
            int maxWeeknumber = cal.getActualMaximum(Calendar.WEEK_OF_MONTH);
            Log.d("LOG","max week number" + maxWeeknumber);
        }

        01-22 01:49:03.591: D/LOG(573): max week number5
        01-22 01:49:03.602: D/LOG(573): max week number5
        01-22 01:49:03.602: D/LOG(573): max week number6
        01-22 01:49:03.671: D/LOG(573): max week number5
        01-22 01:49:03.671: D/LOG(573): max week number5
        01-22 01:49:03.671: D/LOG(573): max week number6
        01-22 01:49:03.681: D/LOG(573): max week number5
        01-22 01:49:03.691: D/LOG(573): max week number5
        01-22 01:49:03.691: D/LOG(573): max week number5
        01-22 01:49:03.711: D/LOG(573): max week number5
        01-22 01:49:03.711: D/LOG(573): max week number5

简单的解决方案适用于极端情况:

        Calendar cal = Calendar.getInstance();
        for(int i = 0 ; i < 11;i++){
            cal.set(Calendar.YEAR, 2010);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, i);
            int maxWeeknumber = cal.getActualMaximum(Calendar.WEEK_OF_MONTH);
            // Month value starts from 0 to 11 for Jan to Dec
            Log.d("LOG","For Month :: "+ i + " Num Week :: " + maxWeeknumber);
        }

日志:

        01-22 01:59:35.841: D/LOG(629): For Month :: 0 Num Week :: 6
        01-22 01:59:35.841: D/LOG(629): For Month :: 1 Num Week :: 5
        01-22 01:59:35.841: D/LOG(629): For Month :: 2 Num Week :: 5
        01-22 01:59:35.841: D/LOG(629): For Month :: 3 Num Week :: 5
        01-22 01:59:35.841: D/LOG(629): For Month :: 4 Num Week :: 6
        01-22 01:59:35.852: D/LOG(629): For Month :: 5 Num Week :: 5
        01-22 01:59:35.871: D/LOG(629): For Month :: 6 Num Week :: 5
        01-22 01:59:35.871: D/LOG(629): For Month :: 7 Num Week :: 5
        01-22 01:59:35.871: D/LOG(629): For Month :: 8 Num Week :: 5
        01-22 01:59:35.871: D/LOG(629): For Month :: 9 Num Week :: 6
        01-22 01:59:35.871: D/LOG(629): For Month :: 10 Num Week :: 5
于 2013-01-22T09:04:39.920 回答
10

我们可以使用日历类,然后做类似的事情

Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getActualMaximum(Calendar.WEEK_OF_MONTH));

这将返回当前月份的周数

于 2016-05-26T06:30:30.180 回答
8

使用 WEEK_OF_MONTH 会更好,没有跨年问题。

public static void main(String[] args) throws Exception {
  for (String m : new String[] { "2012-11", "2012-12", "2013-01", "2013-02", "2013-03",
              "2013-04", "2013-05", "2013-06" }) {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
      Date date = format.parse(m);
      Calendar c = Calendar.getInstance();
      c.setTime(date);

      int start = c.get(Calendar.WEEK_OF_MONTH);

      c.add(Calendar.MONTH, 1);
      c.add(Calendar.DATE, -1);
      int end = c.get(Calendar.WEEK_OF_MONTH);
      System.out.println(" # of weeks in " + format.format(c.getTime())
              + ": " + (end - start + 1));
  }
}

结果:

# of weeks in 2012-11: 5
# of weeks in 2012-12: 6
# of weeks in 2013-01: 5
# of weeks in 2013-02: 5
# of weeks in 2013-03: 6
# of weeks in 2013-04: 5
# of weeks in 2013-05: 5
# of weeks in 2013-06: 6
于 2013-01-22T09:34:18.140 回答
2

java.time

我建议您使用现代 Java 日期和时间 API java.time 来处理您的日期工作(坦率地说,我很惊讶地看到到目前为止没有任何答案表明这一点)。

public static int getTotalNumberOfWeeks(WeekFields wf, Temporal month) {
    YearMonth ym = YearMonth.from(month);
    int firstWeekNumber = ym.atDay(1).get(wf.weekOfMonth());
    int lastWeekNumber = ym.atEndOfMonth().get(wf.weekOfMonth());
    return lastWeekNumber - firstWeekNumber + 1; // Both weeks inclusive
}

让我们首先尝试使用您问题中的示例月份,即 2013 年 1 月,因此我们知道预期结果是 5。由于您的周从星期日开始,我们也在通话中指定:

    System.out.println(getTotalNumberOfWeeks(
            WeekFields.SUNDAY_START, YearMonth.of(2013, Month.JANUARY)));

输出是预期的:

5

对于一个较新的示例,我将在 2021 年 5 月(撰写本文时的下个月)。因为我住的地方我们使用 ISO 周(从星期一开始),所以我们也尝试一下:

    System.out.println(getTotalNumberOfWeeks(
            WeekFields.ISO, YearMonth.of(2021, Month.MAY)));

6

如果您希望在 JVM 的默认语言环境中使用周数,请WeekFields.of(Locale.getDefault())用作第一个参数。如果你想要当前月份,你可以YearMonth.now(ZoneId.systemDefault())作为第二个传递。为方便起见,我声明了第二个参数 a Temporal。这允许您传递 a LocalDate、 a YearMonth、 a ZonedDateTime、任何定义月份和年份的 java.time 类。

ISO 8601 是可能在世界大部分地区使用的国际标准,它将每月的第 1 周定义为每月至少包含 4 天的第一周。这意味着月初最多三天可能在第 0 周。这就是为什么只查看月休的最大周数的答案的原因。相反,我从最大值中减去最小周数并加 1,因为我们希望这两个周都包含在计数中。

关联

Oracle 教程:日期时间解释如何使用 java.time。

于 2021-04-21T14:03:10.343 回答
0

假设我们知道一个月的第一天(周六、周日等)。

  • 如果该月的第一天是 aSunday并且不是闰年,那么(更正编辑)February月份将只有 4 周。否则,在所有情况下,它应该至少有 5 周,最多 6 周。
  • 现在,如果您的月份从 开始Saturday,您将始终有 6 周(不包括 2 月,届时将有 5 周)
  • 现在,如果您的月份从 开始Friday,那么您将有 6 周的月份有 31 天,而其他月份有 5 周。
  • 对于其他情况,将始终为 5 周。

找出每月的第一天应该不难,您可以使用Calendar或其他日期/时间实用程序库类。但是,我想可能会有更清洁的解决方案来消除极端情况和不必要的复杂性。

于 2013-01-22T09:16:24.537 回答
0

如果你想用“手”来做

用这个:

Date.prototype.getMonthWeek = function(monthAdjustement)
{    

    var firstDay = new Date(this.getFullYear(), this.getMonth(), 1).getDay();

    var returnMessage = (Math.ceil(this.getDate()/7) + Math.floor(((7-firstDay)/7)));

    return returnMessage;

}

与今天的日期相比,哪里monthAdjustement只是调整您寻找的月份的整数。

于 2013-11-12T13:41:25.697 回答
0

Java 的Calendar API对于这种用例非常有用。参考链接:日历文档

我假设你有一个月的开始日期。

  1. 我们需要使用 setTime() 设置 Time(java.util.Date obj) 因为当您创建 Calendar 类的实例时,它默认将时间设置为机器的当前时间和日期

    如果您不需要计算特定月份的总周数,那么您可以简单地避免第一步。

  2. 我们只需要为名为 Calendar.WEEK_OF_MONTH 的字段名称调用 getActualMaximum()。

    public static int getTotalNumberOfWeeks() throws ParseException {
    
        Calendar calendar = Calendar.getInstance();
    
        Date monthStartingDate = new SimpleDateFormat("yyyy-MM- dd").parse("2021-04-01");
    
        calendar.setTime(monthStartingDate);
    
        return calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
    }
    

您也可以通过打印日历的对象在控制台中查看给定日期的更多详细信息。

于 2021-04-21T09:04:06.250 回答