c# - Best way to compare Periods in using NodaTime (or alternative) -
i have requirement have relative min/max date validation able stored in database customize application per customer. decided nodatime.period
due it's capability specify years best choice. however, nodatime.period
not offer way compare against period.
example data provided validation:
- minimum age of 18 years old.
- maximum age o 100 years old.
- minimum sale duration of 1 month
- maximum sale duration of 3 months
- minimum advertising campaign 7 days
(note: current requirements year / month / day not combined in validations)
the validations are:
public period relativeminimum { get; set; } public period relativemaximum { get; set; }
given user entered date (and now):
var = new localdate(datetime.now.year, datetime.now.month, datetime.now.day); var uservalue = new localdate(date.year, date.month, date.day); var difference = period.between(uservalue, now);
i have comparison of:
if(relativeminimum != null && difference.islessthan(relativeminimum)))) { response.isvalid = false; response.errors.add(minimumerrormessage); }
which consuming extensions class:
public static class periodextensions { public static bool islessthan(this period p, period p2) { return (p.years < p2.years) || (p.years == p2.years && p.months < p2.months) || (p.years == p2.years && p.months == p2.months && p.days < p2.days); } public static bool isgreaterthan(this period p, period p2) { return (p.years > p2.years) || (p.years == p2.years && p.months > p2.months) || (p.years == p2.years && p.months == p2.months && p.days > p2.days); } }
while approach works, given test conditions have, have wonder why @jon-skeet didn't implement this, , have worry on missing , alternative should using instead?
the main reason periods aren't comparable can contain components of variable lengths.
two one-month periods aren't same number of days long. example, greater: 1 month or 30 days? if month january, that's longer 30 days. if month february, that's less 30 days.
the same applies years. 365 days long, 366.
of course, assumes you're using gregorian calendar. noda time supports other calendar systems, , there similar quirks in well.
regarding code:
if want
localdate
datetime
, uselocaldatetime.fromdatetime(dt).date
to current date, use
systemclock.instance.now.inzone(tz).date
- if intended same
datetime.now
, uses local time zone of computer code running,tz
callingdatetimezoneproviders.tzdb.getsystemdefault()
- if intended same
for comparison of type of problem have described, consider defining min , max days instead of min , max periods. wont have such variation of units. can difference in days this:
long days = period.between(d1, d2, periodunits.days).days;
i believe work use case:
public static bool isdifferencelessthan(localdate d1, localdate d2, period p) { if (p.hastimecomponent) throw new argumentexception("can compare dates.", "p"); if (p.years != 0) { if (p.months != 0 || p.weeks != 0 || p.days != 0) throw new argumentexception("can compare 1 component of period.", "p"); var years = period.between(d1, d2, periodunits.years).years; return years < p.years; } if (p.months != 0) { if (p.weeks != 0 || p.days != 0) throw new argumentexception("can compare 1 component of period.", "p"); var months = period.between(d1, d2, periodunits.months).months; return months < p.months; } if (p.weeks != 0) { if (p.days != 0) throw new argumentexception("can compare 1 component of period.", "p"); var weeks = period.between(d1, d2, periodunits.weeks).weeks; return weeks < p.weeks; } var days = period.between(d1, d2, periodunits.days).days; return days < p.days; }
Comments
Post a Comment