# Calculating Dates in AutoHotkey by Adding Years, Months, and/or Days

## The HowLongYearsMonthsDays.ahk Script Calculates Time Spans—This New DateCalc() Function Yields New Dates Based on Adding or Subtracting Years, Months, or Days

Allan recently inspired me to write (and helped me debug) an AutoHotkey function for calculating new dates based on entering years, months, and/or days. While not long or involved, the function includes a couple of interesting techniques.

Note: I have no doubt that many others have written similar date-calculating functions in AutoHotkey. This merely represents my stab at it.

The lack of consistency in days between 12-month years (leap years) and the varying numbers of days in months underlies the basic date calculating problem. While AutoHotkey includes a special tool (EnvAdd) for determining new dates based upon adding days, hours, minutes, or seconds to any valid date-time stamp format, writing a more complete date finding function requires accounting for the year and month variables separately.

Although, the EnvAdd expression (`Var += Value, TimeUnits`) overcomes date unit inconsistencies when working with days, it doesn’t help when computing years or months. Changing the year or month in the date-time stamp format can cause a variation in the EnvAdd day calculation. While most years contain 365 days, leap years run 366. Months vary from 28 days to 31 days depending upon the month and year. That means we must know both the final calculation year and the month before adding the days for a new date. Otherwise, we risk settling at an erroneous spot on the calendar—often, off by a day or two.

### Adding or Subtracting Years

You’ll find years the simplest of all date-time calculations in both math and format. With the number of digits fixed at four, you merely need to add to (or subtract from) that number:

`` SubStr(Date,1,4)+Years``

The SubStr() function extracts the first four characters of the date-time stamp and adds (or subtracts negative numbers) in years. If the new month process worked that easily, then the year would stand resolved. However, calculating the new month can cause changes to the year.

### Adding or Subtracting Months

Any month represents an entire unit—regardless of how many days each month contains. Each year consists of 12 complete month units. We can add months to the date-time stamp by adjusting the fifth and sixth date-time stamp digits:

``SubStr(Date,5,2)+Months ``

However, since a year only contains 12 months, we must adjust the year whenever we jump into a new year (total month value over 12) or regress to a previous year (zero or negative month value).

``````	While (Months > 12)
{
Years++
Months := Months - 12
}
While (Months <= 0)
{
Years--
Months := Months + 12
}``````

The above code shows two AutoHotkey While-Loop commands: one for adding months and the other for subtracting months.

1. In the first loop, each time the number of months exceeds 12, AutoHotkey must add one year to the date and subtract 12 months. This loop continues until the number of months drops below 13.
2. In the second loop, whenever the month number drops below 1 (zero or a negative number of months when substracting), AutoHotkey must subtract one year from the date and add 12 months—similar to borrowing higher units in a basic math subtraction problem.

This code calculates both the proper year and month prior to using the date-specific form of the EnvAdd expression using the days units to determine the new date.

Note: An alternative approach to the month calculation uses the Floor() function and the Mod() function to determine the impact on the years and months, thus eliminating the two loops. The single-line functions offer significantly faster results—especially for large changes in the number of years or months. I’ll discuss this AutoHotkey trick next time.

### Adding or Subtracting Days

Once we settle on the proper year and month, the EnvAdd command can do its work:

``````NewDate := Substr(Date,1,4)+Years
. Format("{:02}", Months)
. Substr(Date,7,2)
NewDate += Days , Days``````

(The above snippet uses line continuation techniques to wrap lines of code for display purposes.)

First, AutoHotkey reformats the input date into the date-time stamp for use in the days calculation. Then, adds the number of days using the EnvAdd expression (`NewDate += Days, Days`)—automatically accounting for any variation in years or months.

### The DateCalc() Function

The following sample AutoHotkey script includes the DateCalc() function for figuring a future (or past) day on the calendar. To test various outcomes, change the Date variable (date-time stamp format) and any of the units (years, months, or days), then rerun the script. Any combination of variables should produce a proper result. (Please let me know if you find a bug.) August 16, 2021 Reported bug (see comments below).

```Date := "20210315"
Years := 3
Months := 3
Days := 2

NewDate := DateCalc(Date,Years,Months,Days)
FormatTime, TimeString, %NewDate%, LongDate
MsgBox % SubStr(NewDate,1,8) "`r" TimeString

DateCalc(Date := "",Years := 0,Months := 0,Days := 0)
{
If (Date = "")
Date := A_Now
Months := SubStr(Date,5,2)+Months
While (Months > 12)
{
Years++
Months := Months - 12
}
While (Months <= 0)
{
Years--
Months := Months + 12
}

NewDate := Substr(Date,1,4)+Years
. Format("{:02}", Months)
. Substr(Date,7,2)
NewDate += Days , Days
Return NewDate
}
```

Click the Follow button at the top of the sidebar on the right of this page for e-mail notification of new blogs. (If you’re reading this on a tablet or your phone, then you must scroll all the way to the end of the blog—pass any comments—to find the Follow button.)

This post was proofread by Grammarly
(Any other mistakes are all mine.)

(Full disclosure: If you sign up for a free Grammarly account, I get 20¢. I use the spelling/grammar checking service all the time, but, then again, I write a lot more than most people. I recommend Grammarly because it works and it’s free.)

Find my AutoHotkey books at ComputorEdge E-Books!

Find quick-start AutoHotkey classes at “Robotic Desktop Automation with AutoHotkey“!

## 4 thoughts on “Calculating Dates in AutoHotkey by Adding Years, Months, and/or Days”

1. […] to perform the month’s calculation problem presented in last week’s blog “Calculating Dates in AutoHotkey by Adding Years, Months, and/or Days” without using any […]

Like

2. KengPoh says:

Try this and you will get a bug:
Date := “20210331”
Years := 0
Months := 3
Days := 0

Like

• Good catch! The function attempts to create an invalid date.

After the first calculation of NewDate, add the following code:

FormatTime, TestDate, %NewDate%, ShortDate
While !TestDate
{
NewDate := Substr(Date,1,4)+Years
. Format(“{:02}”, Months)
. Substr(Date,7,2)-A_Index

FormatTime, TestDate, %NewDate%, ShortDate
}