duration calcuation with a schedule

RBlor
Mega Guru

I am trying to write a business rule for the problem table that works for the most part but I need some help for part of it. The goal is to create a business rule for the problem table that updates the two duration fields, Outage Duration (Business Hours) | u_outage_duration_business_hours and Elapsed Outage Duration (includes Non-Business Hours) ! u_elapsed_outage_duration when the date/time fields Incident Start Date/Time* ! u_incident_start_date_time and Incident End Date/Time** ! u_incident_end_date_time are filled in . The schedule to use has the sysid of var scheduleId = 'c271af3edb0ff300557f5878dc96194e';

condition: 

current.u_incident_start_date_time.changes() ||
current.u_incident_end_date_time.changes()

(function executeRule(current, previous) {
    // Clear if either time is missing
    if (current.u_incident_start_date_time.nil() || current.u_incident_end_date_time.nil()) {
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        return;
    }

    var startGdt = new GlideDateTime(current.u_incident_start_date_time);
    var endGdt   = new GlideDateTime(current.u_incident_end_date_time);

    // Validate End >= Start and block save if invalid
    if (endGdt.getNumericValue() < startGdt.getNumericValue()) {
        gs.addErrorMessage('Incident End Date/Time cannot be before Incident Start Date/Time.');
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        current.setAbortAction(true);
        return;
    }

    // Elapsed (all hours)
    var totalMs = endGdt.getNumericValue() - startGdt.getNumericValue();
    var elapsedDur = new GlideDuration();
    elapsedDur.setNumericValue(totalMs);
    current.u_elapsed_outage_duration = elapsedDur;

    // Business-hours using your schedule
    var schedule = new GlideSchedule('c271af3edb0ff300557f5878dc96194e'); // or .load(sys_id)
    var businessMs = schedule.duration(startGdt, endGdt);

    var businessDur = new GlideDuration();
    businessDur.setNumericValue(businessMs);
    current.u_outage_duration_business_hours = businessDur;


})(current, previous);

RBlor_0-1762388444355.png

 

The problem I am encountering is that it updates the u_elapsed_outage_duration just fine, but does not update the u_outage_duration_business_hours, which checks the schedule. Can anyone assist?

1 ACCEPTED SOLUTION

RBlor
Mega Guru

to those looking for an answer : 

(function executeRule(current, previous) {
    // Clear if either time is missing
    if (current.u_incident_start_date_time.nil() || current.u_incident_end_date_time.nil()) {
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        return;
    }

    var startGdt = new GlideDateTime(current.u_incident_start_date_time);
    var endGdt   = new GlideDateTime(current.u_incident_end_date_time);

    // Validate End >= Start and block save if invalid
    if (endGdt.getNumericValue() < startGdt.getNumericValue()) {
        gs.addErrorMessage('Incident End Date/Time cannot be before Incident Start Date/Time.');
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        current.setAbortAction(true);
        return;
    }

    // --- Elapsed (all hours) ---
    var totalMs = endGdt.getNumericValue() - startGdt.getNumericValue();
    current.u_elapsed_outage_duration.setDateNumericValue(totalMs);

    // --- Business-hours using your schedule ---
    var scheduleId = 'c271af3edb0ff300557f5878dc96194e';
    var dc = new DurationCalculator();
    dc.setSchedule(scheduleId);
    dc.calcScheduleDuration(startGdt, endGdt);
    
    var businessMs = dc.getSeconds() * 1000;
    current.u_outage_duration_business_hours.setDateNumericValue(businessMs);

})(current, previous);

View solution in original post

4 REPLIES 4

J Siva
Kilo Patron
Kilo Patron

Hi @RBlor 

 

You can directly assign the duration value without converting them into Numeric value. Also, mention the timezone as mentioned below if possible.

    // Business-hours using your schedule
    var schedule = new GlideSchedule('c271af3edb0ff300557f5878dc96194e',<Time Zone>);  // Ex: Australia/Perth
    var businessMs = schedule.duration(startGdt, endGdt);

    current.u_outage_duration_business_hours = businessMs ;

 Regards,
Siva

Ankur Bawiskar
Tera Patron
Tera Patron

@RBlor 

try this

// Business-hours using your schedule
    var schedule = new GlideSchedule('c271af3edb0ff300557f5878dc96194e'); // or .load(sys_id)
    var businessMs = schedule.duration(startGdt, endGdt);

    current.u_outage_duration_business_hours.setDateNumericValue( businessMs..getNumericValue());

You will find many OOTB business rules with this logic

AnkurBawiskar_0-1762399520721.png

 

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Thank you for your help. Still having issues. 
So I got the other field updating like before, no issue, but the business hrs duration field is still not working. Can you review and point out anything? I confirmed the sysid from the cmn_schedule record is correct.

 

// Business Rule: Before Insert/Update on problem
// Condition (advanced):
// current.operation() == 'insert' || current.u_incident_start_date_time.changes() || current.u_incident_end_date_time.changes()

(function executeRule(current, previous) {
    // Clear if either time is missing
    if (current.u_incident_start_date_time.nil() || current.u_incident_end_date_time.nil()) {
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        return;
    }

    var startGdt = new GlideDateTime(current.u_incident_start_date_time);
    var endGdt   = new GlideDateTime(current.u_incident_end_date_time);

    // Validate End >= Start and block save if invalid
    if (endGdt.getNumericValue() < startGdt.getNumericValue()) {
        gs.addErrorMessage('Incident End Date/Time cannot be before Incident Start Date/Time.');
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        current.setAbortAction(true);
        return;
    }

    // --- Elapsed (all hours) ---
    var totalMs = endGdt.getNumericValue() - startGdt.getNumericValue();
    // Write milliseconds directly to the Duration field
    current.u_elapsed_outage_duration.setDateNumericValue(totalMs);

    // --- Business-hours using your schedule ---
    var schedule = new GlideSchedule('c271af3edb0ff300557f5878dc96194e'); // or .load(sys_id)
    var businessMs = schedule.duration(startGdt, endGdt); // milliseconds inside schedule
    current.u_outage_duration_business_hours.setDateNumericValue(businessMs);


})(current, previous);

 

RBlor
Mega Guru

to those looking for an answer : 

(function executeRule(current, previous) {
    // Clear if either time is missing
    if (current.u_incident_start_date_time.nil() || current.u_incident_end_date_time.nil()) {
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        return;
    }

    var startGdt = new GlideDateTime(current.u_incident_start_date_time);
    var endGdt   = new GlideDateTime(current.u_incident_end_date_time);

    // Validate End >= Start and block save if invalid
    if (endGdt.getNumericValue() < startGdt.getNumericValue()) {
        gs.addErrorMessage('Incident End Date/Time cannot be before Incident Start Date/Time.');
        current.u_outage_duration_business_hours = '';
        current.u_elapsed_outage_duration = '';
        current.setAbortAction(true);
        return;
    }

    // --- Elapsed (all hours) ---
    var totalMs = endGdt.getNumericValue() - startGdt.getNumericValue();
    current.u_elapsed_outage_duration.setDateNumericValue(totalMs);

    // --- Business-hours using your schedule ---
    var scheduleId = 'c271af3edb0ff300557f5878dc96194e';
    var dc = new DurationCalculator();
    dc.setSchedule(scheduleId);
    dc.calcScheduleDuration(startGdt, endGdt);
    
    var businessMs = dc.getSeconds() * 1000;
    current.u_outage_duration_business_hours.setDateNumericValue(businessMs);

})(current, previous);