Je suis face à une validation qui me fait fumer la tête assez souvent. J'ai un objet que j'appelle Downtime
pour l'instant et ça ressemble à ça :
public class Downtime {
/** The start date of the downtime. */
private ZonedDateTime downtimeFrom;
/** The end date of the downtime. */
private ZonedDateTime downtimeTo;
/**
* Gets the downtime from.
*
* @return the downtime from
*/
public ZonedDateTime getDowntimeFrom()
{
return downtimeFrom;
}
/**
* Gets the downtime to.
*
* @return the downtime to
*/
public ZonedDateTime getDowntimeTo()
{
return downtimeTo;
}
/**
* Sets the downtime from.
*
* @param downtimeFrom the new downtime from
*/
protected void setDowntimeFrom( ZonedDateTime downtimeFrom )
{
this.downtimeFrom = downtimeFrom;
}
/**
* Sets the downtime to.
*
* @param downtimeTo the new downtime to
*/
protected void setDowntimeTo( ZonedDateTime downtimeTo )
{
this.downtimeTo = downtimeTo;
}
}
Lorsque je crée un nouveau temps d'arrêt sur une implémentation CRUD, je valide déjà que l'heure de début est bien avant l'heure de fin et d'autres choses encore.
Maintenant, je dois ajouter la validation que lorsque je crée un nouveau temps d'arrêt, il n'interfère pas avec les temps d'arrêt déjà créés. En d'autres termes, la date de début du nouveau temps d'arrêt n'est pas déjà existante. et n'est pas sur un autre temps d'arrêt. ( entre le début et la fin d'un temps d'arrêt déjà créé ).
Ainsi, ma façon de procéder pour l'instant, puisque je ne suis pas doué pour les questions de date et d'heure en matière de localisation, serait la suivante :
private boolean isNewDowntimeValid(Downtime newDowntime, List<Downtime> createdDowntimes){
// let's just assume I already filtered out that the list only contains the same day. That's actually pretty easy.
List<ZonedDateTime> dateRange = new LinkedList<>();
ZonedDateTime newTime = newDowntime.getDowntimeFrom();
for(Downtime downtime : createdDowntimes){
ZonedDateTime downtimeStart = downtime.getDowntimeFrom();
ZonedDateTime downtimeEnd = downtime.getDowntimeTo();
for(ZonedDateTime start = downtimeStart; !start.isAfter(downtimeEnd); start = start.plusHours(1)){
dateRange.add(start);
}
}
if(dateRange.contains(newTime)){
return false;
}
return true;
}
Le code est écrit dans ma tête ici, il peut donc y avoir des erreurs de syntaxe mais je pense que vous pouvez avoir une idée de ce que je veux.
Et maintenant, ma question.
Ce code ci-dessus semble être une telle surcharge et je voudrais savoir comment je peux le valider plus rapidement et avec moins de code.
EDIT : Laissez-moi vous donner un exemple clair
J'ai une liste de temps d'arrêt comme celle-ci :
List<Downtime> createdDowntimes = [
{
start:2015-01-10T00:00Z,
end:2015-01-10T02:00Z
},
{
start:2015-01-10T04:00Z,
end:2015-01-10T06:00Z
},
{
start:2015-01-10T07:00Z,
end:2015-01-10T09:00Z
}
]
et ensuite j'ai le nouveau temps d'arrêt que je veux créer :
Downtime newDowntime =
{
start:2015-01-10T05:00Z,
end:2015-01-10T05:30Z
}
Dans cet exemple, le nouveau temps d'arrêt est pas valable puisqu'il se situe en fait pendant une période qui est déjà dans un autre temps d'arrêt déjà créé.
J'espère que cela rendra les choses plus claires.
EDIT 2 : Bien que le duplicata marqué comprenne la raison et offre une solution, je veux aussi donner des crédits à Hugo qui a fourni une bonne réponse en tenant compte de mes critères.
Voici une autre solution que j'ai préparée et qui offre un traitement beaucoup plus détaillé des exceptions et des informations.
/*
* Collision 1 = the new downtime starts before the created ones but ends in their span
* Collision 2 = the new downtime starts after created ones and also ends after their span
* Collision 3 = the new downtime starts after created ones and ends in their span
*/
List<Downtime> collision1 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isAfter( newTimeStart ) )
.filter( e -> e.getDowntimeTo().isAfter( newTimeEnd ) ).collect( Collectors.toList() );
List<Downtime> collision2 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isBefore( newTimeStart ) )
.filter( e -> e.getDowntimeTo().isBefore( newTimeEnd ) ).collect( Collectors.toList() );
List<Downtime> collision3 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isBefore( newTimeStart ) )
.filter( e -> e.getDowntimeTo().isAfter( newTimeEnd ) ).collect( Collectors.toList() );
Gardez à l'esprit que ma "solution" est une solution parmi d'autres et qu'elle est également assez intensive en termes de performances puisque les flux sont des opérations lourdes. Donc, si vous n'avez pas besoin de savoir exactement combien sont entrés en collision et pourquoi ils sont entrés en collision, considérez la réponse d'Hugo.