tl; dr
Используйте современные классы java.time.LocalDate
и org.threeten.extra.LocalDateRange
, чтобы упростить вашу бизнес-логику до одной строки, спрашивающей, находится ли предыдущий элемент всписок не перед текущим элементом.
if (
!
prior
.getDateRange()
.isBefore(
current.getDateRange()
)
) { … handle rule violation … }
См. также правильный ответ Ole VV
Избегайте устаревших классов даты и времени
Никогда не используйте плохо разработанные унаследованные классы.Класс java.util.Date
, несмотря на свое название, представляет момент, дату с временем суток в UTC.Класс java.sql.Date
претендует на то, чтобы представлять только дату, но фактически включает в себя время суток и смещение.
java.time
Современный подход использует классы java.time .
LocalDate
Класс LocalDate
представляет значение только для даты без времени суток и без часовой пояс или смещение от UTC .
Вы можете установить месяц по номеру, с вменяемой цифрой 1-12 для января-декабря.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Или, лучше, использовать предварительно определенные объекты перечисления Month
, по одному на каждый месяц года.Совет: используйте эти Month
объекты по всей вашей кодовой базе, а не просто целое число, чтобы сделать ваш код более самодокументируемым, обеспечить допустимые значения и обеспечить безопасность типов .
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Вы можете напрямую анализировать строки в стандартном формате ISO 8601 : ГГГГ-ММ-ДД
LocalDate ld = LocalDate.parse( "2018-01-23" ) ;
Для анализа других форматов выполните поиск переполнения стека, чтобы узнать о DateTimeFormatter
.
LocalDateRange
В вашем классе Machine
вы, кажется, используете пару дат, даты начала и окончания.
Для этого есть класс.Добавьте библиотеку ThreeTen-Extra в свой проект, чтобы получить доступ к классу LocalDateRange
.Этот класс имеет несколько очень полезных методов для сравнения.Использование этого класса значительно упрощает ваш код и делает цель вашей бизнес-логики более очевидной.
Сохраните даты остановки / начала в виде объекта LocalDateRange
на вашем объекте Machine
.
private LocalDateRange dateRange;
Half-Open
Как правило, лучший подход к отслеживанию промежутка времени - это метод Half-Open.Начало включительно , а окончание эксклюзив .
Таким образом, неделя определяется как начинающаяся с одного дня, например, с понедельника, и продолжающаяся до, но не включая, того же дня следующей недели, например, следующего понедельника.Год начинается 1 января одного года и продолжается до 1 января следующего года.
Использование подхода Half-Open будет означать определение даты в вашем примере, как показано ниже.Обратите внимание на то, как изменение конечной даты на значения в годах в строках 1, 3 и 4 совпадает с вашим собственным определением видимых значений в месяцах для строк 2 и 5.
STRT_DT END_DT
---------- ----------
2014-01-01 2015-01-01
2013-01-01 2013-02-01 (Here the second record is having the date less than first record), this should fail
2016-01-01 2017-01-01
2017-01-01 2018-01-01
2018-01-01 2018-02-01
Пример класса: Machine
Вот пример кода для вашего класса Machine
.
package com.basilbourque.example;
import org.threeten.extra.LocalDateRange;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
public class Machine {
private String name;
private LocalDateRange dateRange;
// Constructor
public Machine ( String name , LocalDate start , LocalDate stop ) {
Objects.requireNonNull( name );
Objects.requireNonNull( start );
Objects.requireNonNull( stop );
// TODO: Add checks to validate data, such as dates being not too far into the past or future, and name being non-empty.
this.name = name;
this.dateRange = LocalDateRange.of( start , stop );
}
// -------| Accessors |--------------------------
public String getName ( ) {
return this.name;
}
public LocalDateRange getDateRange ( ) {
return this.dateRange;
}
// -------| Object |--------------------------
@Override
public String toString ( ) {
return "Machine{ " +
"name='" + name + '\'' +
" | dateRange=" + dateRange +
" }";
}
}
Давайте попробуем этот класс, написав метод main
.
public static void main ( String[] args ) {
List < Machine > machines =
List.of(
new Machine( "one" , LocalDate.parse( "2014-01-01" ) , LocalDate.parse( "2015-01-01" ) ) ,
new Machine( "two" , LocalDate.parse( "2013-01-01" ) , LocalDate.parse( "2013-02-01" ) ) , // Violates rule, where date-range should be *after* the prior one.
new Machine( "three" , LocalDate.parse( "2016-01-01" ) , LocalDate.parse( "2017-01-01" ) ) ,
new Machine( "four" , LocalDate.parse( "2017-01-01" ) , LocalDate.parse( "2018-01-01" ) ) ,
new Machine( "five" , LocalDate.parse( "2018-01-01" ) , LocalDate.parse( "2018-02-01" ) )
);
// Compare
for ( int i = 1 ; i < machines.size() ; i++ ) { // Using annoying zero-based index counting.
Machine prior = machines.get( i - 1 );
Machine current = machines.get( i );
if ( ! prior.getDateRange().isBefore( current.getDateRange() ) ) {
System.out.println( "BAD: Machine at index " + ( i - 1 ) + " is not before Machine at index " + i + " ➙ " + prior.getDateRange().toString() + " versus " + current.getDateRange().toString() );
}
}
}
При запуске.
ПЛОХО: машина с индексом 0 не раньше, чем машина с индексом 1 ➙ 2014-01-01 / 2015-01-01 против 2013-01-01 / 2013-02-01
JDBC 4.2
Начиная с JDBC 4.2 и более поздних версий мы можем напрямую обмениваться java.time объектами с базой данных.
LocalDate start = myResultSet.getObject( "start_date" , LocalDate.class ) ;
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация JSR 310 .
Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .