2017-01-05 2 views
2

Я хочу сравнить строковые представления недель, например. неделя «01/17» до «02/17» и после «52/16».Анализ строк недели для сравнения с использованием Java 8

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

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ww/YY", Locale.GERMANY); 
LocalDate date1 = formatter.parse(str1, LocalDate::from); 

Мне нужно изменить анализатор делать? Или проанализируйте какой-либо другой формат? Unfortunatley нет объектов, таких как YearMonth в течение нескольких недель ...

+1

Что именно вы называете здесь «неделя»? –

ответ

5

Одно решение будет всегда по умолчанию в в тот же день, скажем, в понедельник. Вы можете создать собственную форматировщик для этого:

DateTimeFormatter fmt = new DateTimeFormatterBuilder() 
      .appendPattern("ww/YY") 
      .parseDefaulting(ChronoField.DAY_OF_WEEK, 1) 
      .toFormatter(Locale.GERMANY); 

Теперь вы можете построить LocalDate сек, представляющие понедельник данной недели:

LocalDate d1 = LocalDate.parse("01/17", fmt); 
LocalDate d2 = LocalDate.parse("52/16", fmt); 
System.out.println(d1.isAfter(d2)); 

, который печатает true потому 01/17 после 52/16.

+0

Отлично, parseDefaulting() был недостающим куском :) – Tom

2

Мне не удалось найти способ для работы с классом DateTimeFormatter, но я хотел бы предложить другой подход.

Threeten Extra library содержит ряд классов, которые считались слишком специфичными для включения в библиотеку java.time. Один из них - класс YearWeek, который вы упомянули.

Ваша проблема может быть решена путем анализа уик-номер и год вручную из ввода-строки, а затем вызова YearWeek создателя-метод, как это:

YearWeek yw = YearWeek.of(year, monthOfYear); 
+1

Спасибо, хорошо знать эту библиотеку. То, что я нашел очень странным, заключается в том, что форматирование, созданное с помощью строки шаблона, не может предоставить детали, необходимые для создания YearWeek, используя from(). Тем не менее, работает один из построителей DateTimeFormatterBuilder. Это неудачно, хотя, поскольку я хочу предоставить шаблон из config. – Tom

+2

@Tom Или альтернативно - со многими дополнительными функциями - есть также мой lib Time4J, который предлагает класс [CalendarWeek] (http://time4j.net/javadoc-en/net/time4j/range/CalendarWeek.html), включая хороший i18n -поддержка и недельная арифметика (с помощью методов, например 'plusWeeks()'). Оба они отсутствуют в Threeten-Extra. Но ТОЛЬКО для сравнения календарных недель добавление дополнительной зависимости не представляется необходимым. –

2

Т.Л., д-р

YearWeek.parse("2017-W01") 

ISO 8601

Или разобрать какой-то другой формат?

Да, используйте другой формат.

Используйте стандартные форматы ISO 8601 при сериализации значений даты и времени для текста. Стандарт включает support for week dates.

В течение года-недели это будет четыре года, дефис, W и две цифры за неделю в году.

2017-W01

Получить ясно вашего определения «недели». Определение ISO 8601 является то, что:

  • Неделя # 1 содержит первый четверг года, и
  • Запускается понедельник-воскресенье.

Таким образом, продолжительность лет 52 или 53 недели. И обратите внимание, что в соответствии с этим определением первые несколько дней года могут быть в предыдущем году, когда нумерация по неделям. Аналогичным образом, последние несколько дней года могут быть в следующем году, когда нумерация по неделям.

Если вы хотите указать конкретный день в течение этой недели, добавьте дефис и цифру с номером 1-7 в понедельник-воскресенье.

Совет. Чтобы увидеть стандартные номера ISO 8601 по умолчанию на вашем компьютере, вам может потребоваться настроить настройку ОС. Например, на macOS установите Системные настройки> Язык & Регион> Календарь> ISO 8601, чтобы приложения, такие как Calendar.app, отображали номера недель с этим стандартным определением.

2017-W01-7

Кстати, пара подобных представлений:

  • Порядковый дата означает, год и день-год-номер работает от 1-366 - год, дефис и трехзначное число: 2017-123
  • Месяц-день без года - это два дефиса, число месяцев, дефис и число дней в месяце: --01-07

Обратите внимание, что использование Locale, как видно из вопроса, здесь не имеет отношения к стандартным форматам ISO 8601.

YearWeek

Unfortunatley нет ни одного объекта, как годМесяц в течение нескольких недель ...

Ааа, но это такого класса.

Для класса, представляющего идею недельного года, см. correct Answer by Henrik. В этом ответе показан класс библиотеки ThreeTen-ExtraYearWeek.

Класс YearWeek может непосредственно анализировать и генерировать строки в стандартном формате.

YearWeek yw = YearWeek.parse("2017-W01"); 

Вы можете сравнить YearWeek объектов с помощью методов: compareTo, equals, isBefore, isAfter.

yw.isBefore(thatYw) 

ThreeTen-Extra проект предлагает другие классы, такие как YearQuarter, которые могут оказаться полезными.