Java: Получить номер недели с любой даты?

У меня есть небольшая программа, отображающая текущую неделю с сегодняшней даты, например:

GregorianCalendar gc = new GregorianCalendar(); int day = 0; gc.add(Calendar.DATE, day); 

И затем JLabel, который отображает номер недели:

 JLabel week = new JLabel("Week " + gc.get(Calendar.WEEK_OF_YEAR)); 

Поэтому прямо сейчас я хотел бы иметь JTextField, где вы можете ввести дату, а JLabel будет обновляться с номером недели этой даты. Я действительно не уверен, как это сделать, поскольку я совершенно новичок в Java. Нужно ли сохранять ввод в виде строки? Целое число? И в каком формате он должен быть (yyyyMMdd и т. Д.)? Если бы кто-нибудь мог мне помочь, я был бы признателен!

Нужно ли сохранять ввод в виде строки? Целое число?

При использовании JTextField вход, который вы получаете от пользователя, является String , так как дата может содержать символы типа . или - , в зависимости от выбранного формата даты. Разумеется, вы также можете использовать несколько более сложных методов ввода, где поле ввода уже проверяет формат даты и возвращает отдельные значения для дня, месяца и года, но с использованием JTextField конечно, легче начать.

И в каком формате он должен быть (yyyyMMdd и т. Д.)?

Это зависит от ваших требований. Вы можете использовать class SimpleDateFormat для анализа любого формата даты:

 String input = "20130507"; String format = "yyyyMMdd"; SimpleDateFormat df = new SimpleDateFormat(format); Date date = df.parse(input); Calendar cal = Calendar.getInstance(); cal.setTime(date); int week = cal.get(Calendar.WEEK_OF_YEAR); 

Но, скорее всего, вы хотите использовать формат даты, свойственный вашему языку:

 import java.text.DateFormat; DateFormat defaultFormat = DateFormat.getDateInstance(); Date date = defaultFormat.parse(input); 

Чтобы дать пользователю подсказку о том, какой формат использовать, вам нужно DateFormat в SimpleDateFormat чтобы получить строку шаблона:

 if (defaultFormat instanceof SimpleDateFormat) { SimpleDateFormat sdf = (SimpleDateFormat)defaultFormat; System.out.println("Use date format like: " + sdf.toPattern()); } 

Комментарий от @adenoyelle выше напоминает мне: Напишите модульные тесты для вашего синтаксического анализа даты .

Java 1.8 предоставляет вам несколько новых classов в пакете java.time :

 import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal.IsoFields; ZonedDateTime now = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); System.out.printf("Week %d%n", now.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)); 

Большинство устаревших календарей можно легко преобразовать в java.time.ZonedDateTime / java.time.Instant по методам взаимодействия, в вашем конкретном случае GregorianCalendar.toZonedDateTime() .

Вы можете сохранить дату в виде строки, и пользователь может ввести ее в любой формат, который вы указали. Вам просто нужно использовать объект DateFormat для интерпретации даты ввода. Например, см. Главный ответ на тему Преобразование String в объект Calendar в Java .

 Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011")); 

Чтобы прочитать дату с JTextField , вы можете заменить ее следующим:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // or any other date format cal.setTime(sdf.parse(dateTextField.getText())); 

Тогда вам просто нужно прочитать номер недели от cal же, как вы показали в вопросе. (Это упрощенный пример. Вам нужно будет обработать потенциальное ParseException , DateFormat методом parse DateFormat .)

ТЛ; др

 YearWeek.of( LocalDate.parse( "2017-01-23" ) ) .getWeek() // and .getYear() 

Стандартная неделя ISO 8601

Если вы хотите, чтобы стандартная неделя ISO 8601 , а не локализованное определение недели, используйте class YearWeek найденный в проекте ThreeTen-Extra, который добавляет функциональность classам java.time, встроенным в Java 8 и более поздние версии .

ISO-8601 определяет неделю, как всегда, начиная с понедельника. Первая неделя – это неделя, которая содержит первый четверг календарного года. Таким образом, недельный год, используемый в этом classе, не совпадает с календарным годом.

Во-первых, получите сегодняшнюю дату. Класс LocalDate представляет значение даты только без времени и без часового пояса.

Часовой пояс имеет решающее значение для определения даты. В любой данный момент дата изменяется по всему миру по зонам. Например, через несколько минут после полуночи в Париже Франция – новый день, еще «вчера» в Монреале Квебек .

Укажите правильное название часового пояса в формате continent/region , например, America/Montreal , Africa/Casablanca или Pacific/Auckland . Никогда не используйте аббревиатуру 3-4 букв, такую ​​как EST или IST поскольку они не являются настоящими часовыми поясами, не стандартизированы и даже не уникальны (!).

 ZoneId z = ZoneId.of( "America/Montreal" ); LocalDate today = LocalDate.now( z ); 

Или дайте пользователю указать дату, введя строку. Разбор строки ввода даты охватывает многие другие вопросы и ответы. Проще всего использовать пользовательский стандарт ISO 8601, YYYY-MM-DD, такой как 2017-01-23 .

 LocalDate ld = LocalDate.parse( "2017-01-23" ) ; 

Для других форматов задайте параметр DateTimeFormatter для синтаксического анализа. Поиск переполнения стека для многих примеров использования этого classа.

 DateTimeFormatter f = DateTimeFormatter.ofPattern( "d/M/uuuu" , Locale.US ) ; LocalDate ld = LocalDate.parse( "1/23/2017" , f ) ; 

Получите YearWeek .

 YearWeek yw = YearWeek.of( ld ) ; 

Чтобы создать строку, рассмотрите использование стандартного формата ISO 8601 на год-неделю , yyyy-Www, например 2017-W45 . Или вы можете извлечь каждый номер.

  • YearWeek::getWeek – получает поле недели недели по неделям.
  • YearWeek::getYear – получает поле недели за год.

Другие определения недели

Вышеприведенное обсуждение предполагает, что вы определяете определение недель и нумерацию по стандарту ISO 8601 . Если вместо этого вы хотите альтернативное определение недельной и недельной нумерации, см. Ответ Mobolaji D., используя определение локали.


О java.time

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

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

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

Где можно получить classы 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
    • Проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше) специально для Android.
    • См. Раздел Как использовать ThreeTenABP ….

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

WeekFields

Этот метод, который я создал, работает для меня в Java 8 и более поздних версиях, используя WeekFields , DateTimeFormatter , LocalDate и TemporalField .

Не забудьте правильно отформатировать дату на основе вашего прецедента!

 public int getWeekNum(String input) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/dd/yy"); // Define formatting pattern to match your input string. LocalDate date = LocalDate.parse(input, formatter); // Parse string into a `LocalDate` object. WeekFields wf = WeekFields.of(Locale.getDefault()) ; // Use week fields appropriate to your locale. People in different places define a week and week-number differently, such as starting on a Monday or a Sunday, and so on. TemporalField weekNum = wf.weekOfWeekBasedYear(); // Represent the idea of this locale's definition of week number as a `TemporalField`. int week = Integer.parseInt(String.format("%02d",date.get(weekNum))); // Using that locale's definition of week number, determine the week-number for this particular `LocalDate` value. return week; } 

Вы можете использовать это, но вам нужно проанализировать значение даты в соответствующем формате даты, используя SimpleDateFormatter из java API . Вы можете указать любой желаемый формат. После этого вы сможете манипулировать, чтобы получить неделю в году.

 public static int getWeek() { return Calendar.getInstance().get(Calendar.WEEK_OF_YEAR); } 

Работает отлично и возвращает неделю для текущего реального времени

этот работал для меня

 public void sortListItems(List list) { Collections.sort(list, new Comparator() { DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); @Override public int compare(PostModel o1, PostModel o2) { int ret = 0; try { ret = dateFormat.parse(o1.getDate()).compareTo(dateFormat.parse(o2.getDate())); return ret; } catch (ParseException e) { e.printStackTrace(); } return ret; } }); }