Subtract a month from a date?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
chef423
Posts: 213
Joined: 28 Aug 2016, 12:10
Contact:

Subtract a month from a date?

08 Feb 2017, 13:01

Code: Select all

	CurrentDate := A_Now
	CurrentDate += -1, D
	FormatTime, TimeString, %CurrentDate%, M/d/yyyy
	msgbox, %TimeString%
That gives me a day behind, so the code spits out 2/7/2017, as it should

When I replace the D with an M as..

Code: Select all

	CurrentDate := A_Now
	CurrentDate += -1, M
	FormatTime, TimeString, %CurrentDate%, M/d/yyyy
	msgbox, %TimeString%
The output is now 2/8/2017

So changing that variable simply wont work? Hmm
User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Subtract a month from a date?

08 Feb 2017, 13:41

First, what do you mean by "a month"? For example, if the date is March 31 and you subtract a month, what's the answer? In any case, date-time math is done with EnvAdd and EnvSub. Regards, Joe
chef423
Posts: 213
Joined: 28 Aug 2016, 12:10
Contact:

Re: Subtract a month from a date?

08 Feb 2017, 13:46

ANSWER = FEB

I only want the MONTH AND YEAR. I should have made that clear from the get go. My apologies.

I want to take today's month, which is Feb, and make it Jan

So the output should be: 1/2017 not, 2/2017
User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Subtract a month from a date?

08 Feb 2017, 14:00

Ah, that's a different story. If the date is 31-Jan-2017, should the answer be 12/2016?
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Subtract a month from a date?

08 Feb 2017, 14:11

TimeUnits can be either Seconds, Minutes, Hours, or Days (or just the first letter of each of these).
Months are not supported. Probably because it becomes subjective with months. What is 1 month before 3/31/2017? What is 1 month before 2/28/2017? Leap year is also a factor. 12 months from 2/29/2018.

Basically you are going to have to create your own function and decide how you want to handle those situations. Based on the same discussions for Excel there is no universal answer.

(Got distracted with work and others posted similar thoughts while I was sitting mid-post)

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
garry
Posts: 3764
Joined: 22 Dec 2013, 12:50

Re: Subtract a month from a date?

08 Feb 2017, 14:15

example

Code: Select all

;- add-subtract-months monthx lastdayofmonthx 
a=2017-03-31
;FormatTime, a, %a_now% ,yyyy-MM-dd

stringmid,y,a,1,4
stringmid,m,a,6,2
stringmid,d1,a,9,2
m:=(m-1)          ;-  <<< subtract or add x months
if (m>12)
  {
  y:=(y+1)
  m:=(m-12)
  }
m:=SubStr(0 m, -1)
z:= y . m
d:=LastDayInMonth(z)        ;- last day of month x
if (d<d1)
   d2:=d
else
   d2:=d1
msgbox,%y%-%m%-%d2%
return

LastDayInMonth(TimeStr="") {
  StringLeft Date,TimeStr,6 ; YearMonth
  Date1 = %Date%
  Date1+= 31,D              ; A day in next month
  StringLeft Date1,Date1,6  ; YearNextmonth
  Date1-= %Date%,D          ; Difference in days
  Return Date1
}
;==================================================

User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Subtract a month from a date?

08 Feb 2017, 14:17

Haven't heard back from you on my last question, but assuming the answer is yes, this will work for you, since A_Now is in YYYYMMDDHH24MISS format:

Code: Select all

CurrentDate:=A_Now
CurrentYear:=SubStr(CurrentDate,1,4)
CurrentMonth:=SubStr(CurrentDate,5,2)
If (CurrentMonth=1)
{
  OutputMonth:=12
  OutputYear:=CurrentYear-1
}
Else
{
  OutputMonth:=CurrentMonth-1
  OutputYear:=CurrentYear
}
MsgBox,,,%OutputMonth%/%OutputYear%
Regards, Joe
chef423
Posts: 213
Joined: 28 Aug 2016, 12:10
Contact:

Re: Subtract a month from a date?

08 Feb 2017, 14:42

Sorry guys, we are making this complicated and it shouldn't be.

I just want to roll back (subtract a month)

My code is this, not what I have above.

Code: Select all

	CurrentDate := A_Now
	FormatTime, TimeString, %CurrentDate%, MMM/yyyy
	msgbox, %TimeString%
So if the current date is 2/2017, I need the output to be 1/2017

Thought this would do it:

Code: Select all

	CurrentDate := A_Now
	CurrentDate += -1, M
	FormatTime, TimeString, %CurrentDate%, MMM/yyyy
	msgbox, %TimeString%
Last edited by chef423 on 08 Feb 2017, 14:48, edited 2 times in total.
chef423
Posts: 213
Joined: 28 Aug 2016, 12:10
Contact:

Re: Subtract a month from a date?

08 Feb 2017, 14:43

JoeWinograd wrote:Ah, that's a different story. If the date is 31-Jan-2017, should the answer be 12/2016?
Correct, Joe
User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Subtract a month from a date?

08 Feb 2017, 14:49

> Correct, Joe

Then the code in my last post will do the job for you.
chef423
Posts: 213
Joined: 28 Aug 2016, 12:10
Contact:

Re: Subtract a month from a date?

08 Feb 2017, 14:56

JoeWinograd wrote:> Correct, Joe

Then the code in my last post will do the job for you.
Worked like a charm. Thank you sir!!
User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Subtract a month from a date?

08 Feb 2017, 15:01

Glad to hear it! You're very welcome!
garry
Posts: 3764
Joined: 22 Dec 2013, 12:50

Re: Subtract a month from a date?

08 Feb 2017, 15:05

another example , minus months ( only subtract one year )

Code: Select all

;- example minus x months
x:=3
stringmid,m,a_now,5,2
stringmid,y,a_now,1,4
c:=(m-x)
if c<1
  {
  c:=(12-(-c))
  y:=(y-1)
  }
c:=SubStr(0 c, -1)   ;- add leading zero
msgbox,%c%/%y%
return
Last edited by garry on 08 Feb 2017, 15:36, edited 1 time in total.
4GForce
Posts: 553
Joined: 25 Jan 2017, 03:18
Contact:

Re: Subtract a month from a date?

08 Feb 2017, 15:13

No one uses EnvAdd and EnvSub ???
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Subtract a month from a date?

08 Feb 2017, 15:22

You might find this function useful:

Code: Select all

Msgbox % Month_Change(-1)
Msgbox % Month_Change(-2)
Msgbox % Month_Change(-14)
Msgbox % Month_Change(2,11,2017, "M/yy")

Month_Change(Change, Month = 0, Year = 0, Format := "MMM-yyyy")
{
	(!Month) ? (Month := A_MM)
	(!Year) ? (Year := A_YYYY)
	Months := Month + (Year * 12) + Change
	Year := Floor(Months / 12)
	Month := Mod(Months, 12), (!Month) ? (Month = 12, Year --)
	FormatTime, Date, %Year% %Month%, %Format%
	Return Date
}
Edit: Added Format parameter.

@4GForce as quoted in my first post, TimeUnits for EnvAdd EnvSub cannot be months.

FG
Last edited by FanaticGuru on 08 Feb 2017, 16:34, edited 1 time in total.
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
garry
Posts: 3764
Joined: 22 Dec 2013, 12:50

Re: Subtract a month from a date?

08 Feb 2017, 15:35

@FanaticGuru , thank you
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Subtract a month from a date?

09 Feb 2017, 06:30

This method is pretty straightforward.

Code: Select all

q:: ;get the previous/next month
;(get a day in the previous/next month)
vDate1 := vDate2 := vDate := A_Now
vDays := SubStr(vDate, 7, 2)
vDate1 += -vDays-1, Days ;last day of the previous month
vDate2 += 32-vDays, Days ;a day in the next month

FormatTime, vDate, % vDate, M/yyyy
FormatTime, vDate1, % vDate1, M/yyyy
FormatTime, vDate2, % vDate2, M/yyyy
MsgBox % vDate1 " " vDate " " vDate2
Return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Subtract a month from a date?

09 Feb 2017, 09:14

I tried to write a date 'add months' function.
I believe it works correctly, but it's not guaranteed,
so please mention any bugs if there are any.
Basically it will add months, maintaining the day of the month.
If the day of the month is too big for the month, the
day is adjusted downwards.

[EDIT:]
I just saw FanaticGuru's function, I had thought about
converting to months first, it looks like it's much simpler,
I will update my function I believe!

[EDIT 2: see improved version of code at the bottom of this post]

Code: Select all

q:: ;date add months
vDate := A_Now
vFormat := "HH:mm dd/MM/yyyy"
vNum := 3
vDate0 := JEE_DateAddMonths(vDate, 0, vFormat)
vDate1 := JEE_DateAddMonths(vDate, -vNum, vFormat)
vDate2 := JEE_DateAddMonths(vDate, vNum, vFormat)
MsgBox % vDate1 "`r`n" vDate0 "`r`n" vDate2
Return

;==================================================

JEE_DateAddMonths(vDate, vNum, vFormat="")
{
vDate += 0, Seconds ;make date the standard 14-character format
vYear := SubStr(vDate, 1, 4)
vMonth := SubStr(vDate, 5, 2)
vDay := SubStr(vDate, 7, 2)
vTime := SubStr(vDate, 9)

vSign := (vNum < 0) ? -1 : 1
vNum := Abs(vNum)
vYears := vSign*Floor(vNum/12)
vMonths := vSign*Mod(vNum,12)

if (vSign = -1) && (vMonth+vMonths < 1)
vYears -= 1, vMonths := 12+vMonths
if (vSign = 1) && (vMonth+vMonths > 12)
vYears += 1, vMonths := vMonths-12

vYear += vYears
vMonth += vMonths

if (vMonth = 2) && (vDay > 28)
if !Mod(vYear,4) && (Mod(vYear,100) || !Mod(vYear,400)) ;4Y AND (100N OR 400Y)
vDay := 29
else
vDay := 28

if (vDay = 31)
if vMonth in 4,6,9,11
vDay := 30

(StrLen(vMonth)=1) ? (vMonth := "0" vMonth) : ""
(StrLen(vDay)=1) ? (vDay := "0" vDay) : ""
vDate := vYear vMonth vDay vTime
if !(vFormat = "")
FormatTime, vDate, % vDate, % vFormat
Return vDate
}
[EDIT 2:]
improved version (simplified code):

Code: Select all

q:: ;date add months
vDate := A_Now
vFormat := "HH:mm dd/MM/yyyy"
vNum := 3
vDate0 := JEE_DateAddMonths(vDate, 0, vFormat)
vDate1 := JEE_DateAddMonths(vDate, -vNum, vFormat)
vDate2 := JEE_DateAddMonths(vDate, vNum, vFormat)
MsgBox % vDate1 "`r`n" vDate0 "`r`n" vDate2
Return

;==================================================

JEE_DateAddMonths(vDate, vNum, vFormat="")
{
vDate += 0, Seconds ;make date the standard 14-character format
vYear := SubStr(vDate, 1, 4)
vMonth := SubStr(vDate, 5, 2)
vDay := SubStr(vDate, 7, 2)
vTime := SubStr(vDate, 9)

vMonths := (vYear*12) + vMonth + vNum
vYear := Floor(vMonths/12)
vMonth := Mod(vMonths,12)
(!vMonth) ? (vYear -= 1, vMonth := 12) : ""

if (vMonth = 2) && (vDay > 28)
if !Mod(vYear,4) && (Mod(vYear,100) || !Mod(vYear,400)) ;4Y AND (100N OR 400Y)
vDay := 29
else
vDay := 28

if (vDay = 31)
if vMonth in 4,6,9,11
vDay := 30

(StrLen(vMonth)=1) ? (vMonth := "0" vMonth) : ""
(StrLen(vDay)=1) ? (vDay := "0" vDay) : ""
vDate := vYear vMonth vDay vTime
if !(vFormat = "")
FormatTime, vDate, % vDate, % vFormat
Return vDate
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Bones
Posts: 28
Joined: 30 Oct 2013, 15:30

Re: Subtract a month from a date?

09 Feb 2017, 09:54

Here is a function I use in one of my programs.

Code: Select all


;///////
change_the_month(a_date,n)  ;  by n months keeping the same day of month  ;  problem with leading zeroes in months
{
	 
	StringLeft a_date,a_date,8
	
	StringLeft my_year,a_date,4
	StringRight my_day,a_date,2
	my_month := SubStr(a_date, 5 , 2) 
	base_12_number := 12 * my_year + my_month
	base_12_number += n
	my_year := floor(base_12_number / 12)
	my_month :=  mod(base_12_number,12)    ;base_12_number - my_year * 12
	if ( my_month = 0 )
	{
		my_month := 12
		--my_year
	}
	if ( my_month < 10 )
		my_month := "0" . my_month

	temp := my_year . my_month . my_day
	FormatTime, temp , %temp%, yyyyMMdd
	return, temp
}

;///////
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Subtract a month from a date?

09 Feb 2017, 14:05

jeeswg wrote:

Code: Select all

(StrLen(vMonth)=1) ? (vMonth := "0" vMonth) : ""
(StrLen(vDay)=1) ? (vDay := "0" vDay) : ""
I find SubStr a more versatile technique for adding leading zeros:

Code: Select all

vMonth = 1
vMonth := SubStr("0" vMonth,-1)
Msgbox % vMonth
vDayOfYear = 9
vDayOfYear := SubStr("00" vDayOfYear,-2)
Msgbox % vDayOfYear
vDayOfYear = 67S
vDayOfYear := SubStr("00" vDayOfYear,-2)
Msgbox % vDayOfYear
Also the else part of a ternary operation is not required. (StrLen(vMonth)=1) ? (vMonth := "0" vMonth) is fine but I can understand if your style just wants to show completeness. But you generally don't put an else with an if when not needed in a non-ternary If statement.

(I only offer critique of your code because you seem to be someone that is learning a lot of AHK coding in a short time and seem to be interested in improving your knowledge of AHK.)

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 377 guests