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, use localdatetime.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 calling datetimezoneproviders.tzdb.getsystemdefault()
  • 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

Popular posts from this blog

apache - PHP Soap issue while content length is larger -

asynchronous - Python asyncio task got bad yield -

javascript - Complete OpenIDConnect auth when requesting via Ajax -