On Sat, 30 Mar 2002, Paul DuBois wrote:
> At 17:15 -0500 3/30/02, Michael Stassen wrote: > >On Sat, 30 Mar 2002, Paul DuBois wrote: > > > >> At 21:25 +0100 3/30/02, Roger Baklund wrote: > >> >* Son Nguyen > >> >> ==> I tried this query, but... it's not working out: > >> >> SELECT YEAR(now()-birthday) from users where loginName="test"; > >> > > >> >You are very close: > >> > > >> >SELECT YEAR(now())-YEAR(birthday) as age from users where loginName="test"; > >> > >> That won't adjust for the relative difference within the calendar > >> year of the two dates. This works better: > >> > >> mysql> SELECT > >> -> YEAR(CURDATE()) - YEAR(birthday) > >> -> - IF(RIGHT(CURDATE(),5) < RIGHT(birthday,5),1,0) > >> -> AS 'age in years' > >> -> FROM users WHERRE loginName="test"; > > > >Or > > > > SELECT > > YEAR(FROM_DAYS(TO_DAYS(CURDATE()) - TO_DAYS(birthday))) > > AS 'age in years' > > FROM users WHERE loginName='test'; > > > >Michael > > mysql> SET @birth = CURDATE() - INTERVAL 1 YEAR; > mysql> SELECT > -> CURDATE(), @birth, > -> YEAR(FROM_DAYS(TO_DAYS(CURDATE()) - TO_DAYS(@birth))) > -> AS 'age in years'; > +------------+------------+--------------+ > | CURDATE() | @birth | age in years | > +------------+------------+--------------+ > | 2002-03-30 | 2001-03-30 | 0 | > +------------+------------+--------------+ Yes, it seems from_days(N) expects N to be days since 0000-00-00, rather than 0000-01-01, which is reasonable. Thus, 0001-01-01 is from_days(366), so I was off by one day. I should have said YEAR(FROM_DAYS(1 + TO_DAYS(CURDATE()) - TO_DAYS(birthday))). On the other hand, now that I think about it, there may be certain combinations of CURDATE and birthday which will still be off by one (for a day) due to leap year. So your way is better (and it's in the manual! <http://www.mysql.com/doc/D/a/Date_calculations.html>). > mysql> SELECT > -> CURDATE(), @birth, > -> YEAR(CURDATE()) - YEAR(@birth) > -> - IF(RIGHT(CURDATE(),5) < RIGHT(@birth,5),1,0) > -> AS 'age in years'; > +------------+------------+--------------+ > | CURDATE() | @birth | age in years | > +------------+------------+--------------+ > | 2002-03-30 | 2001-03-30 | 1 | > +------------+------------+--------------+ While looking into this, however, I ran across some strange behavior for from_days and to_days which I didn't expect. ==== from_days(N) appears to work only for N>=366. mysql> select from_days(1), from_days(365), from_days(366); +--------------+----------------+----------------+ | from_days(1) | from_days(365) | from_days(366) | +--------------+----------------+----------------+ | 0000-00-00 | 0000-00-00 | 0001-01-01 | +--------------+----------------+----------------+ I would have expected 0000-01-01, 0000-12-31, 0001-01-01, respectively. Perhaps there's a good reason for this. If not, I'd call it a bug. ==== to_days(D) appears to work only for D >= 0200-01-01 mysql> select D, to_days(D), from_days(to_days(D)) from day_test; +------------+------------+-----------------------+ | D | to_days(D) | from_days(to_days(D)) | +------------+------------+-----------------------+ | 0000-00-00 | NULL | NULL | | 0000-01-01 | 730485 | 2000-01-01 | | 0000-12-31 | 730850 | 2000-12-31 | | 0001-01-01 | 730851 | 2001-01-01 | | 0069-01-01 | 755688 | 2069-01-01 | | 0070-01-01 | 719528 | 1970-01-01 | | 0099-01-01 | 730120 | 1999-01-01 | | 0100-01-01 | 730485 | 2000-01-01 | | 0169-01-01 | 755688 | 2069-01-01 | | 0170-01-01 | 756053 | 2070-01-01 | | 0199-01-01 | 766645 | 2099-01-01 | | 0200-01-01 | 73049 | 0200-01-01 | +------------+------------+-----------------------+ I imagine this is Y2K related, as it seems to be treating my 4-digit years as if they were 2-digit for 0000 to 0099, or 3-digit for 0100 to 0199. But I really did specify 4 digits! Perhaps there's a good reason to do this, but again, if there isn't, I'd call it a bug. Of course, I don't expect MySQL to be too worried about these. They did tell me, after all, that to_days and from_days aren't intended for dates before 1582, due to the calendar change, and the date type itself isn't supported before year 1000. But, I think there's a difference between saying the output will be inaccurate for early dates because the calendar changed and saying your output will be wrong even if you pretend the current calendar was always in effect. Regardless of calendar changes, I would have expected FROM_DAYS(TO_DAYS(D)) = D and TO_DAYS(FROM_DAYS(N)) = N. I would have been wrong for D < 0200-01-01 and N < 73049. At the very least, it would be nice if the ranges for which these functions are mathematically valid were included in the docs. Now that I've made a mountain out of a molehill, I think the real problem is that while we have methods to add/subtract an interval to/from a date to get a new date, we don't have a method to subtract two dates (or datetimes) to get an interval (in days or months or years or...). It seems to come up a lot, but I don't see it on the TODO lists. Michael --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php