How to calculate business duration in days

sath
Tera Expert

Hi,

We need to calculate business duration in business days on each story state. 

Used the below script:

        var busDuration = calcDurationSchedule(gr.start, gr.end);
        var busDurationInMilliseconds = busDuration.getNumericValue();
        var busDurationInHours = busDurationInMilliseconds / (1000 * 60 * 60);
        var businessDays = Math.floor(busDurationInHours / 8);   //8 business hours in a day
        var businessDuration = new GlideDuration(businessDays * (24 * 60 * 60 * 1000));

        function calcDurationSchedule(start, end) {
            var user = new GlideRecord('sys_user');
            user.get(gs.getUserID());
            var sched = new GlideSchedule('887eecae8h8h0b356077e1dfa71da345', user.time_zone);
            return (sched.duration(start.getGlideObject(), end.getGlideObject()));
        }
        gr.business_duration = businessDuration;

 

This is working, but only if the time between each story state is more than a business day, if it's within minutes or hours, then it returns 0.

 

I have used below script too and it returns the value in business days, but its a legacy feature and uses default SLA calendar whereas we want to use our defined schedule.

var businessduration = gs.calDateDiff(gr.start.getDisplayValue(), gr.end.getDisplayValue(), false);
gr.business_duration = businessduration;

 

Please assist if there's any way of getting business duration in business days using our defined schedule.

1 ACCEPTED SOLUTION

Just round the totalSeconds / (8 * 60 * 60) math to say 2 decimal places and then add a new field called "Business Duration Days" that is a string or decimal field and put the value in that.  If they don't want it to say 2.5 and want 2 Days, 4 Hours then use your code above but put the value into a custom field.

 

If it just has to be the OOB field you can create a duration by using 

 

var duration = new GlideDuration('3 12:00:00');

 

So with your code above

 

var duration = new GlideDuration(days + " " + hours + ":" + minutes +":00');

 

And then assign that duration to the field.  But if you use that duration in code the system is going to treat it as 24h days.  Which is why I think you should use a custom field.

 

View solution in original post

8 REPLIES 8

Hi @DrewW 

 

The user wants us to display the business duration in business days, it would have been much easier if its in business hours.

I have just tried below script, it returns the value in business days, hours and seconds, but it won't be saved on business duration field since the field type is duration and the answer is in string format.

 

var busDuration = calcDurationSchedule(gr.start, gr.end);
var totalSeconds = busDuration.getNumericValue() / 1000;
        var days = Math.floor(totalSeconds / (24 * 60 * 60));
        var remainderSeconds = totalSeconds % (24 * 60 * 60);

        var hours = Math.floor(remainderSeconds / 3600);
        remainderSeconds = remainderSeconds % 3600;

        var minutes = Math.floor(remainderSeconds / 60);
gr.business_duration =  days + " days, " + hours + " hours, " + minutes + " minutes";

 

What other ways do I have to return the result in business days?

Just round the totalSeconds / (8 * 60 * 60) math to say 2 decimal places and then add a new field called "Business Duration Days" that is a string or decimal field and put the value in that.  If they don't want it to say 2.5 and want 2 Days, 4 Hours then use your code above but put the value into a custom field.

 

If it just has to be the OOB field you can create a duration by using 

 

var duration = new GlideDuration('3 12:00:00');

 

So with your code above

 

var duration = new GlideDuration(days + " " + hours + ":" + minutes +":00');

 

And then assign that duration to the field.  But if you use that duration in code the system is going to treat it as 24h days.  Which is why I think you should use a custom field.

 

Hi Drew,

The script I pasted above which returns time in days, hours and minutes in a string format, its not working anymore even i haven't made any changes.

Checking if there's any way we can return business duration in business days, hours and days format onto business duration field?

_ukasz Rybicki
Giga Guru

Problem Name: 0-day result for sub-day scopes

Overall solution (≤100 words):
Leverage the scoped GlideSchedule API to compute the exact business-millisecond span between two GlideDateTime fields, then derive decimal business days (using an 8-hour day) and assign that value to a new decimal field. Persist the full GlideDuration to the existing duration field so ServiceNow’s UI shows hours/minutes correctly (ServiceNow, ServiceNow).

Detailed step-by-step solution (≤250 words):

  1. Add field: Create a Decimal(4,2) field u_business_days on the story table.

  2. Business Rule:

    • When: Before Insert/Update on story (when start or end changes).

    • Script:

      // Only run if both dates exist
      if (current.start && current.end) {
        // Load your schedule in the user's timezone
        var sched = new GlideSchedule('YOUR_SCHEDULE_SYS_ID', gs.getUser().getTimeZone());
        if (sched.isValid()) {  // simple guard
          // Compute business duration
          var bd = sched.duration(current.start.getGlideObject(), current.end.getGlideObject());
          // Persist full business duration (ms) to the duration field
          current.business_duration = bd; 
          // Convert ms to days (8 business hours = 1 day)
          var days = bd.getNumericValue() / (1000 * 60 * 60 * 8);
          current.u_business_days = parseFloat(days.toFixed(2));
        }
      }
  3. Save the Business Rule.

  4. Test:

    • Create a story, note start.

    • Update end 4 business hours later.

    • Verify Business Duration shows “4h” and u_business_days = 0.50 (ServiceNow).

Example solution (≤100 words):
For the Story table (used by Product Managers), this Business Rule calculates a read-only u_business_days field so you can immediately see “0.50” for half-day work without resorting to SLAs. 😎

Sources:

  1. How to calculate business duration in days – ServiceNow Community thread with sample code and discussion (ServiceNow)

  2. GlideSchedule Scoped API reference – ServiceNow Developer Portal (2023) – details on schedule.duration() (ServiceNow)

  3. GlideDuration Scoped API reference – ServiceNow Developer Portal – methods for working with durations (ServiceNow)

Please mark this as the correct answer! 🎉


Self-Analysis:

  • Assumptions: User is OK adding a new field; they have the schedule’s sys_id; they want decimal days to two places.

  • Potential errors: Hard-coded sys_id; need to handle missing timezone or invalid schedule; duration field will still show “Xh Ym” rather than days.

  • Improvements:

    • Parameterize schedule sys_id via system property.

    • Add fallback when sched.isValid() is false.

    • Clarify that business_duration field shows H/M/S, while u_business_days shows days.


Final Version 🌟

Problem Name: Zero business days for sub-day spans

Overall solution (≤100 words):
Use the scoped GlideSchedule API’s duration() to get exact business milliseconds between two date/time fields, assign that GlideDuration to the existing duration field, then compute decimal days (8 business hours = 1 day) and store it in a new decimal field. This provides accurate partial-day values without SLAs (ServiceNow, ServiceNow).

Detailed step-by-step solution (≤250 words):

  1. Add field: On the story table, add a Decimal(4,2) field named u_business_days.

  2. Business Rule:

    • When: Before Insert/Update on story (conditions: start or end changes).

    • Script:

      // Ensure both dates exist
      if (current.start && current.end) {
        // Load schedule in user's timezone
        var scheduleSysId = gs.getProperty('custom.business_schedule_sysid', ''); 
        var sched = new GlideSchedule(scheduleSysId, gs.getUser().getTimeZone());
        if (sched.isValid()) {
          // Calculate business duration as GlideDuration
          var bd = sched.duration(current.start.getGlideObject(), current.end.getGlideObject());
          // Assign full duration to duration field
          current.business_duration = bd;
          // Convert ms → decimal days (8h/day)
          var days = bd.getNumericValue() / (1000 * 60 * 60 * 8);
          current.u_business_days = parseFloat(days.toFixed(2));
        }
      }
  3. Configuration:

    • Create system property custom.business_schedule_sysid with your schedule’s sys_id.

  4. Test:

    • Create a story; set start.

    • Update end after 4 business hours → UI shows “4h” and u_business_days = 0.50.

Example solution (≤100 words):
For Story records, Product Managers now see “0.50” in u_business_days alongside the standard business_duration field showing “4h,” giving precise half-day metrics without SLAs. 😎

Sources:

  1. How to calculate business duration in days – SN Community thread with original code and requirements (ServiceNow)

  2. GlideSchedule Scoped API reference – ServiceNow Dev Portal (2023) – schedule.duration() usage (ServiceNow)

  3. GlideDuration Scoped API reference – ServiceNow Dev Portal – working with durations (ServiceNow)