Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: How to...? Convert Date of Birth to Age

From: joel:neely:fedex at: 3-Jul-2002 8:21

Hi, Andrew, Andrew Martin wrote:
> Using Rebol (of course!), how would I convert a date of birth to > an age in years, months and days? >
First a couple of observations: - Date arithmetic is non-trivial; tricks with 365.25 (or 365.2425, to be more precise ;-) days are fragile in the presence of leap years. - Keeping up with lots of boilerplate (e.g. days per month) offers many opportunities for typos with subtle bugs. - As with sorting, one can do things simply (trading away speed) or highly tuned (trading away simplicity and clarity). All of that said, here's a "bubble-sort-style" solution. It's not a speed winner (and isn't suitable for large problems), but should be obvious and clear enough that you can type it from memory any time you need such a calculation. First, a version with comments explaining the strategy: 8<---------------------------------------------------------------- datedelta: func [ bdate [date!] edate [date!] /local result temp adjust ][ ; ; ensure proper order ; if bdate > edate [temp: bdate bdate: edate edate: temp] ; ; result = difference between bdate and temp (initially zero) ; temp: reduce [bdate/year bdate/month bdate/day] result: copy [0 0 0] ; ; function to modify a date component [y=1 m=2 d=3] ; in both result and temp by the same adjustment amount ; adjust: func [pos [integer!] delta [integer!]] [ poke result pos result/:pos + delta poke temp pos temp/:pos + delta ] ; ; tally difference in years, then months, then days ; foreach datepart [1 2 3] [ ; ; adjust up until overshoot ; while [edate > to-date temp] [ adjust datepart 1 ] ; ; correct any overshoot ; while [edate < to-date temp] [ adjust datepart -1 ] ] ; ; result = difference between bdate and temp ; temp = edate ; ergo result is final answer ; result ] 8<---------------------------------------------------------------- ... then a version without comments to help remember just the code: 8<---------------------------------------------------------------- datedelta: func [ bdate [date!] edate [date!] /local result temp adjust ][ if bdate > edate [temp: bdate bdate: edate edate: temp] temp: reduce [bdate/year bdate/month bdate/day] result: copy [0 0 0] adjust: func [pos [integer!] delta [integer!]] [ poke result pos result/:pos + delta poke temp pos temp/:pos + delta ] foreach datepart [1 2 3] [ while [edate > to-date temp] [adjust datepart 1] while [edate < to-date temp] [adjust datepart -1] ] result ] 8<---------------------------------------------------------------- HTH! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]