Подтвердить что ты не робот

Почему 31 декабря 2010 года возвращается 1 как неделя года?

Например:

Calendar c = Calendar.getInstance();
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
out.println( c.get( Calendar.WEEK_OF_YEAR ) );  

Печать 1

То же самое происходит с временем Джоды.

:)

4b9b3361

Ответ 1

Определение недели года Locale зависит.

Как он определен в США, он обсуждается в других сообщениях. Например, в Германии (DIN 1355-1/ISO 8601): первая неделя * года - это первая неделя с 4 или более днями в новом году.

* первый день недели - понедельник и последний день недели - воскресенье

И Javas Calendar обращает внимание на локаль. Например:

public static void main(String[] args) throws ParseException {

    DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    Date lastDec2010 = sdf.parse("31/12/2010");

    Calendar calUs = Calendar.getInstance(Locale.US);       
    calUs.setTime(lastDec2010);

    Calendar calDe = Calendar.getInstance(Locale.GERMAN);       
    calDe.setTime(lastDec2010);

    System.out.println( "us: " + calUs.get( Calendar.WEEK_OF_YEAR ) ); 
    System.out.println( "de: " + calDe.get( Calendar.WEEK_OF_YEAR ) );
}

печатает:

us: 1
de: 52

ADDED Для США (и я могу думать, что это то же самое для Мексики) 1. Неделя года - это неделя, на которую принадлежит 1. январь. - Итак, если 1. Januar - суббота, то пятница до (31. Dec) относится к той же неделе, и в этом случае этот день относится к 1. Неделе 2011 года.

Ответ 2

Значения, рассчитанные для WEEK_OF_YEAR диапазон полей от 1 до 53. Неделя 1 для год - это самый ранний семидневный период начиная с getFirstDayOfWeek(), который содержит не менее getMinimalDaysInFirstWeek() дней от этот год. Следовательно, это зависит от значения getMinimalDaysInFirstWeek(), getFirstDayOfWeek() и день неделя 1 января. Недели между неделя 1 года и 1-й недели следующий год пронумерованы последовательно от 2 до 52 или 53 (как необходимо).

Чтобы определить, является ли эта неделя последней неделей 2010 года или первой из 2011 года, Java использует getMinimalDaysInFirstWeek javadoc. Если этот метод возвращает 7, то первая неделя, в которой все дни недели относятся к тому же году, относится к первой неделе, если она вернется 1, то первая неделя с любыми днями следующего года будет первой неделей следующего года.

В этом случае первое января 2011 года состоится в субботу, поэтому считается первой неделей 2011 года, если вы хотите, чтобы неделя с одним днем ​​считалась уже первой неделей следующего года, если вы не делайте этого:

Calendar c = Calendar.getInstance();
c.setMinimalDaysInFirstWeek(7);//anything more than 1 will work in this year
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
System.out.println( c.get( Calendar.WEEK_OF_YEAR ) ); 

возвращает:

52

Ответ 3

IIRC, первая неделя с датой 1 января - неделя 1.
Вот почему неделя 1 возвращается за 31.12.2010.
Попробуйте 12/31/2011, и вы получите 52.

Изменить: неделя является специфичной для локали, иногда определяемой как воскресенье - суббота, иногда определяется как понедельник - воскресенье

Ответ 4

Это связано с тем, что начало недели зависит от локального.

В США неделя 1 начинается в воскресенье до 1 января. В 2010 году это 26 декабря. Почему 31 декабря по-прежнему остается 1-й неделей.

В Европе неделя 1 начинается в понедельник до 1 января. В 2010 году это 27 декабря. Почему же в Европе 31 декабря по-прежнему остается 1-й.

Ответ 5

TL;DR

java.time.LocalDate.parse( 
    "31/12/2010" , 
    DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )  
)      
.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )

52

Или добавьте библиотеку, а затем...

org.threeten.extra.YearWeek.from(     // Convert from a `LocalDate` object to a `YearWeek` object representing the entire week of that date’s week-based year.
    java.time.LocalDate.parse( "31/12/2010" , DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )  
).getWeek()                           // Extract an integer number of that week of week-based-year, either 1-52 or 1-53 depending on the year.

52

java.time

Как отмечалось другими, определение недели изменяется в Locale в старом классе java.util.Calendar.

Этот трудный класс и его партнер java.util.Date были вытеснены инфраструктурой java.time, встроенной в Java 8 и более поздние версии.

Класс IsoFields определяет неделю, используя ISO 8601: неделя всегда начинается в понедельник, а неделя № 1 проводится в первый четверг календарного года.

Получить текущий момент.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );

Спросите о стандартном недельном году.

int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );

Стандартное определение недели

Существует множество способов определить "неделю" и "первую неделю года".

Однако существует одно основное стандартное определение: ISO 8601. Этот стандарт определяет недели года, включая первую неделю года.

неделя с годом первый четверг

Стандартные недели начинаются с понедельника и заканчиваются в воскресенье.

Неделя № 1 недельного года имеет первый четверг календарного года.

Классы java.time поддерживают неделю ISO 8601 через класс IsoFields, содержащий три константы, которые реализуют TemporalField:

Вызовите LocalDate::get для доступа к TemporalField.

LocalDate ld = LocalDate.parse( "2010-12-31" ) ;
int weekOfWeekBasedYear = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int yearOfWeekBasedYear = ld.get( IsoFields.WEEK_BASED_YEAR ) ;

ld.toString(): 2010-12-31

weekOfWeekBasedYear: 52

yearOfWeekBasedYear: 2010

Формат строки ISO 8601

Стандарт ISO 8601 определяет текстовый формат, а также значение для значений недельного года: yyyy-Www. На определенную дату добавьте день недели с номером 1-7 в понедельник-воскресенье: yyyy-Www-d.

Создайте такую ​​строку.

String outputWeek = String.format( "%04d" , yearOfWeekBasedYear ) + "-W" + String.format( "%02d" , weekOfWeekBasedYear ) ;
String outputDate = outputWeek + "-" + ld.getDayOfWeek().getValue() ;

2010-W52-5

YearWeek

Эта работа намного проще, если вы добавите в свой проект библиотеку ThreeTen-Extra. Затем используйте класс YearWeek.

YearWeek yw = YearWeek.from( ld ) ;  // Determine ISO 8601 week of a `LocalDate`. 

Создать стандартную строку.

String output = yw.toString() ;

2010-W52

И проанализируйте.

YearWeek yearWeek = YearWeek.parse( "2010-W52" ) ;  

yearWeek.toString(): 2010-W52

Определите дату. Передайте объект java.time.DayOfWeek enum для дня недели с понедельника по воскресенье.

LocalDate localDate = yw.atDay( DayOfWeek.MONDAY ) ;

localDate.toString(): 2010-12-27

Я настоятельно рекомендую добавить эту библиотеку в ваш проект. Затем вы можете передавать интеллектуальные объекты, а не тупые ints. Это делает ваш код более самодокументированным, обеспечивает тип безопасности и обеспечивает допустимые значения.


О java.time

Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятный старый legacy классы даты-времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь в режим обслуживания, советуем перейти к классам java.time.

Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация JSR 310.

Использование JDBC-драйвера, совместимого с JDBC 4.2 или позже вы можете обменивать java.time-объекты непосредственно с вашей базой данных. Нет необходимости в строках или java.sql. * Classes.

Где получить классы java.time?

  • Java SE 8, Java SE 9, и позже
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональных возможностей java.time обратно переносится на Java 6 и 7 в ThreeTen-Backport.
  • Android
    • Более поздние версии реализаций пакетов Android классов java.time.
    • Для более раннего Android проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). См. Как использовать ThreeTenABP....

Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и больше.


Более подробно см. мой ответ по аналогичному вопросу:

... и см. мой ответ по аналогичному вопросу:

Ответ 6

Я считаю, что это лучший подход.

Calendar c = Calendar.getInstance();
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));

int thisWeek = c.get(Calendar.WEEK_OF_YEAR);
if (c.get(Calendar.MONTH) == Calendar.DECEMBER && thisWeek == 1)
    thisWeek = 53;

System.out.println(thisWeek);

Основное предположение здесь состоит в том, что в течение декабря неделя не может быть 1, следовательно, просто возвращается 53.

Пожалуйста, предложите, если я где-то ошибаюсь и почему это не реализовано в календаре Java.