0

I'm trying to create a dateAdd function in SSJS by calling the dateAdd function in Ampscript. The code below works. But I cannot figure out how to make the date argument dynamic. This means the function in my code always starts with the current date time and calculates a new date from there. I would like to make the function truly dynamic by passing a date to the function.

My problem is that the date in SSJS and Ampscript is not formatted in the same way. That is a problem when I pass the date into the ampscript code.

I'm aware of this question (Date manipulation Function SSJS) regarding creating a dateadd function in SSJS, but the answer there takes another approach. It tries to make the dateadd function from scratch in Javascript. I want to take advantage of the function that is already made in Ampscript.

<!-- For debugging only start -->
<p>
  Printing a date in ampscript for comparison<br>
  newDateAmpScript: %%=v(NOW())=%% <br><br>
</p>
<!-- For debugging only end -->


<script runat="server">
  Platform.Load("Core","1.1.1");
  
   // For debugging only start
   var newDateSsjs = new Date();
   Write('Printing a date in Javascript for comparison<br>')
   Write('newDateSsjs: ' + newDateSsjs + "<br><br>");
  // For debugging only end

  function dateAdd(date, intervalNumber, intervalUnit) {
       
   var calulatedDateAmpScriptString = '%' + '%['
                                      + 'VAR @calulatedDate '
                                      + 'SET @calulatedDate = SystemDateToLocalDate(DateAdd(NOW(), ' + intervalNumber +', "' + intervalUnit + '")) '
                                      + 'VAR @calulatedDateIso '
                                      + 'SET @calulatedDateIso = FormatDate(@calulatedDate, "iso") '
                                      + ']%' + '%';
    
      
    // Printing ampscript string for easier debugging
     Write(calulatedDateAmpScriptString + "<br><br>");
     
     try {
       var content = Platform.Function.TreatAsContent(calulatedDateAmpScriptString);
       return Platform.Variable.GetValue("@calulatedDateIso");
     }
     catch(e) {
       Write("error: " + Stringify(e) + "<br><br>")
     }
   }

   // Calling the dateAdd function to test it
   var modifiedDateFrom = dateAdd(newDateSsjs, -18, 'D');
   Write("modifiedDateFrom: " + modifiedDateFrom);
</script>
1
  • Going back and forth between languages will actually be slower than using the inherit date options in SSJS. I would highly recommend using SSJS functions instead of dynamically creating an ampscript statement and running it. – Gortonington Dec 4 '20 at 14:23
0

I would not recommend using SSJS to dynamically create and then run AMPScript like this, it is going to open a TON of risk and slow down processing and load times.

If you just want a dateadd function to reference instead of having to build something new for each need, I can give you a homegrown dateAdd() function I created/Frankensteined in SSJS that you can use. I would not call it perfect and it certainly has some odd coding and such (e.g. each case in switch needs to be filled in order to work right) but it gets the job done.

function dateAdd(date, interval, units) {

  //Backfill of Array.includes
  Array.includes = function(val,arr) {
    for(i=0;i<arr.length;i++){
      if (!r || r == false){r = val == arr[i] ? true: false;}
    }
    return r;
  }

  // Verify if date is a date
  if(!(typeof date.getMonth === 'function'))  
    return 'Not a valid Date';
 
  var ret = new Date(date); //don't change original date

  // Verify if units are positive integers
  if (units < 1) { return 'Unit needs to be an integer of 1 or higher'; }

  // Verify if correct interval || case insensitive
  var arr = ["y","q","m","w","d","h","mi","s","year","quarter","month","week","day","hour","minute","second"]
  if (!(Array.includes(interval.toLowerCase(),arr))) { return 'Incorrect interval passed'; }

  var checkRollover = function() { if(ret.getDate() != date.getDate()) ret.setDate(0);};
  switch(String(interval).toLowerCase()) {
    case 'y'      :  ret = new Date(date.getFullYear() + units, date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()); checkRollover();  break;
    case 'year'   :  ret = new Date(date.getFullYear() + units, date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()); checkRollover();  break;
    case 'q'      :  ret.setMonth(ret.getMonth() + 3*(units+1)); checkRollover();  break;
    case 'quarter':  ret.setMonth(ret.getMonth() + 3*(units+1)); checkRollover();  break;
    case 'm'      :  ret.setMonth(ret.getMonth() + (units+1)); checkRollover();  break;
    case 'month'  :  ret.setMonth(ret.getMonth() + (units+1)); checkRollover();  break;
    case 'w'      :  ret.setDate(ret.getDate() + 7*units);  break;
    case 'week'   :  ret.setDate(ret.getDate() + 7*units);  break;
    case 'd'      :  ret.setDate(ret.getDate() + units);  break;
    case 'day'    :  ret.setDate(ret.getDate() + units);  break;
    case 'h'      :  ret.setTime(ret.getTime() + units*3600000);  break;
    case 'hour'   :  ret.setTime(ret.getTime() + units*3600000);  break;
    case 'mi'     :  ret.setTime(ret.getTime() + units*60000);  break;
    case 'minute' :  ret.setTime(ret.getTime() + units*60000);  break;
    case 's'      :  ret.setTime(ret.getTime() + units*1000);  break;
    case 'second' :  ret.setTime(ret.getTime() + units*1000);  break;
  }

  return ret;
}

And then just output similar to the AMPScript version:

var date = new Date(),
    interval = 'Q',
    units = 1;
var newDate = dateAdd(date,interval,units);
Write('date: ' + date + '<br>');
Write('interval: ' + interval + '<br>');
Write('units: ' + units + '<br>');
Write('newDate: ' + newDate + '<br>');

Outputs:

date: Fri, 04 Dec 2020 13:28:35 GMT-06:00
interval: Q
units: 1
newDate: Thu, 04 Mar 2021 13:28:35 GMT-06:00
7
  • thank you for sharing your function with me, and my apologizes for my late response. The function is very useful, but I have a few questions. To me, it looks like there is an error in calculating quarter. It seems like getMonth counts from zero, and setMonth counts from one. This means that the quarter calculation is off by one month. Your code for calculation months has taken that problem into account. – Knud Back Dec 22 '20 at 13:17
  • Code that illustrates the difference in how getMonth and setMonth counts. <script runat="server"> Platform.Load("Core","1.1.1"); var newDate = new Date(); Write('Date BEFORE using get and set: ' + newDate + '<br>'); newDate.setMonth(newDate.getMonth()); Write('Date AFTER using get and set: ' + newDate + '<br>'); </script> – Knud Back Dec 22 '20 at 13:18
  • @KnudBack - if you run the code, you will notice it works as expected. E.g. Dec, Jan, Feb = 3 months, which is one quarter of a year. As I stated, it has different eccentricities that do not make sense with normal JS. – Gortonington Dec 22 '20 at 13:21
  • Also, if, as you stated, I already accounted for getMonth being 0 based in my answer, I am not sure why you would then show me code explaining what I obviously already know...? Seems kind of rude. – Gortonington Dec 22 '20 at 13:26
  • @KnudBack - As I wrote out my first comment, I found out my fallacy of logic. I was counting total months not additional months. I do fully stand behind my second comment and still find that to be pedantic and rude. It would be like me explaining to you in my answer what a function is, which you obviously already know. – Gortonington Dec 22 '20 at 13:30
0

Here is one way to do this using the AMPscript DateAdd() function by invoking it with SSJS. I also included the AMPscript date format as a parameter, so that can be changed to match your desired format.

<script runat="server">
Platform.Load("Core","1.1.1") // load platform library

//call the dateaddJS function, passing the startingDate, intervalNumber, intervalUnit, and desired format all as separate arguments
var startingDate = "12/19/2020"
var modifiedDate = dateAddJS(startingDate, -18, 'D', "mm/dd/yyyy") 

//output startingDate
Write("<hr>startingDate: " + startingDate)
//output date calculated by ampscript dateadd function
Write("<hr>modifiedDate: " + modifiedDate)

function dateAddJS(date, intervalNumber, intervalUnit, dateFormat) {
    var date = new Date(date)
    // pass our js variables to ampscript variables
    Variable.SetValue("date",date)
    Variable.SetValue("intervalNumber",intervalNumber)
    Variable.SetValue("intervalUnit",intervalUnit)
    Variable.SetValue("dateFormat",dateFormat)
    // return ampscript forced to run by SSJS TreatAsContent function 
    return TreatAsContent("%%[output(formatdate(dateadd(@date,@intervalNumber,@intervalUnit),@dateFormat))]%%")
}
</script>
1
  • 1
    Thank you for your response to my question. I have tried your code, and it worked great. Apart from solving my immediate problem, the code also serves a good template for using ampscript functions in ssjs. Thank you for your time. – Knud Back Dec 26 '20 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.