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; }