Using Javascript, how would it be possible to detect the format of dates in date input fields (input[type=date])?
Tools like Modernizr only detect the capability of using an HTML5 datepicker (desirable especially for mobile devices, and their UI for selecting dates). However, I haven't been able to find any solution on detecting the format used by the browser.
I have an input field like this:
<input type="date" class="border-radius" min="2013-12-21" max="2015-12-20" data-persist-local="FromDate">
The value is entered with a jQuery call .val()
if it's found in localStorage. I thought that since valid date formats for min and max attributes are in valid ISO format, getting the value of the field would return the same format. It turns out, it doesn't.
Testing on a Chrome browser (31.0.1650.63 m) with Swedish as primary language gives the ISO format, but using the same browser with Danish as primary language reverses the date format to dd-mm-yyyy instead of yyyy-mm-dd. I suspect it's the same for other locales.
I'm not looking to change the input format - and ideally there would be a function to get the date by a consistent "wire format" but I haven't found a way to get anything but the display format.
How do I detect the format of the input field, and consistently convert to a valid Date in JS, and back again?
Using Javascript, how would it be possible to detect the format of dates in date input fields (input[type=date])?
Tools like Modernizr only detect the capability of using an HTML5 datepicker (desirable especially for mobile devices, and their UI for selecting dates). However, I haven't been able to find any solution on detecting the format used by the browser.
I have an input field like this:
<input type="date" class="border-radius" min="2013-12-21" max="2015-12-20" data-persist-local="FromDate">
The value is entered with a jQuery call .val()
if it's found in localStorage. I thought that since valid date formats for min and max attributes are in valid ISO format, getting the value of the field would return the same format. It turns out, it doesn't.
Testing on a Chrome browser (31.0.1650.63 m) with Swedish as primary language gives the ISO format, but using the same browser with Danish as primary language reverses the date format to dd-mm-yyyy instead of yyyy-mm-dd. I suspect it's the same for other locales.
I'm not looking to change the input format - and ideally there would be a function to get the date by a consistent "wire format" but I haven't found a way to get anything but the display format.
How do I detect the format of the input field, and consistently convert to a valid Date in JS, and back again?
Share Improve this question edited May 23, 2017 at 11:52 CommunityBot 11 silver badge asked Dec 20, 2013 at 12:42 CalleCalle 1,8001 gold badge18 silver badges34 bronze badges 2- When getting the value with javascript or when submitting it with a form, the HTML5 spec claims it should always be in RFC 3339/ISO 8601 "wire format": YYYY-MM-DD, however how it's displayed to the user is up to the browser, and some browsers do use the locale settings to display the date in the users local date format. – adeneo Commented Dec 20, 2013 at 12:47
- @adeneo thanks but I'm after getting the value in a valid format without sending the form. This is for an AJAX call, so the value is parsed by Javascript and added as a param to the call. – Calle Commented Dec 20, 2013 at 12:52
2 Answers
Reset to default 14ideally there would be a function to get the date by a consistent "wire format"
There's a input.valueAsDate
method which returns a Date
object reflecting the input's current value.
According to experimentation (edit: with Chrome & Opera desktop versions on 2013-12-20), it appears that the displayed value of date inputs follows the same format as that returned by new Date().toLocaleDateString()
, at least in Chrome.
There are then 3 representations of a date in action on the front-end:
- The Javascript date object
- The ISO date string for the input's attributes and ostensible value
- The date string represented to the user by the input.
To get any one of these from any of the other:
// From Javascript `Date` object to input value:
new Date().toISOString().substr( 0, 10 );
// From Javascript `Date` object to input display:
new Date().toLocaleDateString();
// From input value to Javascript `Date`:
input.valueAsDate;
// From input value to input display (step 3, then step 2):
input.valueAsDate.toLocaleDateString();
// From input display to Javascript `Date` object:
new Date( input.valueAsDate );
// From input display to input value (step 5, then step 1):
new Date( input.valueAsDate ).toISOString().substr( 0, 10 );
EDIT:
The above happens to work on Chrome. Desktop Safari 5.1.7 displays time in ISO format, meaning what you input is what the user sees. iOS Safari displays a dropdown with abbreviated month names in the format dd mmm yyyy
. So it seems there is no standard.
Here's a little function that will give you the right conversions for desktop Chrome & Opera only:
var dateInput = ( function inputDateClosure(){
// Type checking
function getType( x ){
return Object.prototype.toString.call( x );
}
function isDate( x ){
return getType( x ) === '[object Date]';
}
function isInput( x ){
return getType( x ) === '[object HTMLInputElement]' || '[object Object]' && Object.prototype.hasOwnProperty.call( x, 'value' );
}
function isString( x ){
return getType( x ) === '[object String]';
}
function fromDateToValue( x ){
return x.toISOString().substr( 0, 10 );
}
function fromDateToString( x ){
return x.toLocaleDateString();
}
function fromInputToDate( x ){
return x.valueAsDate;
}
function fromStringToDate( x ){
return new Date( x.valueAsDate );
}
return function( x ){
if( isDate( x ) ){
return {
asDate : x,
asValue : fromDateToValue( x ),
asString : fromDateToString( x )
}
}
else if( isString( x ) ){
return {
asDate : fromStringToDate( x ),
asValue : fromDateToValue( fromStringToDate( x ) ),
asString : fromStringToDate( fromDateToString( x ) )
}
}
else if( isInput( x ) ){
return {
asDate : fromInputToDate( x ),
asValue : fromDateToValue( fromInputToDate( x ) ),
asString : fromDateToString( fromInputToDate( x ) )
}
}
}
}() );
I think I got an easier solution. Not sure if it will work at any browser, but assuming that javascript date function uses same local format, this would work:
$(".date").on("change", function () {
var selectedDate = new Date(jQuery(this).val());
var selectedDateFormat = selectedDate.toLocaleDateString()
.replace(selectedDate.getDate(), "DD")
.replace(selectedDate.getMonth()+1, "MM")
.replace(selectedDate.getFullYear(), "YYYY");
console.log(selectedDateFormat);
});
But anyway, reaching at this point we might not need this, as the point is to use any browser date format, and send it on the format we desire if Im not wrong. In this case I would do it in another way wich is the following:
$(".date").on("change", function () {
var selectedDate = new Date(jQuery(this).val());
this.setAttribute('value',
(selectedDate.getMonth() + 1) +
'/' + selectedDate.getDate() +
'/' + selectedDate.getFullYear());
});