Overview: Why Multiply a Time Value?
Multiplying an LTime value is a recurring question in Siemens TIA Portal programming because the IEC 61131-3 LTime data type is fundamentally a 64-bit signed integer scaled to nanoseconds. Engineers frequently need to compute derived quantities such as:
- Energy = average power × duration (scaling time-of-day or pulse-width totals)
- Distance = velocity × elapsed time (motion tracking, conveyor length estimation)
- Cost = rate per hour × runtime (machine operating cost dashboards)
- Totalized throughput = flow rate × interval (batch reporting)
In every case, the conceptual operation is Duration × Rate, not Time × Time. The naive expression Result := LTime * LTime; in SCL (Structured Control Language) compiles and executes but produces numerically meaningless output whenever the operands exceed a few seconds, because the result exceeds the LINT representation range. This article documents the numeric limits, the exact overflow thresholds, the supported TIA Portal functions, and field-proven safe-coding patterns for any product that involves an LTime operand.
LTime * LTime, you almost certainly want LTime * Real (or LReal * LTime) instead, with one operand converted to a numeric duration in seconds.LTime Data Type: Numeric Foundation
The LTime data type is defined in IEC 61131-3 Third Edition and implemented by Siemens as a 64-bit signed integer with an implicit time base of one nanosecond. The TIA Portal online help describes the format as LTime#<numeric_value>d<h>m<s>ms<us>ns, where each suffix is optional and the underlying storage is always a LINT.
| Attribute | Value |
|---|---|
| Storage size | 64 bits (8 bytes) |
| Base data type | LINT (signed) |
| Time base | 1 ns |
| Minimum value | -9 223 372 036 854 775 808 ns ≈ -106,751 d 23 h 47 m 16.854 s |
| Maximum value | +9 223 372 036 854 775 807 ns ≈ +106,751 d 23 h 47 m 16.854 s |
| Approximate range in days | ±8.64 × 1013 ns/day → ±106,751 days ≈ ±292 years |
| First introduced (Siemens) | S7-1500 CPU FW 1.0; S7-1200 CPU FW 4.2; TIA Portal V13 SP1 |
| Display in watch table | Date/time format or nanosecond integer |
Compare this to the older TIME (32-bit) data type, which covers only ±2,147,483,647 ms ≈ ±24.8 days. The introduction of LTime was driven by long-duration batch timers, GPS-synchronized timestamping (with 100 ns precision per SIMATIC Time-of-Flight applications), and high-resolution motion profiles on the S7-1500 platform.
Overflow Math: When Does LTime * LTime Fail?
The numeric ceiling is the LINT maximum 9,223,372,036,854,775,807 ≈ 9.22 × 1018. To determine whether a multiplication overflows, compute the product of the two operand magnitudes and compare against this ceiling. Convenient reference points:
| Operand A | Operand B | Product (ns²) | Status |
|---|---|---|---|
| 1 s = 109 ns | 1 s | 1018 | Within range (≈ 10.85 % of max) |
| 1 s | 4 s | 4 × 1018 | Within range (≈ 43 %) |
| 3 s | 3 s | 9 × 1018 | Borderline overflow on signed multiply |
| 10 s | 10 s | 1020 | Overflow (10,000 % of max) |
| 1 day | 1 day | 7.46 × 1027 | Overflow by ~9 orders of magnitude |
| 1 ms | 1 s | 1015 | Safe (≈ 0.011 % of max) |
| 1 ms | 1 ms | 1012 | Safe |
| 100 ms | 100 ms | 1016 | Safe (≈ 0.1 % of max) |
| 1 s | 1 min | 6 × 1019 | Overflow |
The threshold is roughly 3 s × 3 s = 9 s². Above that, the signed 64-bit product wraps and the CPU returns a result whose absolute value, sign, and interpretation are all undefined from an engineering standpoint. SCL does not raise an exception; the runtime silently stores a wrapped LINT and the HMI may display a negative or nonsensical duration.
How the SCL Compiler Handles LTime × LTime
In TIA Portal V16 and later, the SCL compiler performs implicit type promotion according to the rules in the TIA Portal Help: "Type conversion of arithmetic expressions":
- If both operands are
LTime, the compiler treats them asLINTand emits a signed 64-bit multiplication. - The result type is
LTime, but the underlying bits are raw LINT. - No overflow check is inserted; the runtime simply writes the low 64 bits of the true mathematical product (modulo 264), then interprets the bits as a signed value if negative.
Equivalently, in TIA Portal:
// Compiles in SCL, but the result is meaningless for large operands
VAR
a : LTime := LT#1d2h30m0s0ms0us0ns;
b : LTime := LT#0d0h0m15s0ms0us0ns;
r : LTime;
END_VAR
r := a * b; // r overflows; expected ≈ 1.27e21, wraps to ≈ 4.3e18
Ladder logic (LAD) and Function Block Diagram (FBD) do not even expose a generic MUL block for LTime; the standard MUL instruction expects integer or real types. In graphic editors, you must first convert both operands to LINT using LTime_TO_LINT, multiply, and then convert back to LTime — at which point the wrap occurs identically.
Standard Library Functions That Touch LTime
The TIA Portal Standard Library / TIA Portal Help: "LTime — conversion functions" documents the supported conversions. The relevant ones for multiplication work:
| Function | From | To | Use |
|---|---|---|---|
| LREAL_TO_LTIME | LReal (s) | LTime (ns) | Best entry point for product calculations |
| LTIME_TO_LREAL | LTime (ns) | LReal (s) | Convert duration before multiplying |
| LTIME_TO_LINT | LTime (ns) | LINT (ns) | Bit-level operations, hashing, modular math |
| DWORD_TO_LTIME | DWORD | LTime | Legacy 32-bit time ingestion |
| LTIME_TO_STRING | LTime | String | Display on HMI without overflow exposure |
| LTIME_TO_DINT / LREAL_TO | LTime | DInt / LReal | Aggregation and trending |
Note that there is no LTIME_MUL standard FB in the TIA Portal basic library. For motion applications, the S7-1500 Motion Control library (LBC) performs time × velocity calculations internally with LReal intermediates to avoid this exact overflow class.
Safe Multiplication Patterns
Pattern 1 — Convert Duration to LReal Seconds, Multiply, Convert Back
This is the canonical solution. The key insight is that the time dimension carries units (seconds, minutes, days), and once one operand is converted to a unitless LReal, the multiplication becomes an ordinary real-time product that never overflows LTime because the LReal intermediate absorbs the magnitude.
// "Total energy = power_kW * runtime_seconds"
FUNCTION_BLOCK FB_EnergyTotalizer
VAR
nRatedPower_kW : LReal := 12.5;
tRunTime : LTime;
tStartTime : LTime;
nEnergy_kWh : LReal;
END_VAR
// Read current runtime from IEC_TIMER or user logic
tRunTime := tNow - tStartTime;
// Convert LTime (ns) to LReal seconds by dividing by 1.0e9
nEnergy_kWh := nRatedPower_kW * LTIME_TO_LREAL(tRunTime) / 3600.0;
No overflow occurs because the LReal intermediate is ~104932 in magnitude — essentially unlimited for process values. The maximum LReal in TIA Portal is approximately 1.7976931348623158 × 10308, far larger than any conceivable plant throughput.
Pattern 2 — Scale Inputs into a Safe Range Before Multiplying
When you specifically need the result expressed in nanoseconds (for instance, to feed an LTime tag that drives an HMI animation curve), scale the inputs first:
// "Cycle length = packets * packet_period_ns"
VAR
nPackets : LInt := 1200000000; // 1.2 billion packets
tPacketTime : LTime := LT#0d0h0m0s1ms0us0us; // 1 ms = 1,000,000 ns
tTotal : LTime;
END_VAR
// Direct product would overflow (1.2e9 * 1e6 = 1.2e15 ns — still safe!)
// But to be defensive, reduce to LReal:
tTotal := LREAL_TO_LTIME(
DINT_TO_LREAL(nPackets) *
LTIME_TO_LREAL(tPacketTime) * 1.0e9);
The 1.0e9 converts the seconds intermediate back into nanoseconds for LREAL_TO_LTIME. Round-trip accuracy for values below 253 ns (≈ 104 days) is exact; above that, the IEEE-754 double begins to lose sub-nanosecond precision.
Pattern 3 — Use a Scale Factor and Integer Multiplication
If the operands are guaranteed small (for example, both below 100 ms), an LInt × LInt multiplication stays inside the safe zone, but never use it for arbitrary inputs:
VAR CONSTANT
cSampleRate_ns : LInt := 100000; // 100 µs
END_VAR
VAR
nSamples : LInt := 50000; // 5 seconds worth
tWindow : LTime;
END_VAR
tWindow := LINT_TO_LTIME(nSamples * cSampleRate_ns); // 5e9 ns → safe
LTime units, do not multiply two LTime/LInt values directly. Switch to LReal intermediates.Pattern 4 — Modular Products with Modular Reduction
For cyclic tasks where only the modulo-N product matters (for example, distributing pulses into a 24-hour window), apply the modulo early:
// Total running time mod 24 hours, so it never exceeds 86,400,000,000,000 ns
tInDay := LT#24h;
tModulo := tInDay; // 8.64e13 ns
tElapsed := (tNow - tShiftStart) MOD tModulo;
Step-by-Step: Refactoring a Naive LTime × LTime Expression
- Identify the physical units of each operand. Write down seconds, minutes, or days for every input. If you cannot name a unit, the operand is not really a duration.
- Compute the order of magnitude of the product. Multiply the typical magnitudes. If it exceeds 1018, plan for an LReal intermediate.
-
Convert the LTime operand to LReal seconds. Use
LTIME_TO_LREAL. The resulting LReal is in seconds with 1 ns resolution (≈ 15 significant decimal digits). - Perform the multiplication in LReal. Combine with the rate, scaling factor, or other operand in LReal arithmetic.
-
Convert the LReal result back to LTime only if the output must be a duration. Use
LREAL_TO_LTIME; remember this multiplies seconds by 109 internally. -
Add an overflow guard if the result drives a critical actuator. Compare the magnitude against
LT#30dand clamp with a safe value. - Verify in the PLCSIM or HMI watch table with boundary inputs: minimum, nominal, and ten times nominal. Confirm sign and magnitude are correct.
Verification: Unit Tests in PLCSIM
Before deploying any LTime multiplication logic, exercise the function block with deterministic inputs in S7-PLCSIM V17+:
| Test | Input A | Input B | Expected Result | Status |
|---|---|---|---|---|
| Boundary low | LT#1ns | LT#1ns | LT#1ns² interpretation → LT#0s | Pass / convention |
| Nominal | LT#500ms | Rate 0.25 kW | 0.125 Wh | Pass with LReal |
| Just below overflow | LT#2s | LT#2s | LT#4s (should be safe, but verify) | Pass |
| Just above overflow | LT#4s | LT#4s | Wrap → invalid | Must use LReal pattern |
| 1 day × 1 day | LT#1d | LT#1d | Wrap → invalid | Must use LReal pattern |
| 1 ms × 1 hr (indirect) | LT#1ms | 3600000 ms rate | 3600 s | Pass with LReal |
A useful PLCSIM trick is to monitor the raw LINT view of the result variable. Right-click the tag in the watch table and select "Display format → Hex / Decimal"; if the value flips between large positive and large negative jumps when input nudges by a small amount, the multiplication has wrapped and you have an overflow.
Comparison: LTime vs. TIME vs. DInt vs. LReal
| Property | TIME | LTIME | DINT | LREAL |
|---|---|---|---|---|
| Bits | 32 | 64 | 32 | 64 |
| Signed | Yes | Yes | Yes | Yes (mantissa + exponent) |
| Range | ±24.8 days (ms) | ±292 years (ns) | ±2.1 × 109 | ±1.8 × 10308 |
| Resolution | 1 ms | 1 ns | 1 | ≈ 15–17 digits |
| Used for multiplication? | Rarely safe | Only with small operands | Common | Preferred for derived quantities |
| HMI display | d / h / m / s / ms | d / h / m / s / ms / µs / ns | Integer | Floating point |
Rule: if the result is a duration (something you would display on a clock or feed to a timer), the output type should be LTime; if the result is a quantity (energy, cost, distance, mass), the output should be LReal. Mixing the two roles is the most common source of LTime overflow bugs.
Diagnostic Checklist for LTime Multiplication Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| Result negative after one positive multiply | Signed wrap-around | Convert to LReal, multiply, convert back |
| Result reads "0" for two nonzero operands | Wrap to exactly 0 modulo 264 | Same — overflow protection via LReal |
| Result in HMI shows date in 1969 / 2096 | Wrapped LINT interpreted as nanoseconds from epoch | Verify operand units; clamp with MAX_LTIME |
| PLC goes to STOP with SF LED | Division by zero in LREAL_TO_LTIME
|
Guard against zero operands |
| Watch table shows "????" or invalid value | LTime display can't render >292 years | Limit operand magnitude; use LReal output |
| SCL warning: "Operand of type LTime is not supported" | Compiler cannot infer promotion (pre-V13 SP1) | Upgrade TIA Portal to V16+ or upgrade CPU FW |
Edge Cases and Field-Proven Caveats
-
Negative LTime operands. SCL allows
LT#-1sfor difference calculations. Multiplying two negative LTime operands produces a positive wrap; multiplying operands of opposite sign produces a negative wrap. Convert to LReal before sign-aware math, or use absolute values explicitly. -
Subnormals and signed zero.
LREAL_TO_LTIMEof +0.0 returnsLT#0ns; of -0.0 returnsLT#0ns. There is no negative zero in LTime semantics. - PLC and HMI display rounding. WinCC Unified and Comfort Panels display LTime to the nearest microsecond on the screen. The actual tag resolution is 1 ns; expect a rounding difference of up to 500 ns in displayed values.
-
Cross-platform portability. LTime exists in IEC 61131-3 Third Edition and is supported in CODESYS 3.5 and Beckhoff TwinCAT 3, but the conversion functions use different names (
DATE_AND_TIME_TO_LTIMEvs.LTIME_FROM_DT). If you are porting blocks, audit every conversion. -
Real-time clock read.
RD_SYS_Ton S7-1500 returnsLTimemeasuring ns since 1970-01-01 UTC. The absolute magnitude is ~1.7 × 1018 ns — already near the upper edge of LTime. Never multiply twoRD_SYS_Tvalues together; the result will wrap. - Grounding / isolation: If your overflowed LTime is read by a safety program, ensure the safety FB clamps the value. SIL-rated function blocks should treat any out-of-range time input as a fault per IEC 61508 SIL 2/3 guidelines.
Alternative Controllers and Cross-References
-
Allen-Bradley / Rockwell: The equivalent is the 64-bit
LINTtag with manual scaling (microseconds or nanoseconds), and multiplication is straightforward because Logix Designer does not reserve a dedicated "long time" data type. See Logix 5000 Controllers General Instructions Reference. -
CODESYS 3.5 / Beckhoff:
LTIMEis identical semantically; the recommended pattern is the same: convert one operand toLREALin seconds before multiplying. TwinCAT 3 usesTIME()andLTIME()conversion functions from theTc2_Utilitieslibrary. -
Schneider Electric EcoStruxure: Modicon M340/M580 lack a native LTime type; durations are stored as
TOD(time of day) orDINTin milliseconds.
FAQ
Can I directly multiply two LTime tags in TIA Portal SCL?
Yes, the SCL compiler accepts Result := LTimeA * LTimeB;, but the result is a 64-bit signed product. Any operand pair whose product exceeds about 9.2 × 1018 ns² (roughly two values above 3 s each) will wrap and produce a meaningless LTime. For safety, convert one operand to LReal seconds first.
What is the exact maximum value of LTime in a Siemens S7-1500?
LTime is a 64-bit signed integer scaled to nanoseconds. The maximum value is 9,223,372,036,854,775,807 ns, equivalent to approximately 106,751 days, 23 hours, 47 minutes and 16.854 seconds (about 292 years). Anything larger wraps to a negative value.
Why does my LTime multiplication return a negative duration?
The product exceeded the LINT ceiling and the signed bit wrapped from positive to negative territory. Convert at least one operand to LReal (seconds), multiply, and only convert back to LTime if the output really must be a duration tag. Otherwise keep the result in LReal.
Which CPU firmware supports the LTime data type?
S7-1500 CPUs support LTime from firmware V1.0 (all current variants). S7-1200 CPUs support LTime from firmware V4.2 (initial support) and V4.4 (full standard library functions). TIA Portal V13 SP1 or later is required on the engineering side; V16+ is recommended for best type-conversion diagnostics.
How do I multiply an LTime by a flow rate or power value?
Convert the LTime to LReal seconds using LTIME_TO_LREAL(tDuration), then perform ordinary LReal multiplication with the rate. For example, nEnergy_kWh := nPower_kW * LTIME_TO_LREAL(tRuntime) / 3600.0;. Avoid converting back to LTime unless you are feeding a timer input.
Is there a standard FB in TIA Portal for safe LTime arithmetic?
No dedicated LTIME_MUL FB exists. The recommended practice is to use the inline LReal conversion pattern shown above. For high-volume motion applications, the LBC (Library of Basic Controls) motion blocks internally handle time × velocity scaling using LReal, which you can replicate in user code.
Can I read the result of a wrapped LTime product and recover the original value?
No. Once the product exceeds 263 ns², the low 64 bits of the true mathematical product are stored, and the high bits are lost. There is no hardware flag or status bit. You must prevent the overflow upstream by either constraining inputs or using an LReal intermediate.