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

Например:

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

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

:)

Ответы [ 6 ]

52 голосов
/ 05 января 2011

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

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

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

И Java 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

ДОБАВЛЕНО Для США (и я могу думать, что для Мексики то же самое) 1. неделя года - это неделя, к которой относится 1. январь. - Таким образом, если 1. Январь - суббота, тогда пятница (31 декабря) принадлежит той же неделе, и в этом случае этот день относится к 1. Неделе года 2011.

9 голосов
/ 05 января 2011

Значения, рассчитанные для 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 голосов
/ 19 января 2016

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 и более поздние версии.

*Класс 1027 * определяет неделю с использованием стандарта 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 для дня недели с понедельника по воскресенье.

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

localDate.toString (): 2010-12-27

IНастоятельно рекомендуем добавить эту библиотеку в ваш проект.Тогда вы можете передавать умные объекты, а не тупые целые.Это делает ваш код более самодокументируемым, обеспечивает безопасность типов и обеспечивает допустимые значения.


About java.time

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

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

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

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

Где получить классы 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 и more .


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

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

3 голосов
/ 05 января 2011

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

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

2 голосов
/ 05 января 2011

Это потому, что начало недели зависит от страны.

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

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

0 голосов
/ 25 мая 2018

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

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.

...