Java'da yılın toplam haftalarını nasıl bulabilirim?


11

Bir proje üzerinde çalışıyorum. Orada bir yılın toplam haftalarını bulmalıyım. Aşağıdaki kod ile denedim, ancak yanlış cevap alıyorum: 2020 53 hafta var, ama bu kod 52 hafta verir.

Bu kodda nerede yanlış yaptım?

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

    }

}

Çıktı:

52


1
Tam olarak tekrar değil, ancak önerilen okuma: stackoverflow.com/questions/44197872/…
Federico klez Culloca

1
Bir haftalık tanımınızı belirtmenizi öneririz.
Andy

4
2020. Lütfen Dateve çevresinde eski sıkıntılı eski api kullanmaktan kaçının Calendar. java.timeBunun yerine kullanın , çok daha iyi ve daha basit.
Zabuzard

Eğer (yıl sıçrama) ve (1 Ocak Pazar ise) o zaman 54 başka 53.
Akina

bana biraz kod verebilir misin
Kumaresan Perumal

Yanıtlar:


7

Wikipedia tanımını burada kullanmak . 1 Ocak Perşembe veya 31 Aralık Perşembe ise bir yıl 53 hafta, aksi takdirde 52 hafta vardır. Bu tanım kullandığınız tanımla eşdeğerdir. Sanırım artık yılları kontrol etmeniz gerekmediği için kontrol edilmesi daha kolay bir durum.

Java 8 java.timeAPI'lerini kullanma :

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. haftanın maksimum haftası iyi. @Naman 54 hafta yok, doğru çözüm LocalDate.of (i, 1, 1) .range (WeekFields.ISO.weekOfWeekBasedYear ()) olduğunu düşünüyorum. ()
Kumaresan Perumal

1
2021 için 53 hafta veriyor. Sanırım yanlış. lütfen test edin
Kumaresan Perumal

1
@KumaresanPerumal Emin misin?
Süpürücü

1
evet çalışıyor. 100 yıl ile test edeceğim ve size söyleyeceğim. çabalarınız için teşekkürler
Kumaresan Perumal

1
JDK 1.8.0_101 ve 1.8.0_121 üzerinde test yaptım. Hâlâ gerektiği gibi 2021'de 52 hafta oluyor.
Ole VV

7

tl; Dr.

Standart bir ISO 8601 haftası için üçlü bir ifadeyle ThreeTen-Extra kütüphanesinden YearWeeksınıfı kullanın .

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. 

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

“Hafta” tanımlayın

Bir hafta tanımlamanız gerekiyor. Kod örneğinizde, haftanın tanımı JVM'nin geçerli varsayılanına göre değişir Locale. Bu nedenle sonuçlarınız çalışma zamanında değişebilir.

Kodunuzda, yıllar önce modern java.time sınıfları tarafından desteklenen korkunç tarih-saat sınıfları da kullanılıyor . GregorianCalendar& Calendar; Kullanmayı bırak iyi nedenlerle değiştirildiler.

ISO 8601 haftası

ISO 8601 standardı bir hafta tanımlar gibidir:

  • Haftalar Pazartesi günü başlar , Pazar günü biter.
  • 1. Hafta , takvim yılının ilk Perşembe günüdür.

Bu tanım şu anlama gelir:

  • Bir haftaya dayanan yılın ilk ve son birkaç günü, önceki / sonraki takvim yılının takip eden / önde gelen günleri olabilir.
  • Haftaya dayalı yıl, 52 veya 53 tam haftaya sahiptir.

Tanımınızdan farklıysa, bkz Ole VV tarafından cevap .

YearWeek:is53WeekYear

Bu, tanımınızla eşleşiyorsa, Java 8 ve sonraki sürümlerinde yerleşik java.time işlevselliğini genişletmek için ThreeTen -Extra kitaplığını projenize ekleyin . Daha sonra sınıfa erişiminiz olur .YearWeek

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

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

Belirli bir haftaya dayalı yılı sormak için yılın herhangi bir haftasını keyfi olarak seçmeniz yeterlidir. Örneğin, hafta temelli 2020 yılı için 1. hafta istiyoruz.

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

haftaUzun = 53

weekStart = 2019-12-30

2020 haftasına dayanan yılın ilk gününün 2019 takvim yılından nasıl olduğuna dikkat edin.


Hindistandayım. Ülke adını belirtmeli miyim?
Kumaresan Perumal

@KumaresanPerumal Hayır, saat dilimi orada now. Geçerli yıl yerine belirli bir yıl için hafta sayısını almak istediğiniz için kullanın YearWeek.of(yourYear, 1).
Süpürücü

tamam teşekkür ederim süpürmek ben kullanacağım
Kumaresan Perumal

@KumaresanPerumal Wikipedia bu saat dilimi adları listesini tutar . Biraz eski olabilir. Bildiğim kadarıyla, tüm Hindistan Asia/Kolkataşu anda +05: 30 ofsetiyle saat dilimini kullanıyor . Java kodunda: ZoneId.of( "Asia/Kolkata" ). Daha fazla bilgi ve tarih için bkz. Wikipedia, Hindistan'da Zaman .
Basil Bourque

4

Esnek çözüm

Bu, bir WeekFieldsnesnede temsil edilebilecek herhangi bir hafta numaralandırma şeması için çalışmalıdır .

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

Buradaki fikir, haftaya göre yılın son haftasının hafta numarasını bulmaktır. İlk olarak 31 Aralık ile deniyorum, ancak bu ertesi yılın ilk haftasında olabilir. Eğer öyleyse, bir hafta geri gidiyorum.

WeekFields.ISODiğer WeekFieldsnesnelerle çok fazla değil, oldukça iyice test ettim , ama dediğim gibi, işe yaradığına inanıyorum.

ISO 8601 haftasına her zaman ihtiyacınız olacak bir gerçeği biliyorsanız , sanırım Süpürge ve Basil Bourque'un iyi cevaplarından biriyle gitmelisiniz . Diğer hafta numaralandırma düzenleriyle de çalışacak daha esnek bir çözüme ihtiyacınız olması durumunda bunu gönderdim.

Java.time kullanın

Sorunuzdaki kod, hem Joda-Time hem de java.time öğelerinden sınıfları içe aktarması, ancak eski Calendarve GregorianCalendarJava 1.1'den sınıfları içe aktarması açısından komik . Bu sınıflar kötü tasarlanmış ve şimdi çok eski, onları kullanmamalısınız. Joda-Time bakım modunda, java.time ondan sonra devraldı. Bunu kullanıyorum ve kullanmanızı tavsiye ederim.


1

Bunun da iyi çalışması gerektiğini düşünüyorum:

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

İyi fikir. Bu, 2020 (53 hafta) ve 2019 ve 2021 (her biri 52 hafta) için doğru sonucu verir. Yine de kendini ikna etmek biraz zor olabilir.
Ole VV

Yine de tüm artık yıllar için 53 hafta veriyor gibi görünüyor, bu doğru değil.
Ole VV

@ OleV.V. Hmm, yeterince adil. O zaman LocalDate hesaplarının kaputun altında nasıl çalıştığını merak ediyorum. Aptal Dünya ve biraz kusurlu zaman döngüsü, şeyleri olması gerekenden daha karmaşık hale getiriyor.
Tim Hunter


0

Java 8'de çok denedikten sonra bir çözüm bulamadım. daha sonra Joda'nın tarih ve zaman bağımlılığını hazırladım. Beklediğim gibi bana iyi bir cevap verdi

kod:

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

Maven Bağımlılığı:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.5</version>
</dependency>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.