ServiceNow script to calculate days until AD account expires

I am just starting to learn how to develop applications and write scripts for ServiceNow. I’m adapting to going from using some of the best tools used for dotNET development to the few options ServiceNow provides (an in-browser IDE with a hit and miss debugger). My employer is not a development house so I get by with Visual Studio Code and some other open source tools.

One of my first tasks was to send an email notification each time an Active Directory account was 10, 7, and 3 days from expiring. But, we quickly discovered LDAP stores this value as a number of 100-nanosecond intervals since January 1, 1601 (UTC). JavaScript does something similar, but it uses milliseconds since January 1, 1970. So, I have to put both in the same unit to be able to subtract one interval from the other.

I added a script in a Field Map inside a Table Transform Map that runs daily to import data from LDAP/AD. This script transforms the value to be imported in the number of days until expiration.

answer = (function transformEntry(source) {

var daysToExpiration = 0;
// Account-Expires attribute comes as source.u_accountexpires from LDAP.
// This value represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).

// If variable is coming null return 0 days
if (source.u_accountexpires == '' || 
    source.u_accountexpires == null || 
    source.u_accountexpires == undefined) {
daysToExpiration = 0

}

A value of 0 or 0x7FFFFFFFFFFFFFFF (9223372036854775807) indicates that the account never expires. Therefore, we assign a big number for the days. This way the user never gets an email.

else {
if (source.u_accountexpires == 0 || 
    source.u_accountexpires == 9223372036854775807) { 
daysToExpiration = 50000;
}
else {

I tried to get the JavaScript Date object to work but it did not so I used GlideDateTime from the ServiceNow API for server scripts to do the calculations.
11644473600000 is the 100ns from Jan 1, 1601, to Jan 1, 1970. Added to match LDAP to Javascript.
now.getNumericValue() return the milliseconds from Jan 1, 1970.
Multiply by 10000 to convert from milliseconds(js) to 100 of a nanosecond (LDAP).

var now = new GlideDateTime();

var today = 116444736000000000 + ( now.getNumericValue() * 10000 )

Subtract today in LDAP format and divide by the number of 100 of nanoseconds in a day.


daysToExpiration = ( source.u_accountexpires - today ) / 864000000000;

If the account has already expired, we assign it a 0

if (daysToExpiration < 0) {
    daysToExpiration = 0;
}

Next is the code that determines if the notification is sent or not, and returns the days to expiration.

daysToExpiration = parseInt(daysToExpiration, 10)

switch (daysToExpiration) {
    case 3:
    case 7:
    case 10:
     //LDAP-disabled users are not sent an email during transform based on 'userAccountControl' attribute
         switch (parseInt(source.u_useraccountcontrol,10)) {
              case 514:
              case 546:
              break;
              default:
              gs.eventQueue('userid.expired', target, parseInt( daysToExpiration, 10 ), target.email);
          }//inner switch
     } // end switch outer
}

return daysToExpiration;
}
})

(source);

Download Script from GitHub