Bagaimana menemukan total minggu dalam setahun di Jawa?

11

Saya sedang mengerjakan sebuah proyek. Di sana saya harus menemukan total minggu dalam setahun. Saya mencoba dengan kode berikut, tetapi saya mendapatkan jawaban yang salah: 2020 memiliki 53 minggu, tetapi kode ini memberikan 52 minggu.

Di mana saya salah dalam kode ini?

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

    }

}

Keluaran:

52

Kumaresan Perumal
sumber
1
Bukan duplikat, tetapi disarankan membaca: stackoverflow.com/questions/44197872/…
Federico klez Culloca
1
Sarankan memberikan definisi Anda seminggu.
Andy
4
Ini tahun 2020. Harap hindari menggunakan api tanggal lama yang bermasalah di sekitar Datedan Calendar. Gunakan java.timesebagai gantinya, itu jauh lebih baik dan lebih sederhana.
Zabuzard
Jika (tahun adalah lompatan) dan (1 Januari adalah hari Minggu) maka 54 lainnya 53.
Akina
dapatkah kamu memberi saya beberapa kode?
Kumaresan Perumal

Jawaban:

7

Menggunakan definisi Wikipedia di sini . Satu tahun memiliki 53 minggu jika 1 Januari adalah hari Kamis, atau 31 Desember adalah hari Kamis, jika tidak maka akan ada 52 minggu. Definisi ini setara dengan yang Anda gunakan. Saya pikir ini adalah kondisi yang lebih mudah untuk diperiksa, karena Anda tidak perlu memeriksa tahun kabisat.

Menggunakan Java 8 java.timeAPIs:

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;
Penyapu
sumber
Maksimum minggu di tahun 53. Saya pikir ini bagus @Naman tidak ada 54 minggu, saya pikir solusi yang tepat adalah LocalDate.of (i, 1, 1) .range (WeekFields.ISO.weekOfWeekBasedYear ()). GetMaximum ()
Kumaresan Perumal
1
itu memberi 53 minggu untuk 2021. Saya pikir itu salah. silakan mengujinya
Kumaresan Perumal
1
@KumaresanPerumal Anda yakin?
Penyapu
1
ya itu bekerja. Saya akan menguji dengan 100 tahun kemudian memberitahu Anda. terima kasih atas usaha Anda
Kumaresan Perumal
1
Saya telah menguji JDK 1.8.0_101 dan 1.8.0_121. Masih mendapatkan 52 minggu di 2021 seperti yang seharusnya.
Ole VV
7

tl; dr

Untuk minggu ISO 8601 standar, gunakan YearWeekkelas dari pustaka ThreeTen-Extra dengan pernyataan ternary.

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. 

Itu adalah, YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52

Tentukan "minggu"

Anda perlu menentukan satu minggu. Dalam sampel kode Anda, definisi minggu bervariasi sesuai dengan standar JVM saat ini Locale. Jadi hasil Anda dapat bervariasi saat runtime.

Kode Anda juga menggunakan kelas tanggal-waktu mengerikan yang digantikan tahun lalu oleh kelas java.time modern . Hentikan penggunaan GregorianCalendar& Calendar; mereka diganti karena alasan yang baik.

ISO 8601 minggu

The ISO 8601 standar mendefinisikan seminggu sebagai:

  • Berminggu-minggu dimulai pada hari Senin , berakhir pada hari Minggu.
  • Minggu # 1 memiliki Kamis pertama tahun kalender.

Definisi itu berarti:

  • Beberapa hari pertama dan terakhir dari tahun berbasis-minggu mungkin merupakan trailing / hari-hari utama dari tahun kalender sebelumnya / berikutnya.
  • Tahun berbasis minggu memiliki 52 atau 53 minggu lengkap.

Jika definisi Anda berbeda, lihat Jawaban oleh Ole VV .

YearWeek:is53WeekYear

Jika ini sesuai dengan definisi Anda, kemudian tambahkan pustaka ThreeTen-Extra ke proyek Anda untuk memperluas fungsionalitas java.time yang ada di Java 8 dan yang lebih baru. Anda kemudian memiliki akses ke YearWeekkelas.

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

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

Untuk bertanya tentang tahun tertentu berdasarkan tahun, pilih saja minggu apa saja dalam setahun. Misalnya, untuk tahun 2020 berbasis minggu kami meminta minggu # 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

Perhatikan bagaimana hari pertama tahun berbasis tahun 2020 dari kalender-tahun 2019.

Basil Bourque
sumber
Saya di India. Haruskah saya menentukan nama negara?
Kumaresan Perumal
@KumaresanPerumal Tidak, zona waktu ada untuk now. Karena Anda ingin mendapatkan hitungan minggu untuk tahun tertentu, alih-alih tahun ini, gunakan saja YearWeek.of(yourYear, 1).
Sweeper
ok terima kasih @sweeper saya akan menggunakannya
Kumaresan Perumal
@KumaresanPerumal Wikipedia menyimpan daftar nama zona waktu ini. Mungkin sedikit ketinggalan zaman. Sejauh yang saya tahu, semua India menggunakan zona waktu Asia/Kolkata, saat ini dengan offset +05: 30. Dalam kode Java: ZoneId.of( "Asia/Kolkata" ). Untuk info dan sejarah lebih lanjut, lihat Wikipedia, Waktu di India .
Basil Bourque
4

Solusi fleksibel

Ini harus bekerja untuk setiap skema penomoran minggu yang dapat direpresentasikan dalam suatu WeekFieldsobjek.

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

Idenya adalah untuk menemukan nomor minggu dari minggu terakhir tahun berbasis minggu. Saya coba dulu dengan 31 Desember, tapi itu mungkin di minggu pertama tahun berikutnya. Jika demikian, saya kembali satu minggu.

Saya telah menguji cukup menyeluruh dengan WeekFields.ISO, tidak begitu banyak dengan WeekFieldsbenda lain , tetapi seperti yang saya katakan, saya percaya itu berhasil.

Jika Anda tahu pasti bahwa Anda akan selalu membutuhkan ISO 8601 minggu, saya pikir Anda harus pergi dengan salah satu jawaban yang baik oleh Sweeper dan oleh Basil Bourque . Saya memposting ini jika Anda membutuhkan solusi yang lebih fleksibel yang akan bekerja dengan skema penomoran minggu lainnya juga.

Gunakan java.time

Kode dalam pertanyaan Anda lucu karena mengimpor kelas baik dari Joda-Time dan dari java.time, namun menggunakan yang lama Calendardan GregorianCalendardari Java 1.1. Kelas-kelas ini dirancang dengan buruk dan sekarang sudah usang, Anda tidak boleh menggunakannya. Joda-Time dalam mode pemeliharaan, java.time telah mengambil alih setelahnya. Itulah yang saya gunakan dan sarankan Anda gunakan.

Ole VV
sumber
1

Saya pikir ini harus bekerja dengan baik juga:

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);
Tim Hunter
sumber
Ide bagus. Ini memberikan hasil yang benar untuk 2020 (53 minggu) serta 2019 dan 2021 (masing-masing 52 minggu). Mungkin agak sulit untuk meyakinkan diri sendiri.
Ole VV
Tampaknya memberi 53 minggu untuk semua tahun kabisat, yang tidak benar.
Ole VV
@ OleV.V. Hmm, cukup adil. Saya ingin tahu bagaimana perhitungan LocalDate bekerja di bawah tenda itu. Bumi yang bodoh dan siklus waktunya sedikit tidak sempurna, membuat segalanya lebih rumit dari yang seharusnya.
Tim Hunter
LocalDate.datesUntil adalah Java 9+
ZhekaKozlov
0

Setelah mencoba banyak di java 8. Saya tidak dapat menemukan solusi. kemudian aku menyiapkan tanggal dan waktu ketergantungan Joda. Itu memberi saya jawaban yang baik seperti yang saya harapkan

kode:

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

Ketergantungan Maven:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.5</version>
</dependency>
Kumaresan Perumal
sumber