I want to validate that ends_on
is always later or the same date as starts_on
. But my custom validation doesn't work. What is the correct way to write this validation?
defmodule Example.Calendar.VacationPeriod do
use Ecto.Schema
import Ecto.Changeset
alias Example.Calendar.VacationPeriod
schema "vacation_periods" do
field :ends_on, :date
field :name, :string
field :starts_on, :date
timestamps()
end
@doc false
def changeset(%VacationPeriod{} = vacation_period, attrs) do
vacation_period
|> cast(attrs, [:name, :starts_on, :ends_on])
|> validate_required([:name, :starts_on, :ends_on])
|> validate_dates_make_sense
end
defp validate_dates_make_sense(changeset) do
starts_on = get_field(changeset, :starts_on)
ends_on = get_field(changeset, :ends_on)
if starts_on > ends_on do
add_error(changeset, :starts_on, "cannot be later than 'ends_on'")
else
changeset
end
end
end
To check if a date is before another date, compare the Date objects, e.g. date1 < date2 . If the comparison returns true , then the first date is before the second, otherwise the first date is equal to or comes after the second. Copied!
val(); var endDate = $('#end_date'). val(); if (endDate < startDate){ alert('End date should be greater than Start date. '); $('#end_date'). val(''); } });
You cannot compare Date
structs using the comparison operators. The Date
module has a compare/2
function you can use:
if Date.compare(starts_on, ends_on) == :gt do
add_error(changeset, :starts_on, "cannot be later than 'ends_on'")
else
changeset
end
or with case
:
case Date.compare(starts_on, ends_on) do
:gt -> add_error(changeset, :starts_on, "cannot be later than 'ends_on'")
_ -> changeset
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With