Environment
- Lucee 7.1.1.16-RC (also seen on 7.1.0.204), CommandBox 6.3.5 / Runwar 6.1.8, Windows 11 25H2
- Java 25.0.4.1+1 (Temurin)
- Timezone: America/Vancouver (Lucee and JVM default), currently PDT (UTC−7)
- Worked correctly on 7.0.0.395 on the same machine (Java 11, July 2026)
Repro (server timezone America/Vancouver)
<cfset t = createTime(8, 0, 0)>
<cfoutput>
#timeFormat(t, "HH:mm:ss")# <!--- 08:00:00 (correct) --->
#t.toString()# <!--- {t '07:00:00'} expected {t '08:00:00'} --->
#createODBCTime("08:00")# <!--- {t '07:00:00'} expected {t '08:00:00'} --->
</cfoutput>
t.getTime() returns -2209107600000 = 1899-12-30T15:00:00Z. That’s 08:00 at today’s offset (−07:00), but it is rendered at America/Vancouver’s offset on 1899-12-30 (−08:00, no daylight time then), so it shows as 07:00.
Impact: scheduled tasks run an hour early cfschedule action="update" ... startTime="08:00:00" interval="daily" writes "startTime":"{t '07:00:00'}" to .CFConfig.json, and the task fires at 07:00 local time. Verified: stored 07:00 fired at 07:00:00, stored 06:00 fired at 06:00:03. cfschedule action="list" and the admin then display the stored value an hour earlier again ({t '06:00:00'} for a stored 07:00). On 7.0.0.395 the same call stored and fired at 08:00.
Related Same root cause as LDEV-5650 (historical offset applied to time values based on 1899; scheduled-task times shifting) and its duplicate LDEV-5693 (createODBCTime("10:45") wrong on 6.2.1.122). Both were fixed in 6.2.2.57 / 7.0.0.266, so this looks like a regression in the 7.1 branch.
Workaround Write the intended startTime directly into .CFConfig.json with the server stopped. It’s read back correctly and fires at that time, until the task is re-saved through cfschedule or the admin.