DatePicker: sets time adjusted to timezone instead of using date only
Describe the bug
I've noticed that when I use DatePicker in model it sets full time with adjustment to timezone instead of putting just date. So if I for example pick 2024-09-05 it'll set 2024-09-04T19:00:00.000Z in model and it'll be sent to the server. Is it possible to set only date like <input type="date"/> does?
Reproducer
https://stackblitz.com/edit/primevue-4-ts-vite-issue-template-csnodp
PrimeVue version
4.0.5
Vue version
4.x
Language
TypeScript
Build / Runtime
Vite
Browser(s)
No response
Steps to reproduce the behavior
No response
Expected behavior
No response
Same issue here
I got really confused when inputting 09/11/2024 and seeing that when pushing my form the date is 2024-09-10T22:00:00.000Z
No transformations on my part prior to POSTing my form
<DatePicker v-model="form.deadline_date" />
PrimeVue version
^4.0.0
Vue version
3.2.x
Language
Javascript
Build / Runtime
Vite
My current solution looks like this:
<script setup lang="ts">
import DatePicker from "primevue/datepicker"
import { inject, ref } from "vue"
const data: any = inject("data")
const errors: any = inject("errors")
const props = defineProps<{
label: string
name: string
}>()
const value = ref(
data.value[props.name] ? new Date(data.value[props.name]) : undefined
)
function setDate(date: Date) {
data.value[props.name] = date.toLocaleDateString`en-CA`
}
</script>
<template>
<DatePicker
class="form-control"
:class="{ 'is-invalid': name in errors }"
v-model="value"
:invalid="errors[name]"
size="small"
date-format="dd.mm.yy"
@update:model-value="setDate"
/>
</template>
So instead of passing data object directly to DatePicker's v-model I use setDate method to update ref which stores the data being sent to server.
Having the same Problem, I don't find a way to configure the right timezone to output. I select a date like 2024-11-25 but i get 2024-11-24T23:00:00.000Z
@cagataycivici any solution please
Note that this issue arises when the model value is set to a string instead of a Date. When the model value is a Date as it should be, you can then format it however you like.
Note that this issue arises when the model value is set to a string instead of a
Date. When the model value is aDateas it should be, you can then format it however you like.
I have not had this experience. On my setup it does this whether its a Date object or a string.
Same problem, and it looks extremely wrong, forcing extra processing of dates from each field. I am using Date object as a value.
I really wish that the DatePicker would let you pick dates. Not DateTime.
side note: shame on js for miss-naming Date.js
Same problem here, will any correction be applied to this case?
Indeed, this is extremely confusing, especially since I always get the day before what i select, due to timezone shenanigans. Threw me for a loop for a few hours there, and I'm unsure how best to fix this without a bunch of spaghetti code everywhere to account for this.
It would be great to be able to either explicitly specify a UTC timezone on DatePicker or otherwise allow a "date only" pick mode that also omits the timezone somehow. Having to do a lot of extra processing and wrap all DatePickers in a custom component right now.
I'm having the same issue. Very frustrating bug. I made this wrapper component to resolve it. I haven't thoroughly tested, so use at your own caution:
<script setup lang="ts">
import { defineModel, defineProps, defineEmits, computed, useAttrs } from 'vue'
import DatePicker, { type DatePickerProps, type DatePickerSlots, type DatePickerEmits } from 'primevue/datepicker';
import { format } from 'date-fns'
const model = defineModel();
const attrs = useAttrs()
interface Props extends /* @vue-ignore */ DatePickerProps {}
const props = defineProps<Props>()
interface Slots extends /* @vue-ignore */ DatePickerSlots {}
defineSlots<Slots>();
interface Emits extends /* @vue-ignore */ DatePickerEmits {}
defineEmits<Emits>();
const computedValue = computed({
get() {
if (attrs.showTime){
return model.value
}
if (model.value !== undefined) {
if (attrs?.selectionMode == 'multiple'){
return (model.value as []).map(v=>convertToLocalDate(v))
}
return convertToLocalDate(model.value as any)
}
return null
},
set(value: Date | null) {
const dateStr = convertToDateString(value)
model.value = dateStr
}
})
function convertToLocalDate(dateValue: string | Date | null): Date | null {
if (!dateValue) return null
// If it's already a Date object, return it
if (dateValue instanceof Date) return dateValue
// If it's a date string like "2025-06-09", create a local date to avoid timezone issues
if (typeof dateValue === 'string' && dateValue.match(/^\d{4}-\d{2}-\d{2}$/)) {
const [yearStr, monthStr, dayStr] = dateValue.split('-')
return new Date(parseInt(yearStr), parseInt(monthStr) - 1, parseInt(dayStr))
}
// For other string formats, try to parse normally
if (typeof dateValue === 'string') {
return new Date(dateValue)
}
return null
}
function convertToDateString(value: Date | null): string | null {
if (!value) return null
// Convert Date object back to YYYY-MM-DD string format
return format(new Date(value), 'yyyy-MM-dd')
}
const computedProps = computed(()=>({...props, 'modelValue': computedValue}))
</script>
<template>
<DatePicker v-bind="(computedProps as any)">
<template v-for="(_, slotName) in $slots" v-slot:[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps ?? {}" />
</template>
</DatePicker>
</template>
Has anyone solved this? annoying
This issue is too important not to be solved by now!
Still waiting for a solution...
It's very annoying indeed to have to deal with javascript Date objects whereas the standard HTML input type="date" control deals with text, especially when you want the DatePicker to work only for dates and not full date and time.
As for the timezone issue, my current "hack" is to bypass the v-model directive and use :model-value and @value-change emit to build a new Date with the offset removed, so that it can easily be converted to a "date only" afterwards:
const myDate = ref<Date>()
[...]
<DatePicker
:model-value="myDate"
@value-change="(e: any) => myDate = new Date(e.getTime() - e.getTimezoneOffset() * 60000)"
/>
{{ myDate?.toISOString().slice(0, 10) }}
@cagataycivici merhaba; sorunla neden ilgilenmiyorsunuz. Sizden satın altığımız themeda da benzer sorunlar var. Teşekkürler
This issue among many others overlooked for years yet highlighted by community is the reason I'm currently waiting for NuxtUI to get free instead of buying Prime's figma kit.
We've decided to add dataType prop as in PrimeNG, default to Date and setting it string provides what is displayed value in formatted form.
@mertsincan @tugcekucukoglu please take over.
Thank you for this! @tugcekucukoglu one console.log sneaked into the commit ;)
Thanks for the update !
We were also annoyed by this behavior.
Waiting for 4.4.0 release...
@tugcekucukoglu using the just released Version 4.4.0 updateModelType is mandatory in DatePickerProps. Was that intentional?
error TS2345: Argument of type '{ modelValue: Date | Date[] | undefined; dateFormat: string; placeholder: string; 'onUpdate:modelValue': any; }' is not assignable to parameter of type 'DatePickerProps & VNodeProps & AllowedComponentProps & ComponentCustomProps & Record<string, unknown>'.
Property 'updateModelType' is missing in type '{ modelValue: Date | Date[] | undefined; dateFormat: string; placeholder: string; 'onUpdate:modelValue': any; }' but required in type 'DatePickerProps'.
80 <DatePicker
~~~~~~~~~~
node_modules/.pnpm/[email protected][email protected][email protected]_/node_modules/primevue/datepicker/index.d.ts:545:5
545 updateModelType: HintedString<'date' | 'string'> | undefined;
~~~~~~~~~~~~~~~
'updateModelType' is declared here.
The problem is that it shows the user the local time but behind the scene it works with UTC time. you should always check for offset between your localtime and utctime when sending the data to server. example:
const now = Date.now();
const offsetMinutes = new Date().getTimezoneOffset();
const timeToBeSent = new Date(now + offsetMinutes * 60 * 1000)