Posted in ColdFusion | Posted on 02-09-2010 | 2,625 views
Ellis asks:
I ran into a problem with my app last week and it had me stumped for three days. I think I worked out all the kinks, but I wanted to see if you could take a glance at my code to make sure I'm on the right path. Main issue is with billing dates. When a user signs up on the app they get a billing recurring date which the same day that they sign up on ie 1/31/2010. An error was thrown 2/30/2010 because the date doesn't exist.
I took a look at Ellis' solution, and while it worked, it was quite complex and long and I suggested a much simpler solution that I thought my other readers may enjoy. Obviously there are multiple ways of handling this situation, but I recommended the following pseudo-code as a solution:
Given that a user wants to be billed on date X, and given it is Month M, Year N, what is the best possible match? If M/X/N exists, then use it. If the month doesn't have X days, then use the last day of the month.
I wrote this logic as the following simple UDF:
2function getBillingDate(month,year,day) {
3 var baseDate = createDate(arguments.year, arguments.month, 1);
4 if(daysInMonth(baseDate) lt arguments.day) return
5createDate(arguments.year, arguments.month, daysInMonth(baseDate));
6 return createDate(arguments.year, arguments.month, arguments.day);
7}
8</cfscript>
As you can see, it creates a date based on the passed in year and month. It uses 1 for the day of the month. Once we have that, I simply compare the days in the month to the desired day. If the days in the month is less than the desired date, I use the total number of days in the month. Otherwise - I use the desired date.
To ensure it actually worked, I whipped up a quick test. It runs through five years and a set of desired dates. I intentionally chose dates towards the end of the month to test my logic.
2
3<cfloop index="year" list="2000,2001,2002,2003,2004">
4 <cfloop index="month" from="1" to="12">
5 <cfloop index="testDate" array="#tests#">
6 <cfoutput>
7 Attempted billing day of #testDate# for #month#/#year# :
8#getBillingDate(month,year, testDate)#<br/>
9 </cfoutput>
10 </cfloop>
11 <br/><br/>
12 </cfloop>
13 <br/><br/>
14</cfloop>
I won't bore people with the output from this, but I confirmed it correctly handled February, and also noticed leap years when it could get a bit closer to 30 and 31.
I'm sure there are probably a thousand other ways to handle this, but hopefully this will help others.


I've found the complexity increases some when people want to change payment days and tracking successful payments. In our system, there is an added check to make sure there are no existing successful payments already in the same month. Also, the recurring payments are disabled after 2 failed attempts within the same month and a notice is sent out to the customer and to an account rep.
<cffunction name="GetNextBillingDate" returntype="date" output="false">
<cfargument name="startdate" type="date" required="true">
<cfargument name="currentdate" type="date" default="#Now()#">
<cfreturn DateAdd("m", DateDiff("m", startdate, currentdate) + 1, startdate)>
</cffunction>
Interestingly, my original code was in SQL, which also has the DateDiff function but works in such a way that the calculation is slightly more complicated.
# Lap Band Surgery
# cheap web hosting
From their pdf:
https://cms.paypal.com/cms_content/en_US/files/dev...
How Subscriptions with Monthly Billing Cycles Work
For monthly billing cycles, recurring payments are collected on the same day of the month. If the initial recurring payment falls on the 31st, PayPal eventually adjusts the billing cycle to the 1st of the month. If the initial recurring payment falls on the 29th or 30th, PayPal adjusts the billing cycle to the 1st of the month on the following February.
EXAMPLE 3.2 When Monthly Recurring Payments Are Due and Collected on the 31st
The subscription terms are:
- $25.99 USD a month; the subscriber signs up on Thursday, July 31.
The subscriber is billed as follows:
- Thursday, July 31 = $25.99 USD
- Saturday, August 31 = $25.99 USD
- Wednesday, October 1= $25.99 USD
- Saturday, November 1= $25.99 USD
and so on...
Notice that no recurring monthly payment was collected in September, but recurring payments were collected roughly every 30 days.
EXAMPLE 3.3 When Monthly Recurring Payments Are Due and Collected on the 30th
The subscription terms are:
- $25.99 USD a month; the subscriber signs up on Tuesday, December 30.
The subscriber is billed as follows:
- Tuesday, December 30 = $25.99 USD
- Friday, January 30 = $25.99 USD
- Sunday, March 1= $25.99 USD
- Wednesday, April 1= $25.99USD
and so on...
Notice that no recurring monthly payment was collected in February, but recurring payments were collected roughly every 30 days.
[Add Comment] [Subscribe to Comments]