Problem Description: RD_SYS_T Output Does Not Match TIA Portal Display
When an engineer reads the system time on a SIMATIC S7-1200 or S7-1500 CPU using the RD_SYS_T (Read time-of-day) instruction, the value at output OUT appears to be incorrect: it is several hours behind the time shown in TIA Portal under Online & Diagnostics > CPU > Time. Typical offsets reported in the field are 1 hour, 2 hours, 3 hours, or even odd half-hour offsets depending on the project location (e.g. UTC+05:30 for India, UTC+05:45 for Nepal).
The symptom is most often reported as a "RD_SYS_T ERROR" or "wrong time on the HMI", but the value is not an error code. The RD_SYS_T block returns a valid DTL (date-and-time-long) value; the engineer is simply misinterpreting what the value represents.
Field Example
- CPU model: S7-1515-2 PN (6ES7515-2AM02-0AB0), firmware V2.9
- CPU clock configured for: (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
- Daylight saving: Europe start/end rules enabled
- NTP server: pool.ntp.org, synchronization every 60 s
- TIA Portal HMI panel (KTP1200) shows: 12:36:00 local time
-
RD_SYS_T.OUTshows: 09:36:00 (3 hours earlier)
The 3-hour difference is not a bug, not a hardware defect, and not a programming mistake. It is the documented behavior of RD_SYS_T for the S7-1200/S7-1500 system.
Root Cause: RD_SYS_T Always Returns UTC, Not Local Time
Per the official Siemens documentation, RD_SYS_T reads the current date and time-of-day of the CPU clock as a module time. On the S7-1200 and S7-1500 platforms, the module time is stored and returned in UTC (Coordinated Universal Time), also historically called GMT. The instruction does not apply the CPU's configured time zone, nor does it apply daylight saving time (DST) conversion.
RD_SYS_T on S7-1200/S7-1500 returns UTC regardless of the time zone and DST settings in the CPU properties. This is the documented behavior in TIA Portal V15.1 through V20, and it applies to every S7-1200 firmware >= V4.0 and every S7-1500 firmware >= V1.0.
The TIA Portal Online & Diagnostics view, on the other hand, takes the raw module time and renders it in the local time zone of the engineering PC (or, more precisely, the time zone configured in the project under Languages & Resources > Time). That is why the online display and the tag value visible in the watch table appear to disagree by exactly the value of the time-zone offset plus the DST delta.
Reference Documentation
- RD_SYS_T: Read time-of-day – SIMATIC STEP 7 Basic/Professional V15.1 manual entry (Siemens Support, ID 109773506)
- RD_SYS_T: Read time-of-day (S7-1200, S7-1500) – TIA Portal V20 Online Help
Technical Details: Instruction Interface and DTL Output
The RD_SYS_T block resides in the TIA Portal instruction palette under Extended instructions > Date and time-of-day > Time-of-day functions. Its interface is identical on every S7-1200 and S7-1500 firmware.
| Parameter | Declaration | Data Type | Description |
|---|---|---|---|
| EN | Input | BOOL | Enable input; rising edge triggers the read |
| ENO | Output | BOOL | Enable output; 1 = success, 0 = error (CPU in STOP, no valid time, etc.) |
| OUT | Output | DTL | Current date and time in UTC |
| RET_VAL | Output (S7-300/400 only) | INT | Error code (see below); not present on S7-1200/S7-1500 |
The DTL structure has the following layout (16 bytes total):
| Byte | Component | Type | Range / Meaning |
|---|---|---|---|
| 0 | YEAR | UINT | 1970 to 2554 |
| 2 | MONTH | USINT | 1 to 12 |
| 3 | DAY | USINT | 1 to 31 |
| 4 | WEEKDAY | USINT | 1 (Sunday) to 7 (Saturday) |
| 5 | HOUR | USINT | 0 to 23 (UTC) |
| 6 | MINUTE | USINT | 0 to 59 |
| 7 | SECOND | USINT | 0 to 59 |
| 8..11 | NANOSECOND | UDINT | 0 to 999,999,999 |
| 12..15 | reserved | - | Always 0 |
Because the HOUR field is already in UTC, an engineer who feeds it directly to an HMI tag (e.g. "DB_Time".systemTime.HOUR) will display UTC on the panel, not local time. The same is true for the S7-1500 web server time tag, OPC UA nodes of type DateTime, and any WinCC faceplate bound to the raw DTL.
S7-300 / S7-400 Behavior and RET_VAL Error Codes
On the older S7-300 and S7-400 platforms, RD_SYS_T uses the Date_And_Time (DT) BCD format and provides a RET_VAL word. Behavior differs from the S7-1200/S7-1500 in two important ways:
- The output is local time by default (the CPU's local time zone, configured in STEP 7 HW Config under CPU properties > Time of Day). This is one of the most common cross-platform confusion points during migration projects.
- If the output buffer is the wrong data type, or if the CPU is in STOP, an error code is returned in
RET_VAL.
| RET_VAL (hex) | Meaning |
|---|---|
| 0000 | No error |
| 8080 | Date/time cannot be saved in the specified data type |
| 80A0 | The value at the OUT parameter cannot be set (e.g. invalid target area) |
| 8xxy | General error (xx = error class, y = error number; see STEP 7 system software manual) |
For the official description on the S7-300/400, see RD_SYS_T: Read time-of-day (S7-300, S7-400) – TIA Portal V20 Online Help. When migrating S7-300/400 code to S7-1500, plan for the time-zone change explicitly: any program that was happy with local time on S7-300 will see a shifted value on S7-1500 after migration.
Solution 1: Use RD_LOC_T for Local Time
The S7-1500 (firmware V2.0 and later) and the S7-1200 (firmware V4.2 and later) provide the instruction RD_LOC_T (Read local time-of-day), which returns the CPU clock converted to the local time zone and DST offset defined in the device configuration. This is the correct instruction to use when the application, the HMI, or the SCADA expects the operator's wall-clock time.
RD_LOC_T Interface
| Parameter | Declaration | Type | Description |
|---|---|---|---|
| EN | Input | BOOL | Enable input; rising edge triggers the read |
| ENO | Output | BOOL | Enable output |
| OUT | Output | DTL | Local date and time-of-day (UTC + configured offset + DST) |
Example LAD/FBD call (single-instance DB) in TIA Portal V18+:
// Call RD_LOC_T once per second from a cyclic OB (e.g. OB1)
CALL "RD_LOC_T" , %DB100
EN := TRUE
ENO => #ok
OUT => "HMI".localTime // DTL, e.g. 2024-06-15-12:36:00.000
When the CPU is configured for (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna with European DST rules, RD_LOC_T.OUT in June returns the correct local time even though the CPU's internal UTC clock is one or two hours behind it.
Solution 2: Apply the Time-Zone Offset Manually in the PLC
On S7-1200 firmware < V4.2 and on S7-1500 firmware < V2.0, RD_LOC_T is not available. In those cases, derive local time from RD_SYS_T by adding the project-specific offset and DST bit. A simple SCL implementation:
// FB_LocalTime - convert RD_SYS_T (UTC) to local time
// Inputs: iUtc DTL from RD_SYS_T.OUT
// iOffsetMin INT offset in minutes incl. DST (e.g. 180 for UTC+3 summer)
// Output: oLocal DTL
// Author: automation engineer notes
FUNCTION_BLOCK "FB_LocalTime"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iUtc : DTL;
iOffsetMin : INT;
END_VAR
VAR_OUTPUT
oLocal : DTL;
END_VAR
VAR
secSinceEpoch : DINT;
tDT : DATE_AND_TIME;
END_VAR
BEGIN
// Convert DTL to seconds since 1970-01-01 00:00:00 UTC
secSinceEpoch := DAT_TO_DINT( DT_DAYS( DTL_TO_DATE(iUtc) ) ) * 86400
+ DWORD_TO_DINT( iUtc.HOUR ) * 3600
+ DWORD_TO_DINT( iUtc.MINUTE ) * 60
+ DWORD_TO_DINT( iUtc.SECOND );
// Add the offset (can be negative for west of UTC)
secSinceEpoch := secSinceEpoch + INT_TO_DINT(iOffsetMin) * 60;
// Convert back to DT (BCD) then to DTL
tDT := DINT_TO_DT( secSinceEpoch );
oLocal := DT_TO_DTL( tDT );
END_FUNCTION_BLOCK
iOffsetMin value. For DST-aware systems, swap the value at the configured DST changeover timestamps, or replace it with a tag driven by the CPU's "Time-of-day is daylight saving time" system bit (S7-1500 only, see System clock > Status).
CPU Clock Configuration in TIA Portal
The local-time behavior of RD_LOC_T and the online display depends on three parameters set in the device configuration of the CPU. Open Project tree > PLC_x > Device configuration > Properties > General > Time of day and verify the following:
-
Time zone – select the entry that matches the plant's standard time, e.g. (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna. The setting applies to the time the CPU uses for local-time functions; it does not change the UTC value returned by
RD_SYS_T. - Daylight saving time (DST) – enable the regional rule that matches local legislation, e.g. Europe: last Sunday in March 02:00 to last Sunday in October 03:00. The CPU automatically advances the local time by one hour on the changeover.
-
NTP synchronization – under Properties > General > Time of day > NTP, enable the NTP client and point it at one or more NTP servers (e.g.
pool.ntp.org, or a plant-local NTP appliance). The synchronization interval defaults to 10 s on S7-1500 and is typically set to 60–600 s in production. Without NTP, drift of the CPU's RTC is on the order of a few seconds per day.
The NTP server itself always returns UTC. The CPU is responsible for converting UTC to local time when RD_LOC_T is called or when time-related system services are queried. The NTP setting on the engineering PC (and on the TIA Portal PC) is independent; it controls only how the Online & Diagnostics view renders the value.
Comparing RD_SYS_T, RD_LOC_T and WR_SYS_T
| Instruction | Platforms | Returns | DST / TZ applied? | Typical Use Case |
|---|---|---|---|---|
| RD_SYS_T | S7-1200/1500/300/400 | Module time (UTC on S7-1200/1500, local on S7-300/400) | No (on S7-1200/1500) | Time-stamping audit logs, OPC UA DateTime tags, UTC time source for downstream gateways |
| RD_LOC_T | S7-1500 >= V2.0, S7-1200 >= V4.2 | Local time-of-day (DTL) | Yes | HMI time display, shift-logic, operator-facing screens, scheduled tasks |
| WR_SYS_T | S7-1200/1500/300/400 | Writes UTC to module time (S7-1200/1500) | No | Forcing CPU RTC, restoring time after battery replacement |
| SET_TIMEZONE | S7-1500 only | Sets TZ rule programmatically | - | Mobile machinery that crosses time zones |
The pattern in well-designed S7-1500 programs is: RD_SYS_T drives a UTC tag, RD_LOC_T drives the HMI. Both are written to separate data blocks so OPC UA consumers and operators never accidentally read the same value for two different meanings.
Verification Steps After Applying the Fix
-
Watch-table test. Create a watch table with the
RD_SYS_Tinstance DB and theRD_LOC_Tinstance DB. TriggerRD_LOC_Twith a 1-Hz pulse from a clock memory bit (e.g.Clock_1Hz). Confirm thatRD_LOC_T.OUT.HOURmatches the time shown in the TIA Portal Online & Diagnostics > Time view. -
DST changeover test. Either wait for the next real changeover or, in the lab, force the CPU clock forward by 30 minutes with Online & Diagnostics > Set time, observe whether
RD_LOC_Tadvances by an extra hour, then restore the time from NTP. -
OPC UA cross-check. Subscribe to the
DTLtag via an OPC UA client (e.g. UaExpert). The client should display the local time if the CPU's time-zone setting is configured; verify thens=…;s=…;s=…;node Server timestamp matchesRD_LOC_T.OUT. - HMI spot check. Bind a date/time field on a Comfort Panel or Unified Panel to the local-time DTL tag. The panel should display wall-clock time, not UTC.
Common Pitfalls and Edge Cases
- Confusing the engineering PC's time zone with the CPU's time zone. A German engineer working remotely on a project in Saudi Arabia will see the TIA Portal Online & Diagnostics view shifted by an extra +1 h or +2 h (depending on DST) on top of the CPU's setting.
-
Migration from S7-300 to S7-1500. Existing S7-300 code reads local time with
RD_SYS_T; the same code on an S7-1500 reads UTC. Add a project-wide review for time-stamped audit-trail tags before commissioning. -
HMI log buffer. WinCC Professional and Unified log templates that take a
DTLtag will silently display UTC if the binding points to aRD_SYS_Tsource. Always re-bind log tags to theRD_LOC_Ttag. - Half-hour and 45-minute offsets. India (UTC+05:30), Iran (UTC+03:30 / +04:30), Nepal (UTC+05:45), and parts of Australia cannot be represented with whole-hour offsets. TIA Portal supports these via the time-zone list; verify the correct region is selected rather than approximating with a manual offset.
-
Battery-backed RTC with no NTP. A CPU that has been powered off for weeks will report a stale time. The PLC will not raise an error;
RD_LOC_T.OUTwill simply be wrong. Add a startup tag that flags "time not synchronized since restart" and force a re-sync. -
Secure PLC and NTP. On S7-1500 with security enabled, NTP traffic uses NTS or signed time packets. Make sure the configured NTP server supports the same protocol; otherwise, the CPU logs a synchronization error in the diagnostic buffer (event ID
0x27for "Time-of-day synchronization error").
Diagnostic Buffer and Online Trace
If you suspect that the time the CPU is reporting is wrong independently of the time-zone interpretation, open the diagnostic buffer (Online & Diagnostics > Diagnostics buffer) and look for the following events:
| Event ID (hex) | Meaning | Recommended Action |
|---|---|---|
| 0x00A1 | Time-of-day has been set by user | Informational; check who/when changed the time |
| 0x00A2 | Time-of-day has been set by NTP | Informational; NTP sync OK |
| 0x00A3 | Time-of-day synchronization interrupted | NTP server unreachable; check network and firewall |
| 0x00A4 | Time-of-day synchronization resumed | Informational; NTP recovered |
| 0x27xx | Secure-communication NTP/NTS error | Reconfigure NTS or relax security level |
For deeper analysis, use the trace function in TIA Portal V17+ to record the DTL tag on a 100 ms cycle. Compare the recorded HOUR field with the value from an external NTP-disciplined reference clock (e.g. a smartphone in airplane mode + GPS time).
FAQ
Does RD_SYS_T return local time on an S7-1500?
No. On every S7-1200 and S7-1500 firmware version, RD_SYS_T returns the CPU module time in UTC. The TIA Portal Online & Diagnostics view renders the value in the PC's local time, which is what causes the apparent mismatch. Use RD_LOC_T (S7-1500 >= V2.0, S7-1200 >= V4.2) to obtain the local time directly.
Why does RD_SYS_T on an S7-300/400 return local time but on an S7-1500 it returns UTC?
The two platform families handle time-of-day differently. S7-300/S7-400 store and expose the CPU clock as local time in BCD format, while S7-1200/S7-1500 store the clock internally as UTC and expose it via RD_SYS_T in UTC, leaving time-zone conversion to instructions such as RD_LOC_T. This is a documented architectural change, not a bug.
What is the difference between RD_SYS_T and RD_LOC_T in STEP 7 TIA Portal?
RD_SYS_T returns the raw module time (UTC on S7-1200/S7-1500) without applying the configured time zone or daylight saving rules. RD_LOC_T applies the CPU's configured time zone and DST settings and returns the resulting local date and time as a DTL value suitable for direct display on HMIs, SCADA, or shift logs.
How do I configure NTP time synchronization on an S7-1500 CPU?
Open the CPU device configuration in TIA Portal, go to Properties > General > Time of day, enable the NTP client, enter one or more NTP server IP addresses (for example pool.ntp.org or a plant NTP appliance), and set the synchronization interval to 60–600 s. The CPU will then discipline its internal RTC against the NTP server. The NTP server always returns UTC; local time is derived only when RD_LOC_T is called.
What error codes can RD_SYS_T return on S7-300 or S7-400 CPUs?
On S7-300/S7-400, RD_SYS_T returns an error code in the RET_VAL word. Common values are 0000 (no error), 8080 (date/time cannot be saved in the specified data type), and 80A0 (OUT parameter cannot be set, for example due to an invalid target area or the CPU being in STOP). On S7-1200/S7-1500, the RET_VAL output does not exist; only ENO is available.