JavaScript Functions for Date Fields

Get Week Number From Date

Description:

Given the BO of a date field this function will return the week number the specified date is part of.

Usage Notes:

Place the function in the onLoad event of the form where you want to use it.  Then in the onItemChange event of the date field where you want to get the week number.

Example Use:

BO.F_weekNumber.setValue(app.getSharedData().getWeekNumberFromDate(BOA.getValue()));

Function:

// theDt - the business object of the date field (i.e. BOA, BO.F_Date1)
app.getSharedData().getWeekNumberFromDate = function(theDt) {
if(theDt !== "") {

// Create a copy of this date object
var t = new Date(theDt);

// ISO week date weeks start on monday so correct the day number
var dayNr = (t.getDay() + 6) % 7;

// Set the target to the thursday of this week so the target date is in the right year
t.setDate(t.getDate() - dayNr + 3);

// ISO 8601 states that week 1 is the week with january 4th in it
var jan4 = new Date(t.getFullYear(), 0, 4);

// Number of days between target date and january 4th
var dayDiff = (t - jan4) / 86400000;

// Calculate week number: Week 1 (january 4th) plus the number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
return weekNr; 
} else {
return "";
}
}

Get Days in Month

Description:

Given a date it will return the number of days in that month.

Function:

app.getSharedData().daysInThisMonth = function( date ) {

var calendarObj = new Array();

calendarObj.push({month: 0, days: 31});
calendarObj.push({month: 1, days: 28});
calendarObj.push({month: 2, days: 31});
calendarObj.push({month: 3, days: 30});
calendarObj.push({month: 4, days: 31});
calendarObj.push({month: 5, days: 30});
calendarObj.push({month: 6, days: 31});
calendarObj.push({month: 7, days: 31});
calendarObj.push({month: 8, days: 30});
calendarObj.push({month: 9, days: 31});
calendarObj.push({month: 10, days: 30});
calendarObj.push({month: 11, days: 31});

// Get the "non-Leap Year" number of days in the current month.
var month = date.getMonth(); // Returns [0-11]
var days = get( calendarObj, month ).days;

// Add one day to February, if this is a Leap Year.
if( month === "1" && app.getSharedData().isLeapYear( date ) ) {
days++;
}

return days;
}

Add Hours to TimeStamp

Description:

Add number of hours to a timestamp

Function:

// dateObj1 - The date field (i.e. BO.F_Date)
// numOfHours - The number of hours to add
app.getSharedData().addHoursToDate = function(dateObj1, numOfHours) {
    var d1 = dateObj1.getValue(); //get first date

    var d1_milli = d1.getTime();
    return new Date(Math.ceil(d1_milli + (1000 * 60 * 60 * numOfHours)));
}

Add Days To Date

Description:

Add number of days to a date. 

Usage Notes: 

Place the function in the Settings...Events...Custom actions.  In the field where you enter the date or the number of days to add you place: 

app.getSharedData().addDaysToDate(BO.F_Date, 90);

You can either hard-code the number of days to add or have the value come from a field.

Function:

// dateObj1 - The date field (i.e. BO.F_Date)
// numOfDays - The number of days to add
app.getSharedData().addDaysToDate = function(dateObj1, numOfDays) {
    var d1 = dateObj1.getValue(); //get first date

    var d1_milli = d1.getTime();
    return new Date(Math.ceil(d1_milli + (1000 * 60 * 60 * 24 * numOfDays)));
}

Add Working Days To Date

Description:

This function will return a new date with the number of specified working days added, it will not include weekends when determining the final date.  You will need to set that returned date into your desired field.

**Updated to account for holidays.  A new function was added to determine if a day was a registered holiday, which is now accounted for in the working day calculation.

 Usage Notes: 

Place the function in the Settings...Events...Custom actions.  In the field where you enter the date or the number of days to add.

You can either hard-code the number of days to add:

app.getSharedData().addWorkingDaysToDate(BO.F_Date, 90);

or have the value come from a field.

app.getSharedData().addWorkingDaysToDate(BO.F_Date, BO.F_Number.getValue());

To set another field with the result:

BO.F_newDate.setValue(app.getSharedData().addWorkingDaysToDate(BO.F_Date, 90));

Function:

app.getSharedData().isHoliday = function(d) {
  var r = false;
  var holidays = ["01-01","02-18","04-19","05-20","08-05","09-02"]; //set your holidays

  //check if any of the days is a holiday
  for(var holiday in holidays) {
    var h = new Date(get(holidays, holiday)+"-2020");

    if(d.getMonth() == h.getMonth() && d.getDay() == h.getDay()) {
      r = true;
    }
  }
  return r;
}

// dateObj1 - The date field (i.e. BO.F_Date)
// numOfDays - The number of working days to add
app.getSharedData().addWorkingDaysToDate = function(dateObj1, numOfDays) {

    var sd = dateObj1.getValue(); //get first date
    var ed = dateObj1.getValue();
    var counter = numOfDays;
    var millisecondsPerDay = 86400 * 1000;
    while (counter > 0) {
      ed = new Date(Math.ceil(ed.getTime() + millisecondsPerDay));
      var theDay = ed.getDay();

    //dont count sat and sunday and holidays
        if(theDay !== 0 && theDay !==6 && !app.getSharedData().isHoliday(ed)) {
            counter--;
        }    
    }

    return ed;    
}

Subtract Days From Date

Description:

Subtract number of days from a date

Function:

// dateObj1 - The date field (i.e. BO.F_Date)
// numOfDays - The number of days to subtract
app.getSharedData().subtractDaysFromDate = function(dateObj1, numOfDays) {
    var d1 = dateObj1.getValue(); //get first date
    var d1_milli = d1.getTime();
    return new Date(Math.ceil(d1_milli - (1000 * 60 * 60 * 24 * numOfDays)));
}

Subtract Working Days From Date

Description:

Subtract number of working days (not incl Sat or Sun) to a date.

Function:

// dateObj1 - The date field (i.e. BO.F_Date)
// numOfDays - The number of working days to subtract
app.getSharedData().subtractWorkingDaysFromDate = function(dateObj1, numOfDays) {
    var d1 = dateObj1.getValue(); //get first date
  var d2 = dateObj1.getValue();
    var counter = numOfDays;
    var millisecondsPerDay = 86400 * 1000;
    while (counter > 0) {
        d2 = new Date(Math.ceil(d2.getTime() - millisecondsPerDay));
    var theDay = d2.getDay();
    //dont count sat and sunday
        if(theDay !== 0 && theDay !==6) {
            counter--;
        }
    }
    return d2;    
}

Convert AD Date to Buddhist Date

Description:

Convert a standard AD date into a Buddhist Date

Usage:

Place in onLoad or beforeSubmit event to convert a date.  The code would be something like:

BO.F_DATETIME.setValue(app.getSharedData().convertToBuddhistDate(new Date()));

Function:

// dateAD: the date to convert
app.getSharedData().convertToBuddhistDate = function(dateAD){
    var dateBE = new Date(dateAD);
    dateBE.setFullYear(dateAD.getFullYear() + 543);
    return dateBE;
}

Calculate Age From Birth Date

Description:

Calculates the age from a specified birth date.

Usage:

Place function in Settings...Events...Custom Actions

BO.F_Number.setValue(app.getSharedData().getAgeFromBirthDate(BOA.getValue(), true));

BO.F_SingleLine.setValue(app.getSharedData().getAgeFromBirthDate(BOA.getValue(), false));


Function:

// birthDay - the date to calculate the age from
app.getSharedData().getAgeFromBirthDate = function(birthDay) {
  
 // 1557600000 is 24 * 3600 * 365.25 * 1000 Which is the length of a year
 // the length of a year is 365 days and 6 hours which is 0.25 day.
  // double tilde converts float to integer
  return ~~((Date.now() - birthDay) / (31557600000));

}

Verify Entered Date is After Today

Description:

This function will set the date field to invalid if the entered date is not after today.

Usage Notes: 

1. Copy the code to the Settings...Events...onStart section of your application.

// dateObj1 - the business object of the date field (i.e. BOA, BO.F_Date1)
// errorMsg - The message to display to the user when the field is set to invalid
app.getSharedData().isDateAfterToday = function(dateObj1, errorMsg) {

//get todays date, including the current time
   var today = new Date();       
var d = dateObj1.getValue(); //get date from passed object

//set the time of the date to just before midnight
   d.setSeconds(59);
    d.setMinutes(59);
    d.setHours(23);

//D1 MUST be less then today
   if(d < today) {
          dateObj1.setValid(false, errorMsg);
    } else {
      dateObj1.setValid(true, "");
    }
}

2. You can use this function in the date field itself or elsewhere.  You could use this in the onItemChange event of the date field by: 

app.getSharedData().isDateAfterToday(BOA, "The date must be after today.");

Or you could use this in a different event within a different item

app.getSharedData().isDateAfterToday(BO.F_Date1, "The date must be after today.");

Verify Entered Date is Before Today 

Description:

This function will set the date field to invalid if the entered date is not after today.

 Usage Notes: 

1. Copy the function to the Settings...Events...onStart section of your application.

// dateObj1 - the business object of the date field (i.e. BOA, BO.F_Date1)
// errorMsg - The message to display to the user when the field is set to invalid
app.getSharedData().isDateAfterToday = function(dateObj1, errorMsg) {
   //get todays date, including the current time
   var today = new Date();       
   var d = dateObj1.getValue(); //get date from passed object
   
   //set the time of the date to just before midnight
d.setSeconds(59);
    d.setMinutes(59);
    d.setHours(23);

   //D1 MUST be less then today
   if(d < today) {
          dateObj1.setValid(false, errorMsg);
    } else {
      dateObj1.setValid(true, "");
    }
}

2. You can use this function in the date field itself or elsewhere.  You could use this in the onItemChange event of the date field by:

app.getSharedData().isDateAfterToday(BOA, "The date must be after today.");

Or you could use this in a different event within a different item:

 app.getSharedData().isDateAfterToday(BO.F_Date1, "The date must be after today.");



Compare Date Fields (D2 must be greater than D1)

Description:

Given two dates the function will validate that they are numOfDays days apart.  If the dateObj2 is not numOfDays days greater than dateObj1 then dateObj2 will be set invalid with the specified errorMsg.

Usage Notes:

1. Copy the function to the Settings...Events...onStart section of your application.

// dateObj1 - the first date field (e.g. BO.F_Date1)
// dateObj2 - the second date field (e.g. BO.F_Date2)
// numOfDays - the number of days that D2 must be grater than D1
// errorMsg - The error message to display for D2 when invalid
app.getSharedData().compareDatesByDays = function(dateObj1, dateObj2, numOfDays, errorMsg) {

var d1 = dateObj1.getValue(); //get first date 
var d2 = dateObj2.getValue(); //get sec date
var diff = 0;

//convert to milliseconds
var d1_milli = d1.getTime();
var d2_milli = d2.getTime();

//get difference and convert back to days
var diff_milli = d2_milli - d1_milli;
var nDays = Math.ceil(diff_milli / 1000 / 60 / 60 / 24);

 //if the diff is less then numOfDays set the d2 field invalid
 if(nDays < numOfDays) {
    dateObj2.setValid(false, errorMsg);
  } else {
    dateObj2.setValid(true, "");
  }
}

2. Then in both of your date fields place this in the onItemChange event to
call the function (make sure you replace F_Date2 and F_Date3 with the IDs of your date fields):

app.getSharedData().compareDatesByDays(BO.F_Date2, BO.F_Date3, 14, "The date must be 14 days past D1.");


Calculate Working Days Between Dates 

Description:

Returns the number of calendar days between the two dates specified.  The function expects to receive date objects, not strings.

Usage Notes:

1. Copy the function to the Settings...Events...onStart section of your application.

app.getSharedData().includesHoliday = function (startDt, endDt) {
  
  var r = false;
  var holidays = ["01-01","02-18","04-19","05-20","08-05","09-02"];

  for(var holiday in holidays) {
    var h = new Date(get(holidays, holiday)+"-2020");

    if(h.getTime() >= startDt.getTime() && h.getTime() <= endDt.getTime()) {
      r = true;
    }
  }
  return r;
}

// includeWeekends - Pass true if you want to include weekends otherwise false.
app.getSharedData().workingDaysBetweenDates = function(startDt, endDt, includeWeekends) {
   // Validate input
   if (endDt < startDt)
       return 0;

   // Calculate days between dates
   var millisecondsPerDay = 86400 * 1000; // Day in milliseconds
   startDt.setHours(0,0,0,1);  // Start just after midnight
   endDt.setHours(23,59,59,999);  // End just before midnight
   var diff = endDt.getTime() - startDt.getTime();  // Milliseconds between datetime objects    
   var days = Math.ceil(diff / millisecondsPerDay);   

   if(!includeWeekends) {
       // Subtract two weekend days for every week in between
       var weeks = Math.floor(days / 7);
       var days = days - (weeks * 2);

       // Handle special cases
       var startDay = startDt.getDay();
       var endDay = endDt.getDay();

       // Remove weekend not previously removed.   
       if (startDay - endDay > 1) {       
         days = days - 2;     
      }

       // Remove start day if span starts on Sunday but ends before Saturday
      if (startDay === 0 && endDay !== 6) {
        days = days - 1;
      }

       // Remove end day if span ends on Saturday but starts after Sunday
      if (endDay === 6 && startDay !== 0) {
        days = days - 1; 
      }

      //subtract for any holiday included in the span
      if(app.getSharedData().includesHoliday(startDt, endDt)) {
        days = days - 1;
      }
    }
   return days;
}

2. We want to make sure that the result gets updated if the user changes either date field.  Therefore in your form of two date fields add the following to the onItemChange of both date fields:

var startDate = BO.F_Date.getValue();
var endDate = BO.F_Date0.getValue();
if(startDate !== null && startDate !== "" && endDate !== null && endDate !== "") {   
var days= app.getSharedData().workingDaysBetweenDates(startDate,endDate, true);
 BO.F_SingleLine.setValue(days);
}

This will insure that if either date field changes that the days between gets updated.  You will have to change the id references to match the fields on your form:

  • F_Date is the Start Date
  • F_Date0 is the End Date
  • F_SingleLine is the field that will hold the number of days returned from the function

Variant:

For the Variant, you will need to declare your holiday list:

var hol = new Array();
hol.push({title:'XMas',d: new Date('2015-12-25')});
hol.push({title:'Boxing Day',d: new Date('2015-12-28')});
hol.push({title:'New Years',d: new Date('2016-01-01')});

And then call the function:

var startDate = BO.F_Date.getValue();
var endDate = BO.F_Date0.getValue();
if(startDate !== null && startDate !== null) {   
  var days= app.getSharedData().workingDaysBetweenDates(startDate,endDate, true, hol);
   BO.F_Number1.setValue(days);
}

Variant Function:

app.getSharedData().workingDaysBetweenDates = function(startDt, endDt, includeWeekends, excludeHolidays) {
   // Validate input
   if (endDt < startDt)
       return 0;

   // Calculate days between dates
   var millisecondsPerDay = 86400 * 1000; // Day in milliseconds
   startDt.setHours(0,0,0,1);  // Start just after midnight
   endDt.setHours(23,59,59,999);  // End just before midnight
   var diff = endDt.getTime() - startDt.getTime();  // Milliseconds between datetime objects    
   var days = Math.ceil(diff / millisecondsPerDay);   

   if(!includeWeekends) {
       // Subtract two weekend days for every week in between
       var weeks = Math.floor(days / 7);
       var days = days - (weeks * 2);

       // Handle special cases
       var startDay = startDt.getDay();
       var endDay = endDt.getDay();

       // Remove weekend not previously removed.   
       if (startDay - endDay > 1)        
            days = days - 2;     

       // Remove start day if span starts on Sunday but ends before Saturday
       if (startDay === 0 && endDay !== 6)
            days = days - 1  

       // Remove end day if span ends on Saturday but starts after Sunday
      if (endDay === 6 && startDay !== 0)
           days = days - 1  
    }
   
   //remove any holidays that might be in the range
   if(excludeHolidays !== null) {
       for(var h=0; h<excludeHolidays.length;h++) {
           var th = get(excludeHolidays, h).d.getTime();
           
           if(th < endDt.getTime() && th > startDt.getTime()) {
                days--;
            }
        }
    }
   return days;

Get Month From Date

Description

Here is a function that when passed a date will return the month name.

Usage:

In the onClick event of a date field I can place the following to see the name of the month of the date selected.

alert(app.getSharedData().getMonthNameFromDate(BOA.getValue()));

Function:

// theDateField - pass it the date value like BO.F_Date.getValue()
app.getSharedData().getMonthNameFromDate = function(theDateField) {
var month = theDateField.getMonth();
var monthName = "";
 
switch (month) {
case 0:monthName = "January";
break;
case 1:monthName = "February";
break;
case 2:monthName = "March";
break;
case 3:monthName = "April";
break;
case 4:monthName = "May";
break;
case 5:monthName = "June";
break;
case 6:monthName = "July";
break;
case 7:monthName = "August";
break;
case 8:monthName = "September";
break;
case 9:monthName = "October";
break;
case 10:monthName = "November";
break;
case 11:monthName = "December";
break;
}
return monthName;
}