Як знайти загальну тиждень у році на Яві?


11

Я працюю над проектом. Там я мушу знайти загальні тижні в році. Я спробував із наступним кодом, але отримав неправильну відповідь: у 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 / ...
Федеріко Klez Culloca

1
Запропонуйте надати своє визначення тижня.
Енді

4
Настає 2020 рік. Будь ласка, уникайте використання тривожної старої спадщини api навколо Dateта Calendar. Використовуйте java.timeнатомість, це набагато краще і простіше.
Забузар

Якщо (рік високосний) і (1 січня - неділя), то 54 інші 53.
Акіна

ти можеш дати мені якийсь код?
Kumaresan Perumal

Відповіді:


7

Використовуючи тут визначення Вікіпедії . Рік має 53 тижні, якщо 1 січня - четвер, або 31 грудня - четвер, інакше - 52 тижні. Це визначення еквівалентне тому, яке ви використовували. Я думаю, що це спосіб простіше перевірити, оскільки вам не потрібно перевіряти високосні роки.

Використання 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;

Максимальний тиждень року 53. Я думаю, що це добре @Naman немає 54 тижня, я вважаю, що правильним рішенням є LocalDate.of (i, 1, 1) .range (WeekFields.ISO.weekOfWeekBasedYear ()). GetMaximum ()
Kumaresan Perumal

1
це дає 53 тижні на 2021 рік. Я думаю, що це неправильно. будь ласка, протестуйте його
Kumaresan Perumal


1
так, це працює. Я випробую з 100 років, то скажу вам. дякую за ваші зусилля
Kumaresan Perumal

1
Я протестував на JDK 1.8.0_101 та 1.8.0_121. Все ще отримуємо 52 тижні 2021 року, як нам належить.
Оле ВВ

7

тл; д-р

Для стандартного стандарту ISO 8601 тиждень використовуйте YearWeekклас із бібліотеки ThreeTen-Extra з потрійним викладом.

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 повних тижня.

Якщо ваше визначення відрізняється, см відповідь на Ole VV .

YearWeek:is53WeekYear

Якщо це відповідає вашому визначенню, додайте до свого проекту бібліотеку ThreeTen-Extra, щоб розширити функціональність java.time, вбудований у Java 8 та новіші версії. Потім у вас є доступ до 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 ) ;

тижнів довгий = 53

weekStart = 2019-12-30

Зауважте, як перший день тижня 2020 року починається з календарного 2019 року.


Я в Індії. Чи потрібно вказати назву країни?
Kumaresan Perumal

@KumaresanPerumal Ні, часовий пояс існує now. Оскільки ви хочете отримати кількість тижнів для конкретного року, а не поточного року, просто використовуйте YearWeek.of(yourYear, 1).
Підмітати

ок, дякую @sweeper Я буду використовувати його
Kumaresan Perumal

@KumaresanPerumal Wikipedia зберігає цей список назв часових поясів. Може бути трохи застарілим. Наскільки мені відомо, у всій Індії використовується часовий пояс Asia/Kolkata, який наразі має зміщення +05: 30. У Java - код: ZoneId.of( "Asia/Kolkata" ). Більше інформації та історії див. У Вікіпедії, Час в Індії .
Василь Бурк

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

Ідея полягає у тому, щоб знайти номер тижня останнього тижня тижня року. Я спробую спочатку з 31 грудня, але це може бути в перший тиждень наступного року. Якщо так, я йду на тиждень назад.

Я досить ретельно перевірив WeekFields.ISO, не стільки з іншими WeekFieldsпредметами, але, як я вже сказав, я вважаю, що це працює.

Якщо ви знаєте на факт, вам завжди знадобиться ISO 8601 напевно, тиждень, я думаю, вам слід піти з однією з хороших відповідей Sweeper і Basil Bourque . Я розмістив це у випадку, якщо вам знадобиться більш гнучке рішення, яке буде працювати з іншими схемами нумерації тижнів.

Використовуйте java.time

Код у вашому питанні смішний тим, що він імпортує класи як з Joda-Time, так і з java.time, але використовує старі Calendarта GregorianCalendarз Java 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 тижні кожен). Однак, можливо, переконати себе у цьому складно.
Оле ВВ

Здається, це дає 53 тижні на всі високосні роки, але це не правильно.
Оле ВВ

@ OleV.V. Хм, досить справедливо. Мені цікаво, як тоді працюють обчислення LocalDate під кришкою. Дурна Земля і трохи недосконалий часовий цикл, що робить речі складнішими, ніж вони мають бути.
Тім Хантер


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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.