Date fields always include milliseconds even when seconds default to zero
Describe the Bug.
When using type: 'date' fields in Payload (e.g. with pickerAppearance: 'timeOnly'), the stored ISO timestamp always contains milliseconds (.323) even if users only select hours/minutes (and seconds default to 00). In many scenarios this millisecond precision is unnecessary and can lead to inconsistent comparisons or unexpected behavior when you expect “round” times.
Current Behavior
- Seconds are correctly set to
00by default, but milliseconds are not, but probably to the milliseconds at time of saving. - There is no built-in way to suppress or zero out the millisecond component at save time - except using a before change hook.
Expected Behavior
- When the UI picker only provides hours and minutes (and seconds default to zero), the saved ISO string should omit or zero the millisecond fraction.
- Ideally Payload would either:
- Strip the milliseconds automatically and set them to zero, resulting in
"2025-05-23T20:00:00Z", or - Expose a field-level config option (e.g.
admin.date.trimMilliseconds: true) to control inclusion of fractional seconds.
- Strip the milliseconds automatically and set them to zero, resulting in
Workaround
Use a beforeChange hook to manually zero‐out milliseconds:
hooks: {
beforeChange: [
async (payload) => {
const newDate = new Date(payload.data?.startTime)
newDate.setMilliseconds(0)
return newDate.toISOString()
},
],
},
Proposal
Add millisecond-trimming behavior to the core date field or expose a simple config flag:
{
name: 'startTime',
type: 'date',
admin: {
date: {
pickerAppearance: 'timeOnly',
trimMilliseconds: true, // ← new option
},
},
required: true,
}
This would improve DX (no need for custom hooks) and ensure stored timestamps match the intended precision.
Reproduction Steps
-
Define a collection with a date field:
{ name: 'startTime', type: 'date', admin: { date: { pickerAppearance: 'timeOnly' }, }, required: true, } -
In the admin UI, pick “08:00 PM.”
-
Save the document and inspect the stored value in the database or via the API.
You’ll see something like:
"startTime": "2025-05-23T20:00:00.323Z"
Environment Info
Binaries:
Node: 18.20.8
npm: 10.8.2
Yarn: 1.22.22
pnpm: 10.8.0
Relevant Packages:
payload: 3.33.0
next: 15.3.0
@payloadcms/db-postgres: 3.33.0
@payloadcms/email-nodemailer: 3.33.0
@payloadcms/graphql: 3.33.0
@payloadcms/next/utilities: 3.33.0
@payloadcms/payload-cloud: 3.33.0
@payloadcms/richtext-lexical: 3.33.0
@payloadcms/translations: 3.33.0
@payloadcms/ui/shared: 3.33.0
react: 19.1.0
react-dom: 19.1.0
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024; root:xnu-10063.141.2~1/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 10