Nathan Sanders
Software / Web / Data
Using GlideSchedule to create events in the future with DST
I recently encountered a problem while setting a fixed time for future events in a script. The issue arose when dealing with daylight saving time (DST) – the time was incorrectly skewed by one hour. The user interface (UI) functions as expected, allowing you to set a time in the future and correctly assigning the time zone (TZ) and DST offset to the value, which is then saved as a UTC DateTime value. However, when using the GlideSchedule function to retrieve a range of dates, the time zone is taken into account but the DST offset is not.
I attempted to solve the problem by migrating all the time zones to the “Country/City” format, as there is a knowledge base (KB) article from ServiceNow (SN) that states DST is not accounted for in the old time zones. However, I later found another KB article that indicates they are linked. Changing the time zone did not resolve the issue, and I eventually determined that the problem was on the script side – even though a time zone with DST is provided, the system does not automatically add the offset to the values.
I hope this information is helpful to others who may encounter a similar problem in the future. It is important to carefully consider time zones and DST offsets when working with dates and times in scripts to ensure accurate results.
Competing KB’s:
https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0594661
https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0960564
Excerpt from my large Script Include, this is what takes the GlideDateTime object in and spits a DST-corrected GlideDtateTime object out:
setDstOffset: function(time) {
// Make sure we account for DST
var dstOffset = (-Number(time.getDSTOffset() / 1000));
time.addSeconds(dstOffset);
return time;
Where I’m creating the timespan and calling the DST function:
refreshTasksInSchedule: function(spansStart, spansEnd, schedule, template, newTask_ID) {
if (!spansStart || !spansEnd)
return;
var timeMap = schedule.getTimeMap(spansStart, spansEnd);
timeMap.buildMap(schedule.getTimeZone());
// Skip the first element in the timeMap if it spans now
if (schedule.isInSchedule(new GlideDateTime()) && timeMap.hasNext() && !newTask_ID) {
timeMap.next();
}
var timeSpan;
while (timeMap.hasNext()) {
count += 1;
timeSpan = timeMap.next();
var start = timeSpan.getStart().getGlideDateTime();
var end = timeSpan.getEnd().getGlideDateTime();
var today = new GlideDateTime(gs.endOfToday());
if (start >= today){
var newTaskID = this.refreshTask(template, start, end, newTask_ID);
...
}
}
},
refreshTask: function(template, start, end, newTask_ID) {
var timeZone = Packages.java.util.TimeZone.getTimeZone(template.u_time_zone);
var startDate = new GlideDateTime(start);
startDate.addSeconds(this.getTzOffsetSeconds(timeZone));
// Setting DST offset for time
startDate = this.setDstOffset(startDate);
var endDate = new GlideDateTime(end);
endDate.addSeconds(this.getTzOffsetSeconds(timeZone));
// Setting DST offset for time
endDate = this.setDstOffset(endDate);
...
}