Normal Topic Adding / Subtracting Dates (Read 5453 times)
Rick_R
Full Member
***
Offline



Posts: 243
Joined: Jan 29th, 2010
Adding / Subtracting Dates
Feb 28th, 2011 at 4:40am
Print Post Print Post  
I'm in the process of developing a complex scheduler that will allow users to add/subtract "6 Months", "2 Weeks", etc.  For the most part that's pretty straightforward, but it does complicated with months because of their varying length.  Test code is in the reply.

If making any modifications be careful because sometimes you are adding a negative, and the tendency can be to think "I need to take the difference between Month and AmountToAdd because the result will be earlier than the original date."

// ======================================================================
// ADD TO DATE
// Returns Old date plus X days, weeks, months or years as Date
// AMOUNT TO ADD CAN BE NEGATIVE
// ======================================================================
Function AddToDate(OldDate as Date, AddWhat as String, AmountToAdd as Int) as Date
     var NewDate as Date = OldDate
     var YearNum as Int = @Year(OldDate)
     var MonthNum as Int = @Month(OldDate)

     AddWhat = @Replace(ToUpper(AddWhat), "S","") // Convert to uppercase, remove final S if any

     If AmountToAdd = 0 then // Do nothing -- date will be returned unchanged
     Else If AddWhat = "DAY" then NewDate = OldDate + AmountToAdd
     Else If AddWhat = "WEEK" then NewDate = OldDate + (7 * AmountToAdd)
     Else If AddWhat = "YEAR" then NewDate = @ToDate(@str(YearNum + AmountToAdd) + @Right(OldDate, 6))
     Else If AddWhat <> "MONTH" then // Do nothing -- date will be returned unchanged

     Else If AmountToAdd > 0 then      // ADD months
     {
           MonthNum = MonthNum + AmountToAdd      // E.g. 11/23/2003 + 27 = 38/23/2003, Months = 38
           YearNum = YearNum + (MonthNum /12)
           MonthNum = @Mod(MonthNum, 12)
           If MonthNum = 0 Then MonthNum = 12 // December mod 12 = Month 0
           NewDate = @ToDate(@Str(YearNum) + "/" + @Right("0" + @Str(MonthNum),2) + @Right(OldDate, 3))
     }
     Else  // SUBTRACT months
     {
           /* Vars:
           MonthNum = current month
           AmountToAdd = Amount to SUBTRACT
           YearNum = current year      
           */
           // Example: subtract 22 months from 1998/02/18
           YearNum = YearNum + @Int(AmountToAdd / 12)            // How many years to subtract = YearNum is now 1997
           AmountToAdd = @Mod(AmountToAdd, 12)            // How many months (less than yr) to subtract = 10.
           // Year is now correct but months not changed yet
           If AmountToAdd = 0      // 12 mos, 24, etc. -- Do nothing
           Else If (AmountToAdd + MonthNum) < 1 Then      // e.g., subtract 2 to 11 months from February
           {
                       YearNum = YearNum - 1                  // Do subtraction "borrowing" of 12 months.  YearNum is now 1996
                       MonthNum = MonthNum + 12 + AmountToAdd  // ADD MINUS 10 months to 14 months. Month is now 4 = April
           }
           Else MonthNum = MonthNum + AmountToAdd

           NewDate = @ToDate(@Str(YearNum) + "/" + @Right("0" + @Str(MonthNum),2) + @Right(OldDate, 3))
     }
     Return(NewDate)
End Function // AddToDate
  
Back to top
 
IP Logged
 
Rick_R
Full Member
***
Offline



Posts: 243
Joined: Jan 29th, 2010
Re: Adding / Subtracting Dates
Reply #1 - Feb 28th, 2011 at 4:44am
Print Post Print Post  
Test Code for AddToDate()
Note that the test for adding days and weeks and most of the years is commented out.

Note that the "interval" word is not case-sensitive and it works with or without a final S, i.e., Day, Days, day, DAYS will all work.


// ================== TEST CODE =====================

var NewDate as Date
// AddToDate(OldDate as Date, AddWhat as String, AmountToAdd as Int) as Date


// Test Add To Date
Subroutine TATD(vDate as Date, vInterval as String, vAmt as Int)
     Writeln("===================")
     Writeln(vDate)
     Writeln(vInterval)
     Writeln(vAmt)
     Writeln(AddToDate(vDate, vInterval, vAmt))
End Subroutine

OpenSlate()

/*

Writeln("DAYS AND WEEKS")
TATD("2006/07/09", "days", 5) // = 2006/07/14
TATD("2007/05/02", "weeks", 6) // = 2007/06/13

TATD("2016/08/09", "days", 15) // = 2016/08/24
TATD("2027/11/06", "weeks", 3) // = 2027/11/27

TATD("2026/12/12", "days", 14) // = 2026/12/26
TATD("2017/10/16", "weeks", 8) // = 2017/12/11


TATD("1992/02/25", "days", 14) // = 1992/03/10
TATD("1980/11/02", "weeks", 28) // = 1981/05/17

TATD("1946/11/09", "days", 85) // = 1947/02/02
TATD("2014/10/06", "week", 3) // = 2014/10/27

TATD("2038/11/12", "days", 34) // = 2038/12/16
TATD("2007/10/16", "weeks", 8) // = 2007/12/11

// =================================

Writeln("")
Writeln("ADD MONTHS AND YEARS")

TATD("2006/07/09", "months", 5) // = 2007/12/09
TATD("2007/05/02", "years", 6) // = 2013/05/02

TATD("2016/08/09", "months", 15) // = 2017/11/09
TATD("2027/11/06", "years", 3) // = 2030/11/06

TATD("2026/12/12", "months", 14) // = 2028/02/12
TATD("2017/10/16", "years", 8) // = 2025/10/16


TATD("1992/12/09", "months", 74) // = 1999/02/09
TATD("1980/11/02", "years", 28) // = 2008/11/02

TATD("1946/11/09", "months", 85) // = 1954/12/09
TATD("2014/10/06", "years", 3) // = 2017/10/06

TATD("2038/11/12", "months", 34) // = 2041/09/12
TATD("2007/10/16", "years", 8) // = 2015/10/16

*/


// =================================

Writeln("")
Writeln("")
Writeln("=========== SUBTRACT MONTHS AND YEARS ==============")
Writeln("")
Writeln("")

TATD("2006/07/09", "months", -5) // = 2006/02/09
Writeln("2006/02/09 <==")

TATD("2006/07/09", "months", -7) // = 2005/12/09
Writeln("2005/12/09 <==")

TATD("2016/08/09", "months", -15) // = 2015/05/09
Writeln("2015/05/09 <==")

TATD("2027/11/06", "years", -3) // = 2024/11/06

TATD("2026/12/12", "months", -14) // = 2025/10/12
Writeln("2025/10/12 <==")

TATD("2017/10/16", "months", -10) // = 2016/12/16


TATD("1992/12/09", "months", -74) // = 1986/10/09
Writeln("1986/10/09 <== 6Y 2M")

TATD("1980/11/02", "months", -35) // = 1977/12/02
Writeln("")

TATD("1946/11/09", "months", -85) // = 1939/10/09
Writeln("1939/10/09 <== 7Y 1M")

TATD("2014/10/06", "years", -3) // = 2011/10/06

TATD("2038/11/12", "months", -34) // = 2036/01/12
Writeln("2036/01/12 <== 2Y 10M")

TATD("2007/10/16", "years", -8) // = 1999/10/16
  
Back to top
 
IP Logged
 
Rick_R
Full Member
***
Offline



Posts: 243
Joined: Jan 29th, 2010
Re: CAUTION - Adding / Subtracting Dates
Reply #2 - Mar 14th, 2011 at 8:24pm
Print Post Print Post  
A caution regarding the routine, that I didn't originally notice --

Scenario: You receive a communication to "Meet me 1 month from today."  If you don't, someone will die (for whatever reason).  You can't communicate with the sender and (again, for whatever reason) you can only go on one day.

The communication is dated January, March, August or October 31. (Each followed by a month with less than 31 days.)

Which date is "1 month from" that date?

Related issue: Which date is "1 month before" March 31, July 31, etc?

I'll probably set up a poll to see if there a consensus.
  
Back to top
 
IP Logged