How to get the time and date in CET time zone in scoped application
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 hours ago
Hi All,
I would like the date and time to be converted in Scoped application below code is not working can you please help me.
The above Incident record created on the 2026-04-07 21:15:06 and output I am getting is Incident opened time in CET: 2026-04-07 19:15:06 (Actually it should be 17:45:06)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 hours ago
Hello Sai,
There are two separate issues here — one is a wrong API choice for timezone conversion in scoped apps, and the other explains why you are getting an unexpected offset.
Issue 1 — GlideScheduleDateTime is the Wrong API for Timezone Conversion
GlideScheduleDateTime is designed for schedule-based time calculations (working hours, SLAs), not straightforward timezone conversions. It is also not reliably available in all scoped app contexts.
The correct API for timezone conversion in a scoped application is GlideDateTime with getUserTimezone or using GlideTimeZone via the DateTimeUtil approach — but the simplest and most reliable method in scoped context is:
var grIncident = new GlideRecord('incident');
if (grIncident.get('sys_id', 'e8bfe5eac380cb9896985630a00131a2')) {
// Get the raw UTC value from the field
var gdtUTC = new GlideDateTime();
gdtUTC.setValue(grIncident.getValue('opened_at')); // getValue gives UTC string
// Convert to target timezone using GlideDateTime's built-in method
var formatter = new GlideDateTime();
formatter.setValue(gdtUTC.getValue());
// setTZ accepts IANA timezone names
formatter.setTZ(new Packages.java.util.TimeZone.getTimeZone('Europe/Paris')); // CET = Europe/Paris
gs.info('Incident opened time in CET: ' + formatter.getDisplayValue());
}
Issue 2 — Why You Are Getting the Wrong Offset
Your record was created at 2026-04-07 21:15:06 and you expected 22:15:06 CET (UTC+1) or 23:15:06 CEST (UTC+2), but you got 19:15:06 which is actually going backwards — this means the API was applying an offset in the wrong direction or using a wrong base timezone.
The core problem is that grIncident.opened_at when passed directly into new GlideDateTime() may be returning the display value in the instance's local timezone rather than raw UTC, causing a double-offset calculation.
Always use getValue() to get the raw UTC string:
// ❌ Wrong — may pass display value (already offset from UTC)
var gdt = new GlideDateTime(grIncident.opened_at);
// ✅ Correct — gets raw UTC value guaranteed
var gdt = new GlideDateTime();
gdt.setValue(grIncident.getValue('opened_at'));
Issue 3 — CET vs CEST
April 7 2026 is in British Summer Time / Central European Summer Time territory. CET is UTC+1 in winter, but in April Europe uses CEST which is UTC+2. If your record is 21:15:06 UTC, the correct CET/CEST display should be 23:15:06 CEST.
Using the IANA name Europe/Paris or Europe/Berlin automatically handles the DST switch, whereas hardcoding "CET" as a string does not — it stays at UTC+1 year-round.
Complete Corrected Script
var grIncident = new GlideRecord('incident');
if (grIncident.get('sys_id', 'e8bfe5eac380cb9896985630a00131a2')) {
// Step 1 — Get raw UTC value (never use field reference directly)
var utcValue = grIncident.getValue('opened_at');
gs.info('Raw UTC value from record: ' + utcValue);
// Step 2 — Load into GlideDateTime as UTC
var gdtUTC = new GlideDateTime();
gdtUTC.setValue(utcValue);
gs.info('Confirmed UTC time: ' + gdtUTC.getDisplayValue());
// Step 3 — Convert to CET/CEST using IANA timezone name
// Europe/Paris and Europe/Berlin both honour CET/CEST DST automatically
var javaTimeZone = Packages.java.util.TimeZone.getTimeZone('Europe/Paris');
gdtUTC.setTZ(javaTimeZone);
// Step 4 — Display converted time
var cetTime = gdtUTC.getDisplayValue();
gs.info('Incident opened time in CET/CEST: ' + cetTime);
}
Expected output for your record:
Raw UTC value from record: 2026-04-07 21:15:06
Confirmed UTC time: 2026-04-07 21:15:06
Incident opened time in CET/CEST: 2026-04-07 23:15:06
Why Each Change Was Made
| Problem | Old code | Fixed code |
|---|---|---|
| Wrong API for scoped timezone conversion | GlideScheduleDateTime |
GlideDateTime.setTZ() |
| Possible double-offset from display value | grIncident.opened_at |
grIncident.getValue('opened_at') |
| DST not handled — fixed UTC+1 year-round | "CET" string |
'Europe/Paris' IANA name |
| Offset applied in wrong direction | Base timezone ambiguous | Explicit UTC load via setValue() |
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
8m ago
Hi Pavan,
getting the below error while running the code.
Error Description: Use of Packages calls is not permitted in scoped applications,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
31 seconds ago
This is a known scoped app restriction. The fix is straightforward — replace the Packages.java call with ServiceNow's native scoped-safe timezone conversion method.
Why It Fails in Scoped Apps
Packages.java.util.TimeZone is a direct Java class call and ServiceNow blocks all Packages.* calls in scoped applications for security isolation reasons. You need a purely ServiceNow-native approach.
Scoped App Safe Solution
var grIncident = new GlideRecord('incident');
if (grIncident.get('sys_id', 'e8bfe5eac380cb9896985630a00131a2')) {
// Step 1 — Get raw UTC value safely
var utcValue = grIncident.getValue('opened_at');
gs.info('Raw UTC value: ' + utcValue);
// Step 2 — Load into GlideDateTime as UTC
var gdtUTC = new GlideDateTime();
gdtUTC.setValue(utcValue);
// Step 3 — Use GlideDateTime.convertTimeZone() — fully scoped app safe
// This is the correct scoped-safe alternative to Packages.java
var gdtCET = new GlideDateTime();
gdtCET.setValue(utcValue);
gdtCET.convertTimeZone('UTC', 'Europe/Paris'); // handles CET/CEST DST automatically
// Step 4 — Display result
gs.info('Incident opened time in CET/CEST: ' + gdtCET.getDisplayValue());
}
Expected output for your record:
Raw UTC value: 2026-04-07 21:15:06
Incident opened time in CET/CEST: 2026-04-07 23:15:06
Why convertTimeZone() Works Here
| Method | Scoped App Safe | Handles DST | Notes |
|---|---|---|---|
Packages.java.util.TimeZone |
❌ Blocked | ✅ | Not usable in scoped apps |
GlideScheduleDateTime.setTimeZone() |
⚠️ Partial | ❌ | Wrong API for this purpose |
GlideDateTime.convertTimeZone() |
✅ Yes | ✅ | Correct scoped-safe method |
convertTimeZone(fromTZ, toTZ) takes two IANA timezone name strings and converts in place — it is fully supported in scoped applications and correctly handles DST transitions, so April dates automatically use CEST (UTC+2) rather than CET (UTC+1).
If You Need the Value as a String for Further Processing
// Get individual components after conversion if needed
var displayValue = gdtCET.getDisplayValue(); // "2026-04-07 23:15:06"
var dateOnly = gdtCET.getDate().getDisplayValue(); // "2026-04-07"
var timeOnly = gdtCET.getTime().getDisplayValue(); // "23:15:06"
gs.info('Date: ' + dateOnly);
gs.info('Time: ' + timeOnly);
