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 и т. д.)? Если любой мог бы мне помочь, я был бы признателен!

8 ответов


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

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

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

это зависит от ваших требований. Вы можете использовать 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 предоставляет вам некоторые новые классы в пакет 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 объект для интерпретации даты, которую они вводят. Например, см. лучшие ответы on преобразовать строку в объект календаря в 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 in так же, как вы показали в вопросе. (Это упрощенный пример. Вам нужно будет справиться с потенциалом ParseException выдано DateFormat parse метод.)


tl; dr

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

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

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

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

во-первых, получить сегодняшнюю дату. The 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, гггг-ММ-ДД, такой как 2017-01-23.

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

для других форматов, указать DateTimeFormatter для разбора. Search Stack Overflow для многих примеров использования этого класса.

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 для Года-недели, гггг-Www такие как 2017-W45. Или вы можете извлечь каждый номер.

  • YearWeek::getWeek – получает поле недели недели на основе года.
  • YearWeek::getYear – получает поле недели на основе года.

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

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


о java.время

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

на Joda Времени проект, в настоящее время в режим обслуживания, советует миграцию в java.время классы.

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

где получить java.время занятий?

  • Java SE 8, Java SE 9, и позже
    • встроенный.
    • часть стандартного API Java со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
  • Android

в ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как 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 of java API. Вы можете указать любой формат. После этого вы можете сделать вам манипуляции, чтобы получить неделю в году.


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

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


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

public void sortListItems(List<PostModel> list) {
    Collections.sort(list, new Comparator<PostModel>() {
        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;
        }
    });
}