I want to change "August 2022" to "2022 August" but i can't find anything similar with this attribute in v-date-picker.
How to change format of this header
Vuetify Datepicker
You have a propery header-date-format that you can use to call your own method of formatting the headers
<v-date-picker
v-model="picker"
:header-date-format="customFormatHeader"
></v-date-picker>
customFormatHeader(isoDate) {
const currentDate = new Date(isoDate)
const month = currentDate.toLocaleString('default', {month: 'long' })
const year = currentDate.toLocaleString('default', { year: 'numeric' })
return year + month
}
Related
I currently have a datetime field in my vue application. I want to split it up, but that would mean having to split it up in my database as well, which I am not interested in. I still want to keep the datetime column in my database table.
So my idea was to make it like 3 seperate fields: datetime, date and time. When a user has entered a date and time, these can be merged into the datetime field.
In Python you would do something like: datetime.datetime.combine( date, time )
Is there are similar method in Vue, or is there a better way of getting around this?
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in time')">
<time-picker v-model="guest.checkInDateTime" />
</b-form-group>
</b-col>
</b-form-row>
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in date')">
<date-picker v-model="guest.checkInDateTime" />
</b-form-group>
</b-col>
</b-form-row>
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in time and date')">
<date-time-picker v-model="guest.checkInDateTime"
:format="format"
:show-second="false"
type="datetime"/>
</b-form-group>
</b-col>
</b-form-row>
Working with dates in Javascript can be nuanced. In Javascript, assuming you have both a date value and a time value, you can easily combine these into a date string used by an html date picker like this:
const date = '2022-08-10' // string returned from date input
const time = '15:00:00' // string returned form time input
const checkInDateTime = date + 'T' + time // ISO String
If you're starting with a Date and you want to break it into a date value and a time value, it's almost easier using string manipulations than working with the Date obj, unless you're using a helper library like dayjs.
Examples:
// Assuming we have a date in ISO String format YYYY-MM-DDTHH:mm:ss
const dateFromString = dateValueFromDB.split('T')[0]
const timeFromString = dateValueFromDB.split('T')[1]
// using Date obj
const d = new Date(dateValueFromDB);
const dateFromObj = `${d.getFullYear()}-${('' + (d.getMonth() + 1)).padStart(2, '0')}-${('' + date.getDate()).padStart(2, '0')}`
const timeFromObj = `${d.getHours()}:${('' + d.getMinutes()).padStart(2,'0')}:${('' + d.getSeconds()).padStart(2,'0')}`
// using dayjs library
const dateFromDayjs = dayjs(dateValueFromDB).format('YYYY-MM-DD')
const timeFromDayjs = dayjs(dateValueFromDB).format('HH:mm:ss')
Now to answer your original question. Once we know how we're getting the correct values, in Vue.js, we can easily get and set these date values using a computed property and a custom setter.
<script>
export default {
data() {
return {
guest: {
checkInDateTime: '2022-09-10 15:00:00' // timestamp returned from database
}
}
},
computed: {
time: {
get() {
return dayjs( this.guest.checkInDateTime ).format('HH:mm:ss')
},
set(val) {
this.guest.checkInDateTime = this.date + 'T' + val
}
},
date: {
get() {
return dayjs(this.guest.checkInDateTime).format('YYYY-MM-DD')
},
set(val) {
this.guest.checkInDateTime = val + 'T' + this.time
}
}
}
}
</script>
Here's the html:
<template>
<div class="datetime-pickers">
<p>date: <input type="date" v-model="date" /></p>
<p>time: <input type="time" v-model="time" /></p>
<p>checkInDateTime: <input type="datetime-local" v-model="guest.checkInDateTime" /></p>
</div>
</template>
When any of the three values are set, the other two are updated accordingly. Here's a CodePen showing this in action:
https://codepen.io/ryanhightower/pen/ExLPobY?editors=1010
In my vue/cli 4/vuex / bootstrap-vue project app I install date picker with custom format, like here
https://dbrekalo.github.io/vue-date-pick/examples.html#custom-date-parser
I use moment/moment-timezone in my project, so I do not want to use fecha as in example
I have to convert date value from mysql to datepicker format and I have a problem that my converted date for
datepicker is 1 day bigger...
I have in my component:
<date-pick
v-model="editableAd.expire_date_formatted"
:format="date_picker_format"
:parseDate="parseDate"
:formatDate="formatDate"
:inputAttributes="{size: 32}"
></date-pick>
...
import moment from 'moment-timezone'
console.log('settingsTimeZone::')
console.log(settingsTimeZone) // it shows Europe/Kiev
moment.tz.setDefault(settingsTimeZone)
...
date_picker_format: 'Do MMMM, YYYY',
...
// setting formated date for dapicker
this.editableAd.expire_date_formatted = this.formatDate(this.editableAd.expire_date, this.date_picker_format)
...
formatDate(dateObj) {
console.log('typeof dateObj::')
console.log(typeof dateObj)
console.log(dateObj) // it has ‘2023-01-19’ value
if (typeof dateObj === 'string') {
dateObj = moment(dateObj, this.date_picker_format)
}
console.log('++typeof dateObj::')
console.log(typeof dateObj)
console.log(dateObj)
console.log('RESULT moment(dateObj).format(this.date_picker_format)::')
console.log(moment(dateObj).format(this.date_picker_format)) // BUT it has ‘20th January, 2023’ value
return moment(dateObj).format(this.date_picker_format) // returns invalid ‘20th January, 2023’ value which I see in datepicker
What I see in console for dateObj var : https://imgur.com/a/KZLtXiL
"bootstrap-vue": "^2.1.0",
"font-awesome": "^4.7.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.27",
"vue": "^2.6.10",
"vue-date-pick": "^1.2.1",
Why error and how it can be fixed?
MODIFIED BLOCK 2:
I removed moment.tz from my project.
In /etc/php/7.2/apache2/php.ini I changed
Timezone ='Europe/Uzhgorod' // That it near my place I live
date.timezone = "Europe/Uzhgorod"
So my phpinfo has this output:
"Olson" Timezone Database Version 0.system
Timezone Database internal
Default timezone Europe/Uzhgorod
I searched how to get a timezone from client browser and found this
get client time zone from browser branch and checking :
var timedifference = new Date().getTimezoneOffset();
console.log('timedifference::')
console.log(timedifference)
var rightNow = new Date();
var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
var temp = jan1.toGMTString();
var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ") - 1));
var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
console.log('std_time_offset::')
console.log(std_time_offset)
let jstz = require('jstimezonedetect')
let timezone = jstz.determine()
console.log('timezone::')
console.log(timezone)
console.log('===========================')
I have next output: https://imgur.com/a/84RqqPJ and again running code when I see date is changed +1 day :
console.log('__')
console.log('__')
console.log('typeof dateObj::')
console.log(typeof dateObj)
console.log(dateObj)
if (typeof dateObj === 'string') {
dateObj = moment(dateObj, this.date_picker_format)
}
console.log('++typeof dateObj::')
console.log(typeof dateObj)
console.log(dateObj) // it has ‘2023-01-19’ value
console.log('RESULT moment(dateObj).format(this.date_picker_format)::')
console.log(moment(dateObj).format(this.date_picker_format)) // BUT it has ‘20th January, 2023’ value
return moment(dateObj).format(this.date_picker_format)
and what I see in console: https://imgur.com/a/Y1aSBez
That is strange that .d has 20 day. What is it? Some day zero based option?
The problem you're having is due to some automatic localization formatting. I too don't get why does this happens, since we are providing only dates, they should be treated as such regardless of our timezone. But to solve this issue we have to read it as UTC with moment.utc() and then format it using your desired format.
From vue-date-pick docs example I've worked out a solution using moment.
var app = new Vue({
el: '#app',
components: {
'date-pick': VueDatePick,
},
data: () => ({
format: 'Do MMMM, YYYY',
date: '19th January, 2023',
}),
methods: {
parseDate(value) {
const m = moment.utc(value, this.format);
return new Date(m.year(), m.month(), m.date());
},
formatDate(value) {
return moment.utc(value).format(this.format);
}
}
});
<link href="https://cdn.jsdelivr.net/npm/vue-date-pick#1.2.1/dist/vueDatePick.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-date-pick#1.2.1/dist/vueDatePick.min.js"></script>
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone.min.js"></script>
<div id='app'>
<date-pick v-model="date" :format="format" :parse-date="parseDate" :format-date="formatDate"></date-pick>
</div>
So I'm making an attendance tracker with Vuejs and Vuetify, and I want it to look like this:
A Calender made up of v-card components, and a list of absences read in from a database. I have my API set up and am able to retrieve a list of absences without any issues, but when it comes to putting them on the screen I have some issues. What I want to do is this:
The user selects the month and year. Each card then shows one day of this month. I have a function called getAbsDate(date) that returns a list of absences for the date passed to it. I want it to work something like this in each card:
<v-card min-height="170" tile>
<v-card-text class="text-center black--text">
{{i}}
<v-sheet
color="blue"
class="pa-1"
v-for="abs in getAbsDate(i+'.'+monthsNums[selMonth]+'.'+selYear)"
:key="abs['id']"
>{{abs["name"]}}</v-sheet>
</v-card-text>
</v-card>
selMonth is the month the user selected, and selYear is the year the user selected. This doesn't work however. I don't get any errors, the cards are just empty. getAbsDate() returns a list of objects. Any ideas as to why this doesn't work?
Thanks!
EDIT
Here is the declaration of my getAbsDate() function.
getAbsDate: function(date) {
let l = [];
this.absences.forEach(abs => {
if (abs["start"] == date) {
l.push(abs);
}
if (abs["end"] == date) {
l.push(abs);
}
let day_start = moment(abs["start"].replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
let day_end = moment(abs["end"].replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
let day_date = moment(date.replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
if (day_start <= day_date && day_date <= day_end) {
l.push(abs);
}
});
return l;
}
}
The formatting is not quite right at the .toDate() and the .getTime(), but in my file it is, s it is not the issue.
I am using bootstrap-datetimepicker version 4.17.47 in ASP MVC 4 app.
I have this model property:
public DateTime MonthYear { get; set; }
I assign default value in controller (arbitrary value is just an example actual value is determined through some logic):
model.MonthYear = new DateTime(2017, 3, 1);
I display this in view using datepicker so users can update the value as needed:
#Html.TextBoxFor(model => model.MonthYear, new { #class = "form-control input month-picker" })
Script:
$('.month-picker').datetimepicker({
format: 'MM/YYYY',
useCurrent: false,
toolbarPlacement: 'bottom',
viewMode: 'months'
});
The problem is the control displays "03/0001" instead of "03/2017".
What am I missing here?
Apparently the problem is that the input is being filled with a DD/MM/YYYY date from server when datetimepicker is expecting only MM/YYYY. Try formating the textbox, like:
#Html.TextBoxFor(model => model.MonthYear, "{0:MM/yyyy}", new { #class = "form-control input month-picker" })
That should work.
I receive from a WebAPI a JSON object that has this property:
"BirthDate": "2018-02-14T15:24:17.8177428-03:00",
the HTML:
<input type="date" v-model="BirthDate" />
I bind that object using VueJS, but
VueJS give this message in the console:
The specified value "2018-02-14T15:24:17.8177428-03:00" does not conform to the required format, "yyyy-MM-dd".
On this case the only relevant part is 2018-02-14, I can discard the other information.
I tried to create a Two Way filter to convert that Date Time to the required format but did not have success. See VueJS two way filter
How can I convert and bind that Date/Time format to the required Date Format of the HTML date input ?
Considering myDate is your property, you can use:
<input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
#input="myDate = $event.target.valueAsDate">
Since v-model is only syntactic sugar to :value and #input, you can use them instead. In this case, we used and changed them a little (to format the String that is the output of the date input to a Date object and vice-versa).
Check demo and caveats below.
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
myDate: new Date('2011-04-11T10:20:30Z')
},
methods: {
setMyDateToToday() {
this.myDate = new Date();
},
addADayToMyDate() {
if (this.myDate) // as myDate can be null
// you have to set the this.myDate again, so vue can detect it changed
// this is not a caveat of this specific solution, but of any binding of dates
this.myDate = new Date(this.myDate.setDate(this.myDate.getDate() + 1));
},
}
});
// Notes:
// We use `myDate && myDate.toISOString().split('T')[0]` instead
// of just `myDate.toISOString().split('T')[0]` because `myDate` can be null.
// the date to string conversion myDate.toISOString().split('T')[0] may
// have timezone caveats. See: https://stackoverflow.com/a/29774197/1850609
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
<input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
#input="myDate = $event.target.valueAsDate">
<p>
<code>
myDate: {{ myDate }}</code>
</p>
<button #click="setMyDateToToday">Set date one to today</button>
<button #click="addADayToMyDate">Add a day to my date</button>
</div>
i think this not related to vueJs , the input type="date" expected a date in YYYY-MM-DD format, or empty
see here : https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date,
it would be better if you split date object as date and time field
Correction to #acdcjunior in that this shouldn't be off by one day
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
myDate: new Date('2011-04-11T10:20:30Z')
},
methods: {
setMyDateToToday() {
this.myDate = new Date();
},
addADayToMyDate() {
if (this.myDate) // as myDate can be null
// you have to set the this.myDate again, so vue can detect it changed
// this is not a caveat of this specific solution, but of any binding of dates
this.myDate = new Date(this.myDate.setDate(this.myDate.getDate() + 1));
},
getDateClean(currDate) {
// need to convert to UTC to get working input filter
console.log(currDate);
let month = currDate.getUTCMonth() + 1;
if (month < 10) month = "0" + month;
let day = currDate.getUTCDate();
if (day < 10) day = "0" + day;
const dateStr =
currDate.getUTCFullYear() + "-" + month + "-" + day + "T00:00:00";
console.log(dateStr);
const d = new Date(dateStr);
console.log(d);
return d;
}
}
});
// Notes:
// We use `myDate && myDate.toISOString().split('T')[0]` instead
// of just `myDate.toISOString().split('T')[0]` because `myDate` can be null.
// the date to string conversion myDate.toISOString().split('T')[0] may
// have timezone caveats. See: https://stackoverflow.com/a/29774197/1850609
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
<input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
#input="myDate = getDateClean($event.target.valueAsDate)">
<p>
<code>
myDate: {{ myDate }}</code>
</p>
<button #click="setMyDateToToday">Set date one to today</button>
<button #click="addADayToMyDate">Add a day to my date</button>
</div>