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: lmecir:mbox:vol:cz at: 24-Oct-2002 11:08

Hi, I think, that it may be useful to summarize the results. The first candidate: fwd-top: func [ lo [date!] hi [date!] /local y m d i j k ][ if hi < lo [k: lo lo: hi hi: k] y: lo/year m: lo/month d: lo/day i: j: k: 0 while [hi > to-date reduce [y m d]] [y: y + 1 i: i + 1] while [hi < to-date reduce [y m d]] [y: y - 1 i: i - 1] while [hi > to-date reduce [y m d]] [m: m + 1 j: j + 1] while [hi < to-date reduce [y m d]] [m: m - 1 j: j - 1] while [hi > to-date reduce [y m d]] [d: d + 1 k: k + 1] while [hi < to-date reduce [y m d]] [d: d - 1 k: k - 1] reduce [i j k] ] Advantages: 1) Rebol compatibility
> FWD-TOP returns triplets that are consistent with the > way REBOL converts blocks to dates.
2) Forward counting The difference is computed counting forward in time. 3) Half-monotonicity For two dates A and B, where A < B, we would expect the difference between A and B (in whatever representation) to increase as B increases. Disadvantages: 1) "Unusual" results
>> fwd-top 31/1/2002 5/3/2002
== [0 1 2]
>> fwd-top 29/2/2004 1/3/2005
== [1 0 0] 2) Uni-directional counting
>> fwd-top 3/1/2002 2/1/2002
== [0 0 1]
>> fwd-top 3/1/2002 4/1/2002
== [0 0 1] The second candidate: new-age: function [birth [date!] date [date!]] [ years months days new ] [ days: date/day - birth/day either date < birth [ if positive? days [ new: to date! reduce [birth/day date/month + 1 date/year] if new/day <> birth/day [ new: to date! reduce [0 date/month + 2 date/year] ] days: date - new date: new ] months: date/month - birth/month years: date/year - birth/year if positive? months [ months: months - 12 years: years + 1 ] ] [ if negative? days [ new: to date! reduce [birth/day date/month - 1 date/year] if new/day <> birth/day [ new: to date! reduce [0 date/month date/year] ] days: date - new date: new ] months: date/month - birth/month years: date/year - birth/year if negative? months [ months: months + 12 years: years - 1 ] ] reduce [years months days] ] Advantages: 1) "Usual" results
>> new-age 31/1/2002 5/3/2002
== [0 1 5]
>> new-age 29/2/2004 1/3/2005
== [1 0 1] 2) Birth-related counting direction The counting starts from the BIRTH and goes towards the DATE
>> new-age 3/1/2002 2/1/2002
== [0 0 -1]
>> new-age 3/1/2002 4/1/2002
== [0 0 1] 3) Weak monotonicity For dates A, B, C, D, for which C <= A and D >= B holds, that (new-age a b) <= (new-age c d) Disadvantages: 1) Non-strict monotonicity We can obtain equal results for (new-age a b) and (new-age c b) even if (a <> c). This means, that given a date and a new-age we aren't able to uniquely determine the birth date.
>> new-age 30/1/2004 5/3/2004
== [0 1 5]
>> new-age 31/1/2004 5/3/2004
== [0 1 5] The third candidate: strict-age: function [birth [date!] date [date!]] [ years months days new direction ] [ days: date/day - birth/day direction: either date < birth [-1] [1] if negative? days * direction [ new: to date! reduce [birth/day date/month - direction date/year] if new/day <> birth/day [ new: to date! reduce [birth/day date/month - direction - direction date/year] ] if not positive? date - new * direction [return reduce [0 0 date - birth]] days: date - new date: new ] months: date/month - birth/month years: date/year - birth/year if negative? months * direction [ months: months + (12 * direction) years: years - direction ] reduce [years months days] ] Advantages: 1) Birth-related counting direction The counting starts from the BIRTH and goes towards the DATE
>> strict-age 3/1/2002 2/1/2002
== [0 0 -1]
>> strict-age 3/1/2002 4/1/2002
== [0 0 1] 2) Monotonicity / uniqueness For dates A, B, C holds, that if C < A, then (STRICT-AGE A B) < (STRICT-AGE C B). If C > B, then (STRICT-AGE A B) < (STRICT-AGE A C). For a given STRICT-AGE and a given DATE we can find the corresponding BIRTH date. Disadvantages: 1) "Unusual" results
>> strict-age 31/1/2002 5/3/2002
== [0 0 33]
>> strict-age 29/2/2004 1/3/2005
== [0 11 31] Cheers -L