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 ));

コーナーケースの場合:

コーナー ケースは 1 月 (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 に答える
8

use 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())、2 番目として渡すことができます。Temporal便宜上、2 番目のパラメーターを a と宣言しました。これにより、月と年を定義する a LocalDate、 a YearMonth、 a ZonedDateTime、任意の java.time クラスを渡すことができます。

おそらく世界の大部分で使用されている国際標準である ISO 8601 は、月の第 1 週を、月の少なくとも 4 日を含む最初の週と定義しています。これは、月初の最大 3 日が週 0 になる可能性があることを意味します。これが、月の最大週番号のみを調べる回答が壊れている理由です。代わりに、最大週数から最小週数を引き、1 を足します。これは、両方の週をカウントに含めるためです。

リンク

Oracle チュートリアル: Java.time の使用方法を説明する Date Time。

于 2021-04-21T14:03:10.343 に答える
0

月の最初の日 (土曜日、日曜日など) がわかっていると仮定しましょう。

  • 月の 1 日がSundayうるう年でない場合、(修正編集)February月は 4 週間しかありません。それ以外の場合は、すべてのケースで、少なくとも 5 週間、最大で 6 週間必要です。
  • 今、月が から始まる場合、Saturday常に 6 週間になります (2 月の場合を除き、5 週間になります)。
  • ここで、月が から始まる場合、Friday31 日ある月は 6 週間、その他の月は 5 週間になります。
  • それ以外の場合は、常に 5 週間です。

月の最初の日を見つけることは難しくありませんCalendar。または他の日付/時刻ユーティリティ ライブラリ クラスを使用できます。ただし、コーナーケースと不要な複雑さを取り除くよりクリーンなソリューションがあると思います。

于 2013-01-22T09:16:24.537 に答える