- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
I would say 1853, since 1900 has no leap day.
Admin
One could alos have written it in plain sql (using oracle) ... (thanks to ammoq).
<font>
SELECT</font> CustomerId, EmailAddress<font>
FROM</font> Customers
-- get's all Customers, even those on the 29th, if birthday and current year are a leap year
<font>WHERE</font> to_Char(Birthdate, 'MMDD') = to_char(sysdate + 1, 'MMDD')
-- get's all the Customers with birthday on leap year and current year non leap year
OR Decode(to_Char(Birthdate, 'MMDD'), '0229', '0301') = to_char(sysdate + 1, 'MMDD');
l.
Admin
In Oracle, i might do this:
<FONT size=+0>SELECT</FONT> CustomerId, EmailAddress
<FONT size=+0>FROM</FONT> Customers
<FONT size=+0>WHERE TO_CHAR( Birthdate, 'ddd' ) = TO_CHAR( Sysdate, 'ddd' )</FONT>
Feb 29th would match to March 1 on non leap years.
Admin
Re: Pirates of Penzance - more discussion (by experts in the field) is available at
http://math.boisestate.edu/gas/pirates/discussion/2.html
Another "gotcha" is that the Major-General's song (I am the very model of a modern major-general) refers to "that infernal nonsense Pinafore" which puts a lower bound on the date...
Admin
Regardless of the leap-year problem, won't this code send out the coupon one day and one month before the birthday? And wouldn't this code fail if the customer's birthday is in January?
Anyway, this approach is also the one I thought of. I guess I would solve the problem like this:
Admin
Err, let's try that again:
I'm pretty sure that "CONCAT(YEAR(CURDATE(), "-", MONTH(Birthday), "-", DAY(Birthday))" will produce this-years-birthday.Admin
No. Watch those parentheses.
Admin
My first thought reading that as well.
-dave-
Admin
I'm afraid if you try to convert that date in a a non leap year you'll get an error - hopefully.
l.
Admin
<FONT face=Verdana size=2>Fearing the worst... That someday soon, I might actually have to implement this exact same project in MySQL, I put together this query. The query focuses on the day and lets the DB handle the leap year calculation.</FONT>
<FONT face=Verdana size=2>Turns out the hardest part about finding the 29th on the 27th ( of a non-leap year ), was NOT finding it again on the 28th ( of a leap year ). </FONT>
<FONT face="Courier New" color=#0000ff size=2>SELECT
CustomerId,
EmailAddress,
Birthdate
FROM
Customers
WHERE
<FONT color=#808080>/* Birth-day is tomorrow. */
/* Birth-month is tomorrow. */
/* this naturally finds feb 29 when curr-year is leap year */
</FONT>(
DAY( Birthdate) = DAY( DATE_ADD(CURDATE(), INTERVAL 1 DAY))
AND MONTH(Birthdate) = MONTH(DATE_ADD(CURDATE(), INTERVAL 1 DAY))
) </FONT>
<FONT face="Courier New" color=#0000ff size=2><FONT color=#808080>/* when curr-year is non leap year */
/* find rouge day at end of month - ie feb 29 */
</FONT>OR
(
DAY(DATE_ADD(Birthdate, INTERVAL 1 DAY)) = 1 <FONT color=#808080>/* day after birthday is the 1st */</FONT>
AND DAY(DATE_ADD(CURDATE(), INTERVAL 2 DAY)) = 1 <FONT color=#808080>/* day after tomorrow is the 1st */</FONT>
AND MONTH(Birthdate) = MONTH(CURDATE()) <FONT color=#808080>/* curr-month is birth-month */
</FONT>)</FONT>
<FONT face=Verdana size=2>Tested briefly on MySQL 5.0.16-nt replacing CURDATE() with hard-coded dates using DATE('2000-02-27'), etc.</FONT>
Admin
(squinting intently...) Oh yeah, you're right!
Admin
Interesting, but for one, you are missing the condition that it has to look for birthdays on the next day, not the current date. And there is of course the question if you compare birthdays from leap years (and I'm not talking about Feb 29th) with current dates from non leap years. Customers then always get notified a day after their birthdays (for all dates after Feb 29th).
l.
Admin
Whyever not just:
WHERE DATEDIFF('y',GetDate(),Birthday) != DATEDIFF('y',GetDate()+1,Birthday)
Wouldn't that do the job, and get rid of all this Leap-Year-Discussion nonsense?
Admin
You ask others about the implication of your solution? Why not test it yourself?
l.
Admin
I don't have access to an SQL server.
Admin
And? Use plain old computational logic, or don't you have access to that either?
l.
Admin
Me either...nor experience with it. But, I admire someone who is not afraid to stick their neck out and ask why not.
That said, a simple google on DATEDIFF took me right to the MSDN library. So...after a few minutes research, the expression:
DATEDIFF('y',GetDate(),Birthday) != DATEDIFF('y',GetDate()+1,Birthday)
simplified to this:
"days tween today and birthday" != "days tween tomorrow and birthday"
Seems likely that would be the case more often than not.
Although...I gotta admit( not knowing much about MSSQL), I may have mis-understood the intent your expression. It was unclear to me what GETDATE()+1 resolves to... is it a day from now, a minute from now, a year from now?
Admin
Even without checking the MSDN documentation, it seems pretty clear to me that the 'y' in the DATEDIFF call is specifying years, not days. And as to GETDATE()+1, clearly the addition of 1 to a date should add days. So the expression:
DATEDIFF('y',GetDate(),Birthday) != DATEDIFF('y',GetDate()+1,Birthday)
should amount to:
"years (not days) tween today and birthday" != "years (not days) tween tomorrow and birthday"
which, unless I'm seriously missing something myself, should indeed work for all cases. But of course I'd have to test that before depending on it!
Admin
In a non-leap year, a 29th February baby will celebrate their birthday depending on how they round.
Round Down: 28th February
Round Up: 1st March
etc....
Haven't we done this before?
Admin
not really, especially if you don't care about it working right in the year 2400 ;)
Admin
Alas,
does not work.
It will send everyone their coupons on December 31.
DateDiff counts the number of year-boundaries BETWEEN two dates.
So
DateDiff('y', 'Jan 1 2006', 'Dec 31 2007') = 1
DateDiff('y', 'Dec 31 2006', 'Jan 1 2007') = 1
Admin
I have, in my life, known two people born on a leap-year. They are usually full of excitement in saying odd things like they are only 1/4th the age they appear, and so on, much as technical people are unduly fascinated with the minutia of their machines that surround them. Having also realized that this second round of code works for as often as these people like to celebrate their birthdays, I say they get what they deserve. If your birthday only comes once every four years, so be it. All the more reason to go out and get your due marketing freebies.
Admin
In Oracle, I would do:
<FONT face="Courier New">SELECT CustomerId, EmailAddress
FROM Customers
WHERE MOD(MONTHS_BETWEEN(sysdate + 1, birthdate), 12) = 0</FONT>
Because:
<FONT face="Courier New">SQL> SELECT MONTHS_BETWEEN(TO_DATE('28-feb-2006', 'dd-mon-yyyy'),
2 TO_DATE('29-feb-2000', 'dd-mon-yyyy')) bday
3 FROM dual;
BDAY
----------
72
SQL> SELECT MONTHS_BETWEEN(TO_DATE('01-Mar-2006', 'dd-mon-yyyy'),
2 TO_DATE('29-feb-2000', 'dd-mon-yyyy')) bday
3 FROM dual;</FONT>
<FONT face="Courier New"> BDAY
----------
72.0967742</FONT>
Admin
Got it.
SELECT FROM Table WHERE ROUND(DATEDIFF(d, '02/29/1980', GETDATE()) % 365.25, 0, 1) = 364
As:
ROUND(DATEDIFF(d, '02/29/1980', '02/27/2005') % 365.25, 0, 1) = 364
ROUND(DATEDIFF(d, '02/29/1980', '02/28/2005') % 365.25, 0, 1) = 365
ROUND(DATEDIFF(d, '02/29/1980', '02/29/2004') % 365.25, 0, 1) = 0
ROUND(DATEDIFF(d, '02/29/1980', '03/01/2005') % 365.25, 0, 1) = 0
(And just to be safe:
ROUND(DATEDIFF(d, '02/27/1980', '02/26/2005') % 365.25, 0, 1) = 364
ROUND(DATEDIFF(d, '02/27/1981', '02/26/2005') % 365.25, 0, 1) = 364
ROUND(DATEDIFF(d, '02/27/1980', '02/27/2005') % 365.25, 0, 1) = 0
)
Admin
<quote>I thought that people who are born on Feb 29th, usually officially declare their birthday as either February 28th or March 1st, so it still shouldn't be an issue.</quote>
That's a little unfair. Do you randomly "fix" your birthday in one direction or the other?
Admin
Does for me, on Sybase. I tested before I posted. Maybe microsoft broke it?
Admin
The really simple answer is to not allow birthdays to be set on Feb 29th in the first place.
;)
Admin
Admin
Admin
Or, using sqlite:
SELECT CustomerId, EmailAddress FROM Customers WHERE Birthdate = date('now','+1 day')