Come trovare settimane totali di un anno in Java?


11

Sto lavorando a un progetto. Lì dovrei trovare le settimane totali di un anno. Ho provato con il seguente codice, ma ho la risposta sbagliata: 2020 ha 53 settimane, ma questo codice dà 52 settimane.

Dove ho sbagliato in questo codice?

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

    }

}

Produzione:

52


1
Non esattamente un duplicato, ma ha suggerito la lettura: stackoverflow.com/questions/44197872/...
Federico klez Culloca

1
Suggerisci di fornire la definizione di una settimana.
Andy,

4
È il 2020. Si prega di evitare di usare la vecchia data problematica precedente api intorno Datee Calendar. Usa java.timeinvece, è molto meglio e più semplice.
Zabuzard,

Se (l'anno è un salto) e (1 gennaio è domenica), allora 54 altro 53.
Akina

puoi darmi un po 'di codice?
Kumaresan Perumal,

Risposte:


7

Usando la definizione di Wikipedia qui . Un anno ha 53 settimane se il 1 ° gennaio è un giovedì o il 31 dicembre è un giovedì, altrimenti ha 52 settimane. Questa definizione è equivalente a quella che hai usato. Penso che questa sia una condizione molto più facile da verificare, in quanto non è necessario controllare per gli anni bisestili.

Utilizzo delle java.timeAPI Java 8 :

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;

La settimana massima dell'anno 53. Penso che sia buono @Naman non ci sono 54 settimane, penso che la soluzione corretta sia LocalDate.of (i, 1, 1) .range (WeekFields.ISO.weekOfWeekBasedYear ()). GetMaximum ()
Kumaresan Perumal,

1
dà 53 settimane per il 2021. Penso che sia sbagliato. per favore
testalo

1
@KumaresanPerumal Sei sicuro?
Spazzatrice

1
si Funziona. Proverò tra 100 anni, poi te lo dirò. grazie per il tuo sforzo
Kumaresan Perumal,

1
Ho testato su JDK 1.8.0_101 e 1.8.0_121. Ancora 20 settimane nel 2021 come dovremmo.
Ole VV,

7

tl; dr

Per una settimana ISO 8601 standard, utilizzare la YearWeekclasse dalla libreria ThreeTen-Extra con un'istruzione ternaria.

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. 

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

Definisci "settimana"

Devi definire una settimana. Nell'esempio di codice, la definizione di settimana varia in base all'impostazione predefinita corrente della JVM Locale. Quindi i risultati possono variare in fase di esecuzione.

Il tuo codice utilizza anche terribili classi data-ora che sono state soppiantate anni fa dalle moderne classi java.time . Smetti di usare GregorianCalendar& Calendar; sono stati sostituiti per buoni motivi.

Settimana ISO 8601

L'ISO 8601 norma definisce una settimana come:

  • Le settimane iniziano lunedì , finiscono domenica.
  • La settimana n. 1 ha il primo giovedì dell'anno civile.

Tale definizione significa:

  • Il primo e l'ultimo giorno di un anno di riferimento settimanale possono essere i giorni finali / iniziali dell'anno civile precedente / successivo.
  • L'anno su base settimanale ha 52 o 53 settimane complete.

Se la tua definizione differisce, vedi la risposta di Ole VV .

YearWeek:is53WeekYear

Se questo corrisponde alla tua definizione, aggiungi la libreria ThreeTen-Extra al tuo progetto per estendere la funzionalità java.time integrata in Java 8 e versioni successive. Quindi hai accesso alla YearWeekclasse.

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

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

Per chiedere informazioni su un determinato anno settimanale, scegli arbitrariamente qualsiasi settimana dell'anno. Ad esempio, per l'anno 2020 a settimana chiediamo la settimana n. 1.

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

settimaneLungo = 53

weekStart = 30-12-2019

Si noti come il primo giorno dell'anno della settimana del 2020 è dell'anno civile 2019.


Sono in India. Devo specificare il nome del paese?
Kumaresan Perumal,

@KumaresanPerumal No, il fuso orario è lì per now. Dal momento che vuoi ottenere il conteggio delle settimane per un anno specifico, anziché l'anno corrente, basta usare YearWeek.of(yourYear, 1).
Spazzatrice

ok grazie @sweeper lo userò
Kumaresan Perumal il

@KumaresanPerumal Wikipedia mantiene questo elenco di nomi di fuso orario. Potrebbe essere leggermente obsoleto. Per quanto ne so, tutta l'India utilizza il fuso orario Asia/Kolkata, attualmente con un offset di +05: 30. Nel codice Java: ZoneId.of( "Asia/Kolkata" ). Per ulteriori informazioni e cronologia, vedi Wikipedia, Time in India .
Basil Bourque,

4

La soluzione flessibile

Questo dovrebbe funzionare per qualsiasi schema di numerazione settimanale che può essere rappresentato in un WeekFieldsoggetto.

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

L'idea è quella di trovare il numero della settimana dell'ultima settimana dell'anno in base alla settimana. Provo prima con il 31 dicembre, ma potrebbe essere la prima settimana dell'anno successivo. Se è così, ci torno una settimana fa.

Ho provato abbastanza accuratamente WeekFields.ISO, non tanto con altri WeekFieldsoggetti, ma come ho detto, credo che funzioni.

Se sai per certo che avrai sempre bisogno di ISO 8601 settimane, penso che dovresti andare con una delle buone risposte di Sweeper e Basil Bourque . L'ho pubblicato nel caso in cui fosse necessaria una soluzione più flessibile che funzionasse anche con altri schemi di numerazione settimanali.

Usa java.time

Il codice nella tua domanda è divertente in quanto importa classi sia da Joda-Time che da java.time, eppure utilizza il vecchio Calendare GregorianCalendarda Java 1.1. Queste classi sono state progettate male e sono ormai obsolete, non dovresti usarle. Joda-Time è in modalità manutenzione, java.time è subentrato dopo di esso. Che è quello che uso e raccomando di usare.


1

Penso che dovrebbe funzionare anche bene:

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

Bel pensiero. Fornisce il risultato corretto per il 2020 (53 settimane), nonché per il 2019 e il 2021 (52 settimane ciascuno). Tuttavia, potrebbe essere un po 'difficile convincersi.
Ole VV,

Sembra dare 53 settimane per tutti gli anni bisestili, il che non è corretto.
Ole VV,

@ OleV.V. Hmm, abbastanza giusto. Sono curioso di sapere come funzionano i calcoli di LocalDate allora. La stupida Terra e il suo ciclo temporale leggermente imperfetto, rendono le cose più complicate di quanto debbano essere.
Tim Hunter,


0

Dopo aver provato molto in Java 8. Non sono riuscito a trovare una soluzione. poi ho preparato la dipendenza da data e ora di Joda. Mi ha dato una buona risposta come mi aspettavo

codice:

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

Dipendenza di Maven:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.5</version>
</dependency>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.