Reputation: 1177
I am trying to make sure the order of dates entered in an object are in a logical order. Here is my code:
function checkDates(pet) {
const dates = [
pet.birthDate,
pet.saleDate,
pet.acquisitionDate,
pet.deathDate
].filter( (date) => {
// filter out undefined items
return date;
});
// list of dates in their chronological order
const sortedDates = dates.slice(0).sort();
const inOrder = dates.every( (date, i) => {
// check to make sure entered date is the same as the chronological date
return date === sortedDates[i];
});
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
The problem is that saleDate and acquisitionDate do not need to be in that order (as defined in the dates array) - they just need to be more than birthDate and less than deathDate. The different dates are not required, for example, the pet object that gets passed through my look like this:
const pet = {
name: "Sam",
birthDate: "2017-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
}
Further clarification: If present, birthDate must always come first, and deathDate must always come last. Sale and acquisition must be between birth and death date (if they are present), otherwise, it doesn't matter if sale comes before acquisition or vice-versa.
Upvotes: 0
Views: 833
Reputation: 32145
You are saying that the order of both saleDate
and acquisitionDate
is not important they just need to be higher than birthDate
and lower than deathDate
, in that case you can simplify your function to do only these four checks:
function checkDates(pet) {
var birthDate = new Date(pet.birthDate);
var saleDate = new Date(pet.saleDate);
var acquisitionDate = new Date(pet.acquisitionDate);
var deathDate = pet.deathDate ? new Date(pet.deathDate) : Infinity;
var inOrder = (birthDate < saleDate) && (birthDate < acquisitionDate) && (saleDate < deathDate) && (acquisitionDate < deathDate);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
There's no need for using an array
and for the sorting and the looping operations, it's really useless.
Demo:
function checkDates(pet) {
var birthDate = new Date(pet.birthDate);
var saleDate = new Date(pet.saleDate);
var acquisitionDate = new Date(pet.acquisitionDate);
var deathDate = pet.deathDate ? new Date(pet.deathDate) : Infinity;
var inOrder = (birthDate < saleDate) && (birthDate < acquisitionDate) && (saleDate < deathDate) && (acquisitionDate < deathDate);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
console.log(checkDates({
name: "Sam",
birthDate: "2018-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
}));
Upvotes: 0
Reputation: 62851
Assuming the deathDate
is the only optional property here, but it appears it could be done in two checks:
birthDate
is less than the minimum of acquisitionDate
/saleDate
deathDate
, deathDate
is greater than the maximum of acquisitionDate
/saleDate
Something along these lines:
function checkDates(pet) {
const inOrder = (
pet.birthDate < Math.min.apply(null, [pet.acquisitionDate, pet.saleDate]) &&
pet.deathDate ? pet.deathDate > Math.max.apply(null, [pet.acquisitionDate, pet.saleDate]) : true
);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order')
}
return true;
}
const pet = {
birthDate: "2017-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
};
console.log(checkDates(pet));
If other properties are optional that would change things a bit but not too drastically.
Upvotes: 0
Reputation: 386680
You could just iterate the given array, without sorting, becaue all dates have to be in order.
function check({ birthDate, acquisitionDate, saleDate, deathDate }) {
return [birthDate, acquisitionDate, saleDate, deathDate]
.filter(Boolean)
.every((a, i, aa) => !i || aa[i - 1] <= a);
}
console.log(check({ name: "Sam", birthDate: "2017-01-01", acquisitionDate: "2017-02-01", saleDate: "2017-03-01" }));
console.log(check({ name: "Sam", birthDate: "2018-01-01", acquisitionDate: "2017-02-01", saleDate: "2017-03-01" }));
Upvotes: 1
Reputation: 42480
You are on the right path, but sorting isn't necessarily required:
function checkDates(pet) {
const dates = [
pet.birthDate,
pet.saleDate,
pet.acquisitionDate,
pet.deathDate
].filter(date => date);
const inOrder =
(pet.birthDate ? dates.every(date => date >= pet.birthDate) : true) &&
(pet.deathDate ? dates.every(date => date <= pet.deathDate) : true)
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
Upvotes: 1