[REBOL] Re: How to...? Convert Date of Birth to Age
From: lmecir:mbox:vol:cz at: 24-Oct-2002 20:41
Hi Joel,
----- Original Message -----
From: "Joel Neely"
> substitue FWD-TOP for DATEDELTA in the snippet below.
> > >> age 29/2/2004 28/2/2005
> > == [0 11 28]
> > >> datedelta 29/2/2004 28/2/2005
> > == [0 11 30]
> >
> > >> age 29/2/2004 1/3/2005
> > == [1 0 1]
> > >> datedelta 29/2/2004 1/3/2005
> > == [1 0 0]
> >
> > Which results are correct?
> >
> The issue (which I didn't think through with sufficient precision
> in the earlier discussion) is that we tend to expect all of these
> statements to be equivalent:
>
> last - first = difference
> last - difference = first
> first + difference = last
>
> when, in fact, they are not equivalent for date "arithmetic".
Exactly! That is why we must answer the question (Which results are
correct?) for our intented application.
> To
> illustrate, consider the number of months/days between the dates
> 27-Jan-2004 and 03-Mar-2004. Working forward, we observe that:
>
> 27-Jan-2002 -> 27-Feb-2002 = 1 months 0 days
> 27-Feb-2002 -> 03-Mar-2002 = 0 months 4 days
> --------------------------------------------
> 27-Jan-2002 -> 03-Mar-2002 = 1 months 4 days
>
> but working backward, we find that:
>
> 03-Mar-2002 <- 03-Feb-2002 = 1 months 0 days
> 03-Feb-2002 <- 27-Jan-2002 = 0 months 7 days
> --------------------------------------------
> 03-Mar-2002 <- 27-Jan-2002 = 1 months 7 days
>
> and this difference resembles the difference between:
>
> >> fwd-top 27-jan-2002 03-mar-2002 == [0 1 4]
> >> age 27-jan-2002 03-mar-2002 == [0 1 7]
> I've concluded that there are two reasons for favoring the
> behavior of FWD-TOP over AGE as follows:
>
> Minor reason: We think of time as moving forward, rather than
> backward, so if we must choose, let's use the
> direction that matches our experience.
Good point! But what if we have got the origin? (E.g. the date of the
birth). Then we should use the counting direction pointing towards the other
date regardless of the fact whether we are counting forward. (see the
monotonicity discussion below)
> Major reason: 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. This
> behavior is exhibited by FWD-TOP,
it isn't ;-)
a: 8/2/2004
b: 1/2/2004
fwd-top a b ; == [0 0 7]
; while
b: 9/2/2004
fwd-top a b ; == [0 0 1]
Here is another candidate function:
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]
]
foreach [birth date] [
29/2/2004 28/2/2005
29/2/2004 1/3/2005
8/2/2004 1/2/2004
8/2/2004 29-Mar-2004
8/2/2004 30-Mar-2004
8/2/2004 31-Mar-2004
8/2/2004 1-Apr-2004
8/2/2004 2-Apr-2004
8/2/2004 3-Apr-2004
29/2/2004 29/2/2008
] [
foreach fnc [fwd-top age new-age] [print [fnc birth date mold do get fnc
birth date]]
]