Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LDATE, LTOD and LDT

TypeHeld asRange
LDATEnanoseconds since 1970-01-01, at midnight; signed 64-bitLD#1677-09-22 .. LD#2262-04-11
LTODnanoseconds since midnight; signed 64-bitLTOD#00:00:00 .. LTOD#23:59:59.999999999
LDTnanoseconds since 1970-01-01 00:00; signed 64-bitLDT#1677-09-21-00:12:43.145224192 .. LDT#2262-04-11-23:47:16.854775807

Ed.3 Table 10 makes each a signed 64-bit count of nanoseconds; the range is the whole of it, as CODESYS, TwinCAT and PLCnext give it (decided 2026-11-08, florin; implementer choices). A date before 1970 is a negative count. A literal takes up to nine digits of a second; one that names no day or time, or that the type cannot hold, is refused (E0020).

At the edges

  • An LTOD wraps at midnight, unflagged, as a TOD does.
  • An LDT outside its range wraps and is flagged OVERFLOW, as a DT does; so does a difference outside LTIME.
  • A long value made a short one drops what the short type is too coarse for, rounding down, unflagged: LDT_TO_DT the fraction of a second, LTOD_TO_TOD and LTIME_TO_TIME what is below a millisecond. Before 1970 down is earlier: LDT_TO_LDATE of the last nanosecond of 1969-12-31 is 1969-12-31.
  • A long value the short type cannot hold gives the short type’s default value, flagged CONVERSION: an LDT before 1970 or after 2106-02-07 made a DT or DATE is 1970-01-01, an LTIME beyond ±24d20h31m23s647ms made a TIME is T#0s. The task goes on. Ed.3 Table 22 leaves this result to the implementer.
  • DT, DATE, TOD and TIME widen to the long types without a conversion function (Ed.3 Figure 11), exactly. With one long operand the other is widened (Ed.3 6.6.1.6, rule 7): DT + LTIME is an LDT, never a DT, which could not hold the LTIME’s range.
ExpressionTypeResultFlagNote
LTOD#23:00:00 + LTIME#2hLTODLTOD#01:00:00—wraps at midnight
LTOD#01:00:00 - LTIME#2h1nsLTODLTOD#22:59:59.999999999—
LTOD#01:00:00 - LTOD#23:00:00LTIMELTIME#-22h—
LDT#2026-11-08-22:00:00 + LTIME#7hLDTLDT#2026-11-09-05:00:00—
LDT#1970-01-01-00:00:00 - LTIME#1nsLDTLDT#1969-12-31-23:59:59.999999999—before 1970
LDT#2262-04-11-23:47:16.854775807 + LTIME#1nsLDTLDT#1677-09-21-00:12:43.145224192flag OVERFLOWwrapped
LDT#2026-11-08-12:00:00 + T#1500msLDTLDT#2026-11-08-12:00:01.5—a TIME widened
DT#2026-11-08-12:00:00 + LTIME#1500msLDTLDT#2026-11-08-12:00:01.5—the DT widened
LDT#2026-11-08-12:00:01.5 - DT#2026-11-08-12:00:00LTIMELTIME#1500ms—
TOD#10:00:00 + LTIME#1500msLTODLTOD#10:00:01.5—
LD#2026-11-09 - D#2026-11-08LTIMELTIME#1d—
LD#2026-12-08 - LD#2026-11-08LTIMELTIME#30d—
SUB_LDT_LDT(LDT#2262-04-11-00:00:00, LDT#1677-09-22-00:00:00)LTIMELTIME#-1d23h34m33s709ms551us616nsflag OVERFLOWbeyond LTIME: wrapped
DT_TO_LDT(DT#2106-02-07-06:28:15)LDTLDT#2106-02-07-06:28:15—
LDT_TO_DT(LDT#2026-11-08-12:00:00.999999999)DTDT#2026-11-08-12:00:00—rounding down
LDT_TO_DT(LDT#1969-12-31-23:59:59)DTDT#1970-01-01-00:00:00flag CONVERSIONbefore DT’s range
LDT_TO_DATE(LDT#2106-02-08-00:00:00)DATED#1970-01-01flag CONVERSIONafter it
LDATE_TO_DATE(LD#2026-11-08)DATED#2026-11-08—
LDT_TO_LDATE(LDT#1969-12-31-23:59:59.999999999)LDATELD#1969-12-31—down is earlier
LDT_TO_LTOD(LDT#1969-12-31-23:59:59.999999999)LTODLTOD#23:59:59.999999999—
LDT_TO_TOD(LDT#2026-11-08-12:34:56.789999999)TODTOD#12:34:56.789—
LTOD_TO_TOD(LTOD#23:59:59.999999999)TODTOD#23:59:59.999—
DT_TO_LTOD(DT#2026-11-08-12:34:56)LTODLTOD#12:34:56—
CONCAT_DATE_LTOD(D#2026-11-08, LTOD#12:34:56.000000001)LDTLDT#2026-11-08-12:34:56.000000001—
CONCAT_LDT(1677, 9, 21, 0, 12, 43, 146)LDTLDT#1677-09-21-00:12:43.146—
CONCAT_LDT(1677, 9, 21, 0, 12, 43, 145)LDTLDT#1970-01-01-00:00:00flag CONVERSIONbefore the range
CONCAT_LTOD(23, 59, 59, 999)LTODLTOD#23:59:59.999—
MAX(LD#1969-12-31, LD#1677-09-22)LDATELD#1969-12-31—

SPLIT_LTOD and SPLIT_LDT give milliseconds, the rest dropped rounding down, as SPLIT_DT’s do (DATE, TOD and DT); the harness’s ldates case runs them, with the other conversions, tick by tick.