Javaで1年の合計週を見つける方法は?


11

私はプロジェクトに取り組んでいます。そこで、私は1年の合計週を見つける必要があります。次のコードを試してみましたが、間違った答えが返ってきました。2020年は53週間ですが、このコードでは52週間になります。

このコードのどこが間違っていますか?

package com.hib.mapping;

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Calendar;
import java.util.GregorianCalendar;

import org.joda.time.DateTime;

public class TestWeek {

    public static void main(String args[]) {
        System.out.println(getWeeks());
    }

    public static int getWeeks() {

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2020);
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        GregorianCalendar gregorianCalendar = new GregorianCalendar();

        int weekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (gregorianCalendar.isLeapYear(2020)) {
            if (weekDay == Calendar.THURSDAY || weekDay == Calendar.WEDNESDAY)
                return 53;
            else
                return 52;
        } else {
            if (weekDay == Calendar.THURSDAY)
                return 53;
            else
                return 52;
        }

    }

}

出力:

52


1
ない正確に重複しますが、推奨読書:stackoverflow.com/questions/44197872/...
フェデリコクレズCulloca

1
週の定義を提供することを提案してください。
アンディ

4
それは周り面倒な古いレガシー日付のAPIを使用して2020ください避けているDateCalendarjava.time代わりに使用してください、それははるかに良くて簡単です。
ザブザード

(年はうるう年である)、その後、54他の53(1月1日は日曜日である)場合
明菜

コードをくれませんか?
Kumaresan Perumal

回答:


7

ここでウィキペディアの定義を使用します。1月1日が木曜日の場合、1年は53週間、12月31日は木曜日、それ以外の場合は52週間です。この定義は、使用した定義と同等です。うるう年をチェックする必要がないので、これは簡単にチェックできる状態だと思います。

Java 8 java.timeAPIの使用:

int year = 2020;
boolean is53weekYear = LocalDate.of(year, 1, 1).getDayOfWeek() == DayOfWeek.THURSDAY ||
        LocalDate.of(year, 12, 31).getDayOfWeek() == DayOfWeek.THURSDAY;
int weekCount = is53weekYear ? 53 : 52;

53年の最大週。54週はないので@Namanは良いと思います。正しい解はLocalDate.of(i、1、1).range(WeekFields.ISO.weekOfWeekBasedYear())。getMaximumです。 ()
クマレサンペルマル

1
それは2021年に53週間を与える。それは間違っていると思う。テストしてください
クマレサンペルマル

1
@KumaresanPerumalよろしいですか?
スイーパー

1
そうです。100年試してから教えてあげます。あなたの努力に感謝
クマレサンペルマル

1
JDK 1.8.0_101および1.8.0_121でテストしました。2021年にはまだ52週間あります。
Ole VV

7

tl; dr

標準のISO 8601週の場合は、ThreeTen-ExtraライブラリのYearWeekクラスを3項ステートメントで使用します。

YearWeek          // Represents an entire week of a week-based-year.
.of( 2020 , 1 )   // Pass the number of the week-based-year (*not* calendar year), and a week number ranging from 1 to 52 or 1 to 53.
.is53WeekYear()   // Every standard week-based-year has either 52 or 52 complete weeks.
? 53              // Ternary statement returns 53 if the predicate returns True, …
: 52              // … otherwise returns 52. 

あれは、 YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52

「週」を定義する

週を定義する必要があります。コードサンプルでは、​​週の定義はJVMの現在のデフォルトによって異なりますLocale。したがって、実行時に結果が異なる場合があります。

また、コードでは、数年前に最新のjava.timeクラスに取って代わられた恐ろしい日時クラスを使用しています。GregorianCalendar&の使用をやめるCalendar; それらは正当な理由で置き換えられました。

ISO 8601週

ISO 8601規格では、週定義しますのように:

  • は月曜日に始まりますに日曜日に終わります。
  • 第1週には は暦年の最初の木曜日です。

その定義は以下を意味します:

  • 週ベースの年の最初と最後の数日は、前の/次の暦年の後続/先行日である場合があります。
  • 週ベースの年は、52または53週間あります。

定義が異なる場合は、Anle by Ole VVを参照してください。

YearWeek:is53WeekYear

これが定義と一致する場合は、ThreeTen-Extraライブラリをプロジェクトに追加して、Java 8以降に組み込まれているjava.time機能を拡張します。その後、YearWeekクラスにアクセスできます。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
YearWeek yearWeekNow = YearWeek.now( z ) ;
boolean is53WeekYear = yearWeekNow.is53WeekYear() ;

int weeksLong = yearWeekNow.is53WeekYear() ? 53 : 52 ;

特定の週ベースの年について尋ねるには、その年の任意の週を任意に選択します。たとえば、週ベースの2020年の場合、1週目を求めます。

int weeksLong = YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52 ;
LocalDate weekStart = YearWeek.of( 2020 , 1 ).atDay( DayOfWeek.MONDAY ) ;

weeksLong = 53

weekStart = 2019-12-30

2020年の週ベースの年の最初の日が、2019年の暦日からどのようになっているかに注意してください。


私はインドにいます。国名を指定する必要がありますか?
Kumaresan Perumal

@KumaresanPerumalいいえ、タイムゾーンはありnowます。現在の年ではなく、特定の年の週数を取得したいので、単にを使用しますYearWeek.of(yourYear, 1)
スイーパー

はい、@ sweeperありがとうございます。私が使用します
Kumaresan Perumal

@KumaresanPerumal Wikipediaは、このタイムゾーン名のリストを保持しています。少し古いかもしれません。私の知る限りでは、インドはすべてタイムゾーンisを使用しておりAsia/Kolkata、現在のオフセットは+05:30です。Javaコード:ZoneId.of( "Asia/Kolkata" )。詳細と履歴については、ウィキペディアのTime in Indiaを参照してください。
バジルブルク

4

柔軟なソリューション

これは、WeekFieldsオブジェクトで表すことができるすべての週の番号付けスキームで機能します。

public static int noOfWeeks(WeekFields wf, int year) {
    LocalDate lastDayOfYear = YearMonth.of(year, Month.DECEMBER).atEndOfMonth();
    if (lastDayOfYear.get(wf.weekBasedYear()) > year) { // belongs to following week year
        return lastDayOfYear.minusWeeks(1).get(wf.weekOfWeekBasedYear());
    }
    else {
        return lastDayOfYear.get(wf.weekOfWeekBasedYear());
    }
}

考えは、週ベースの年の最後の週の週番号を見つけることです。最初は12月31日ですが、翌年の最初の週になるかもしれません。その場合、1週間前に戻ります。

私はかなり徹底的にテストしました WeekFields.ISO、他のWeekFieldsオブジェクトではそれほどいませんが、言ったように、うまくいくと思います。

ISO 8601週が常に必要になるという事実を知っているなら、スイーパーの良い答えの1つに行くべきだと思いますバジルブルクの選ぶ。他の週の番号付けスキーマでも機能するより柔軟なソリューションが必要な場合に備えて、これを投稿しました。

java.timeを使用する

あなたの質問のコードは面白いです。Joda-Timeとjava.timeの両方からクラスをインポートしますが、古いコードCalendarGregorianCalendarJava 1.1を使用しています。これらのクラスは設計が不十分で、現在は古くなっているため、使用しないでください。Joda-Timeは保守モードにあり、java.timeがその後を引き継ぎました。これは私が使用するものであり、使用することをお勧めします。


1

これもうまくいくと思います:

int year = 2020;
long numOfWeeks = LocalDate.of(year, 1, 1).datesUntil(LocalDate.of(year, 12, 31), Period.ofDays(7)).count();
System.out.println("Weeks: " + numOfWeeks);

いい考え。2020(53週間)と2019および2021(各52週間)の正しい結果が得られます。しかし、自分を納得させるのは少し難しいかもしれません。
Ole VV

ただし、うるう年はすべて53週間あるようですが、これは正しくありません。
Ole VV

@ OleV.V。うーん、まあまあ。LocalDateの計算が内部でどのように機能するか知りたいです。愚かな地球、それはわずかに不完全な時間サイクルであり、物事は必要以上に複雑になります。
Tim Hunter


0

Java 8でたくさん試した後、私は解決策を見つけることができませんでした。次に、Jodaの日付と時刻の依存関係を準備しました。それは私が期待したように私に良い答えを与えました

コード:

for (int i = 2020; i < 2100; i++) {
  int weeks = new DateTime().withYear(i).weekOfWeekyear().getMaximumValue();
  System.out.println(i + " years : " + weeks); 
}

Mavenの依存関係:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.5</version>
</dependency>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.