How about:
FUNCTION olddate(thedate, offset) * parameters: * the date: the source date * offset number of years offset, positive or negative * returns: the nearest date that is the same day of week as the source date
LOCAL thediff, theoffset thediff = DOW(thedate) - DOW(GOMONTH(thedate, offset*12)) theoffset = IIF(ABS(thediff)>3, 7-SIGN(thediff)*(thediff), thediff) RETURN GOMONTH(thedate, offset*12)+theoffset
ABS() only picks up the high end of the date difference, 4,5,6 SIGN() toggles whether you add or subtract the difference (minus a minus is a plus)
On Tue, May 8, 2018 at 5:03 PM, Ted Roche tedroche@gmail.com wrote:
An ICASE might do it.
Basically the idea is get the day number (DOW) of the current date, like 2 for Tuesday if SET FDOW is 1 ("the first day of the week is Monday")
Then create a new date with GOMONTH() and get the day number of that, some number 1 through 7. So if the new date is a five, I want to go back 3 to get to 2. Similarly, if it's a 6, I want to go forward 3 to get to the next, closest 2.
So, you want to find the nearest matching day number: they're either the same day, so zero offset, or the matching day number are 1,2,3 days earlier or later.
so you take the difference between the original date and the new date. if the absolute difference is 3 or less, that's your offset and you use that to move the new date to the matching day number.
If the difference is -4, -5, -6 or 4, 5, 6 days, you need to look to the next/previous weeks' matching day number, hence the magic 7 number.
On Tue, May 8, 2018 at 3:39 PM, Richard Kaye rkaye@invaluable.com wrote:
Or an ICASE? (I haven't quite wrapped my head around what you're doing there but it seems like there are 3 states?)
m.theOffset=ICASE(theDiff>3, 7-m.theDiff,theDiff<-3, 7+m.theDiff, m.theDiff)
--
rk
-----Original Message----- From: ProfoxTech profoxtech-bounces@leafe.com On Behalf Of Ted Roche Sent: Tuesday, May 08, 2018 3:25 PM To: profoxtech@leafe.com Subject: Re: Fun with date calculations in VFP
GOMONTH() just moves back to 2/28 on years that don't have a 2/29, so your olddate({^2016-02-29},-2) gives you the previous Tuesday, 2/24/2014.
Hmmm. That's an OBO. It goes back 4 instead of forward 3. I think the nearest date ought to be 2014-03-03
Ah, if thediff = -4, it remains -4. That's a bug. Add the second line below after the first:
m.theOffset=IIF(theDiff>3, 7-m.theDiff, m.theDiff) m.theOffset=IIF(theDiff<-3, 7+m.theDiff, m.theDiff)
I know there's a better algorithm, likely involving MOD() or CEILING() or FLOOR() but it's escaping me at the moment.
There's 49 combinations of original date = (1,2,3,4,5,6,7) and resultant date = (1,2,3,4,5,6,7) and the offset should come out as {-3,-2,-1,0,1,2,3} , but I'm drawing a blank. Anyone? Beuller?
On Tue, May 8, 2018 at 2:15 PM, Richard Kaye rkaye@invaluable.com wrote:
Ted's solution works just fine. What I didn't test yet is using leap day itself as the starting point. Hmmm.....
Program: datestuff3.prgDate: 05/08/2018 11:09 AM- VFP Version: Visual FoxPro 09.00.0000.7423 for Windows
Notes:
ACTIVATE SCREEN CLEAR ? [Today: ]+CHR(9)+CHR(9) ?? DATE() ?? CHR(9)+CDOW(DATE()) ? [Same day last year: ] ?? olddate(DATE(),-1) ?? CHR(9)+CDOW(olddate(DATE(),-1)) ? [Same day 2 years ago: ] ?? olddate(DATE(),-2) ?? CHR(9)+CDOW(olddate(DATE(),-2)) ? [Same day 3 years ago: ] ?? olddate(DATE(),-3) ?? CHR(9)+CDOW(olddate(DATE(),-3)) ? [Same day 10 years ago: ] ?? olddate(DATE(),-10) ?? [ ]+CDOW(olddate(DATE(),-10)) ? [Yesterday: ]+CHR(9) ?? DATE()-1 ?? CHR(9)+CDOW(DATE()-1) ? [Same day last year: ] ?? olddate(DATE()-1,-1) ?? CHR(9)+CDOW(olddate(DATE()-1,-1)) ? [Same day 2 years ago: ] ?? olddate(DATE()-1,-2) ?? CHR(9)+CDOW(olddate(DATE()-1,-2)) ? [Same day 3 years ago: ] ?? olddate(DATE()-1,-3) ?? CHR(9)+CDOW(olddate(DATE()-1,-3)) ? [Same day 10 years ago: ] ?? olddate(DATE()-1,-10) ?? [ ]+CDOW(olddate(DATE()-1,-10)) ? [Tomorrow: ]+CHR(9) ?? DATE()+1 ?? CHR(9)+CDOW(DATE()+1) ? [Same day last year: ] ?? olddate(DATE()+1,-1) ?? CHR(9)+CDOW(olddate(DATE()+1,-1)) ? [Same day 2 years ago: ] ?? olddate(DATE()+1,-2) ?? CHR(9)+CDOW(olddate(DATE()+1,-2)) ? [Same day 3 years ago: ] ?? olddate(DATE()+1,-3) ?? CHR(9)+CDOW(olddate(DATE()+1,-3)) ? [Same day 10 years ago: ] ?? olddate(DATE()+1,-10) ?? [ ]+CDOW(olddate(DATE()+1,-10))
FUNCTION oldDate(theDate AS Date, offset AS Integer)
- compliments of Ted Roche
- parameters: thedate: date to start from
- offset: number of years offset, positive or negative
- returns: nearest date to the offset that falls on the same day of the week
LOCAL m.theDiff, m.theOffset m.theDiff=DOW(m.theDate)-DOW(GOMONTH(m.theDate, m.offset*12)) m.theOffset=IIF(theDiff>3, 7-m.theDiff, m.theDiff) RETURN GOMONTH(m.theDate, m.offset*12) + m.theOffset
ENDFUNC
--
rk
-----Original Message----- From: ProfoxTech profoxtech-bounces@leafe.com On Behalf Of Gene Wirchenko Sent: Tuesday, May 08, 2018 12:46 PM To: profoxtech@leafe.com Subject: RE: Fun with date calculations in VFP
At 06:27 2018-05-08, Richard Kaye rkaye@invaluable.com wrote:
The latter. And that was the approach I was just working through.
What about the week every few years that you will be disregarding? A year has 52 weeks plus one or two days.[snip]
Sincerely,
Gene Wirchenko
[excessive quoting removed by server]