I'm using Pikaday.js like so:
new Pikaday({
field: document.getElementById('top-banner-datepicker'),
minDate: new Date()
I know that the answer lies in this example from the documentation:
var picker = new Pikaday({
field: document.getElementById('datepicker'),
format: 'D/M/YYYY',
toString(date, format) {
// you should do formatting based on the passed format,
// but we will just return 'D/M/YYYY' for simplicity
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
return `${day}/${month}/${year}`;
},
parse(dateString, format) {
// dateString is the result of `toString` method
const parts = dateString.split('/');
const day = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1;
const year = parseInt(parts[2], 10);
return new Date(year, month, day);
}
});
But I can't figure out how to use full day (Monday, Tuesday, Wednesday, etc) and full month names (January, February, etc) instead of the abbreviations (Mon, Tue, Wed... Jan, Feb, Mar... etc)
I don't want to use Moment.JS as it's a giant dependency.
Any help much appreciated!
Thank you
Formatting By default, dates are formatted and parsed using standard JavaScript Date object. If Moment.jsis available in scope, it will be used to format and parse input values. You can pass an additional formatoption to the configuration which will be passed to the momentconstructor.
picker.toString('YYYY-MM-DD') Returns the selected date in a string format. If Moment.jsexists (recommended) then Pikaday can return any format that Moment understands. You can also provide your own toStringfunction and do the formatting yourself.
Change the year being viewed. picker.setMinDate() Update the minimum/earliest date that can be selected. picker.setMaxDate() Update the maximum/latest date that can be selected. picker.setStartRange() Update the range start date. For using two Pikaday instances to select a date range. picker.setEndRange() Update the range end date.
If Moment.jsexists (recommended) then Pikaday can return any format that Moment understands. You can also provide your own toStringfunction and do the formatting yourself. Read more in the formattingsection.
If you wish to format the datepicker field you could use toLocaleString().
For example if you want to get October instead of Oct:
date.toLocaleString('default', {
month: 'long' // use localestring month to get the long month
});
And if you want to get Sunday instead of Sun:
date.toLocaleString('default', { // use localestring weekday to get the long day
weekday: 'long'
});
Example snippet:
var picker = new Pikaday({
field: document.getElementById('datepicker'),
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000, 2020],
format: 'D-M-YYYY',
toString(date, format) {
console.log(date.toLocaleString('default', {
weekday: 'short' // use localestring weekday to get the short abbv of day
}));
console.log(date.toLocaleString('default', {
month: 'short' // use localestring weekday to get the short abbv of month
}));
// you should do formatting based on the passed format,
// but we will just return 'D/M/YYYY' for simplicity
const day = date.getDate();
const daylong = date.toLocaleString('default', { // use localestring weekday to get the long day
weekday: 'long'
});
const month = date.getMonth() + 1;
const monthlong = date.toLocaleString('default', {
month: 'long' // use localestring month to get the long month
});
const year = date.getFullYear();
return `${daylong}, ${monthlong}, ${day} ${year}`; // just format as you wish
}
});
#datepicker {
width: 200px;
}
<link href="https://pikaday.com/css/pikaday.css" rel="stylesheet" />
<script src="https://pikaday.com/pikaday.js"></script>
<label for="datepicker">Date:</label>
<input type="text" id="datepicker">
It's usually pretty easy getting dates into the correct format, but the tricky part usually is getting a date from a string. There's this warning in the Pikaday Read Me:
Be careful, though. If the formatted string that you return cannot be correctly parsed by the
Date.parse
method (or bymoment
if it is available), then you must provide your ownparse
function in the config. This function will be passed the formatted string and the format:
parse(dateString, format = 'YYYY-MM-DD')
Using Date.parse
, can yield irregular results. This is where moment.js
comes in handy as it can handle a variety of formats. The parsing function is used when a person directly types into the input field and maybe elsewhere.
Two approaches could involve using lightweight alternative to moment.js, or a custom formatter.
You can search for moment.js alternatives. I found this repo that lists a few. For this example, I chose luxon, as it seems to be pretty small. You can see all the token it supports here: https://moment.github.io/luxon/docs/manual/parsing.html#table-of-tokens
To help out with parsing, I added this bit, which strips out weekday parsing, just in case if the weekday doesn't match the actual date:
if (format.startsWith('EEEE ')) {
format = format.split(' ').slice(1).join(' ');
dateString = dateString.split(' ').slice(1).join(' ');
}
Here's a working snippet:
var picker = new Pikaday({
field: document.getElementById('datepicker'),
format: 'EEEE LLLL d, yyyy',
toString(date, format) {
return luxon.DateTime.fromJSDate(date).toFormat(format);
},
parse(dateString, format) {
if (format.startsWith('EEEE ')) {
format = format.split(' ').slice(1).join(' ');
dateString = dateString.split(' ').slice(1).join(' ');
}
return luxon.DateTime.fromFormat(dateString, format).toJSDate();
}
});
div {
position: absolute;
bottom: 0;
}
#datepicker {
width: 250px;
}
<link href="https://pikaday.com/css/pikaday.css" rel="stylesheet" />
<script src="https://pikaday.com/pikaday.js"></script>
<script src="https://moment.github.io/luxon/global/luxon.min.js"></script>
<div><label for="datepicker">Date:</label>
<input type="text" id="datepicker">
</div>
For this answer I'll just use the format that you're asking for, but it gets tricky to parse a variety of formats.
To get custom names for months, you can just hard code them in:
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
Alternatively, since you want normal names, you can just programmatically generate them using Intl.DateTimeFormat. This is also useful if you want to have the months and weekdays show up in the user's locale:
var monthFormatter = new Intl.DateTimeFormat([], { month: 'long' });
var months = [... new Array(12)].map((d, i) => monthFormatter.format(new Date(2020, i, 1)));
var dayFormatter = new Intl.DateTimeFormat([], { weekday: 'long' });
var days = [... new Array(7)].map((d, i) =>dayFormatter.format(new Date(2020, 1, 2 + i)));
To access the names, you just use the corresponding index (remember that they're zero based though)
console.log(months[new Date().getMonth()]); // current month
console.log(days[new Date().getDay()]); // current day
Thus your custom format function looks something like this:
toString(date, format) {
// you should do formatting based on the passed format,
// but we will just return 'D/M/YYYY' for simplicity
const day = date.getDate();
const year = date.getFullYear();
const weekday = date.getDay();
const month = date.getMonth(); // remember, this is zero based!
return `${days[weekday]} ${months[month]} ${day}, ${year}`;
},
Here's a custom tailored parsing function for the above format Weekday Month Day, Year
:
parse(dateString, format) {
// split the string into the parts separated by a space
const parts = dateString.trim().split(' ');
var day, month, year, startIndex;
if (parts.length >= 3) {
if (parts.length >= 4) {
// if there's four parts, assume the first part is the weekday, which we don't need to use to convert it to a date
startIndex = 1; // skip the weekday
} else {
// if there's only three parts, assume that the weekday was omitted
startIndex = 0;
}
// look up the month from our prebuilt array. If it isn't found, it'll return -1, otherwise it will return the (zero based) numerical month.
month = months.indexOf(parts[startIndex]);
day = parts[startIndex + 1];
// if there's a comma after the day, remove it
if (day.endsWith(',')) {
day = day.substring(0, day.length - 1);
}
day = +day; // convert the string into a number
year = +parts[startIndex + 2]; // convert the string year into a number
}
if (parts.length < 3 // there is less than 3 parts
|| month === -1 // the month wasn't found
|| isNaN(day) // the day isn't a number
|| isNaN(year)) { // the year isn't a number
return Date.parse(dateString); // fall back to default Date parsing
}
return new Date(year, month, day);
}
All together, it looks like this:
var monthFormatter = new Intl.DateTimeFormat([], { month: 'long' });
var months = [... new Array(12)].map((d, i) => monthFormatter.format(new Date(2020, i, 1)))
var dayFormatter = new Intl.DateTimeFormat([], { weekday: 'long' });
var days = [... new Array(7)].map((d, i) =>dayFormatter.format(new Date(2020, 1, 2 + i)))
// Alternatively you can just hard code these:
// var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
// var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var picker = new Pikaday({
field: document.getElementById('datepicker'),
format: 'D/M/YYYY',
toString(date, format) {
// you should do formatting based on the passed format,
// but we will just return 'D/M/YYYY' for simplicity
const day = date.getDate();
const year = date.getFullYear();
const weekday = date.getDay();
const month = date.getMonth(); // remember, this is zero based!
return `${days[weekday]} ${months[month]} ${day}, ${year}`;
},
parse(dateString, format) {
// split the string into the parts separated by a space
const parts = dateString.trim().split(' ');
var day, month, year, startIndex;
if (parts.length >= 3) {
if (parts.length >= 4) {
// if there's four parts, assume the first part is the weekday, which we don't need to use to convert it to a date
startIndex = 1; // skip the weekday
} else {
// if there's only three parts, assume that the weekday was omitted
startIndex = 0;
}
// look up the month from our prebuilt array. If it isn't found, it'll return -1, otherwise it will return the (zero based) numerical month.
month = months.indexOf(parts[startIndex]);
day = parts[startIndex + 1];
// if there's a comma after the day, remove it
if (day.endsWith(',')) {
day = day.substring(0, day.length - 1);
}
day = +day; // convert the string into a number
year = +parts[startIndex + 2]; // convert the string year into a number
}
if (parts.length < 3 // there is less than 3 parts
|| month === -1 // the month wasn't found
|| isNaN(day) // the day isn't a number
|| isNaN(year)) { // the year isn't a number
return Date.parse(dateString); // fall back to default Date parsing
}
return new Date(year, month, day);
}
});
div {
position: absolute;
bottom: 0;
}
#datepicker {
width: 250px;
}
<link href="https://pikaday.com/css/pikaday.css" rel="stylesheet" />
<script src="https://pikaday.com/pikaday.js"></script>
<div><label for="datepicker">Date:</label>
<input type="text" id="datepicker">
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With