如何解决 jQuery UI Datepicker 的手动日期输入?
Posted
技术标签:
【中文标题】如何解决 jQuery UI Datepicker 的手动日期输入?【英文标题】:How to resolve manual date entry for jQuery UI Datepicker? 【发布时间】:2019-08-04 04:40:57 【问题描述】:我的页面上有一个 jQuery UI 日期选择器,应该可以手动输入日期。为了使用户更容易,还应该可以输入简短的日期形式(仅限日和月),一旦焦点离开字段,它将在下一个可能的日期解决。
示例(德国日期格式):
29092019 应该解析为 29.09.2019
2909 应解析为 29.09.2019
当今年 3 月 1 日已经结束时,0103 应该解决到 01.03.2020。
我该如何解决这样的问题?
$( function()
$("#myDate").datepicker(
dateFormat : "dd.mm.yy"
);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<input type="text" id="myDate" />
【问题讨论】:
"29042019 应该解析为 24.09.2019" 对吗?不应该是24092019 -> 24.09.2019
吗?
你是对的,这是一个错字。立即改变!
好的,感谢给出的答案,我们已经非常接近了。我只需要找出如何验证解析的日期!目前可以获得诸如例如“40.15.2050”或“30.02.2019”,不应该这样。有什么想法吗?
看看当你在控制台中运行它时会发生什么:new Date("30.02.2019")
- 它返回 Invalid Date
- 使用它进行验证。您应该阅读 javascript 的 Date 对象。
**** 此问题已结束 - 无需更多答案! **** 赏金将转到@scott6,感谢他在过去几周的惊人帮助。我只需要等待 24 小时,直到我可以奖励他......
【参考方案1】:
这是一种方法 - 下面是 cmets:
// Some sample dates
let userDates = [
"29092019",
"2909",
"0103",
"1303",
"1403"
];
// Run the sample dates through parseUserDate()
for (let userDate of userDates)
console.log(userDate + ":");
console.log(parseUserDate(userDate));
function parseUserDate(dateStr)
let parsedDate;
// If it's 8 characters long, slice into YYYY-MM-DD
if (dateStr.length === 8)
let dateSplit = [
dateStr.slice(4),
dateStr.slice(2, 4),
dateStr.slice(0, 2)
];
parsedDate = new Date(dateSplit.join("-"));
// 4 characters long - slice into MM-DD and prefix with YYYY later.
else if (dateStr.length === 4)
let monthDay = [
dateStr.slice(2, 4),
dateStr.slice(0, 2)
].join("-");
// The current date - this is used to check if the user date should be next year.
let now = new Date();
// MM-DD with the current year.
let userDateCurrentYear = new Date(now.getFullYear() + "-" + monthDay);
// MM-DD with next year.
let userDateNextYear = new Date((now.getFullYear() + 1) + "-" + monthDay);
// If the current date is past the MM-DD this year, set parsedDate to next year's date.
if (now > userDateCurrentYear)
parsedDate = userDateNextYear;
else
parsedDate = userDateCurrentYear;
return parsedDate;
【讨论】:
如何让解析器灵活适应不同的日期格式? @JonSnow 您可以在函数调用中添加一个附加参数:parseUserDate(dateStr, dateFormat)
然后相应地拆分dateStr
。【参考方案2】:
试试这个..
要与 jQuery 的日期选择器集成,你可以像下面那样做
编辑:
添加无效日期验证,并在无效日期返回空字符串 修复日期验证:添加闰日验证 修复 monDt 变量(在 JS 中添加 getMonth+1 作为月份以 0 开头)$(function()
$('.datepicker').datepicker(
dateFormat:'dd.mm.yy'
);
$('.datepicker').on('blur',function()parseInputDate(this););
)
function parseInputDate(elm)
var currDate = new Date(),
monDt = (('0'+(currDate.getMonth()+1)).slice(-2)+('0'+currDate.getDate()).slice(-2)), // get current month+date to compare
inputVal = $(elm).val().match(/\d2/gi); // split date components into array of [dd,mm,yy,yy]
// another date validation, by comparing parameters and date object result
var isValidDate = function(yyyy,mm,dd)
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
return (dt.getFullYear()+'-'+('0'+(dt.getMonth()+1)).slice(-2)+'-'+('0'+dt.getDate()).slice(-2)) == yyyy+'-'+mm+'-'+dd;
if (inputVal!=null && inputVal.length>=2)
var year = currDate.getFullYear();
if (monDt>(inputVal[1]+inputVal[0])) year++;
// generate formatted text based on date component count
// add date validation to catch invalid dates using (new Date('yyyy-mm-dd')).getTime() which will return NaN on invalid date
var result = (inputVal.length==2 && isValidDate(year,inputVal[1],inputVal[0]) && inputVal[0]+'.'+inputVal[1]+'.'+year) ||
(inputVal.length==3 && isValidDate('20'+inputVal[2],inputVal[1],inputVal[0]) && inputVal[0]+'.'+inputVal[1]+'.20'+inputVal[2]) ||
(inputVal.length==4 && isValidDate(inputVal[2]+inputVal[3],inputVal[1],inputVal[0]) && inputVal[0]+'.'+inputVal[1]+'.'+inputVal[2]+inputVal[3]) ||
''; // set empty on invalid dates
$(elm).val(result);
else $(elm).val('');
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<input type="text" id="myDate" class="datepicker" />
这是具有一些约束的多个日期选择器的示例。您可以根据需要进行调整:)
&根据日期选择器的格式返回日期字符串
$(function()
initDatePicker();
)
function initDatePicker()
// do a loop for custom property on each element
$('.datepicker').each(function()
// you can find available formats here : http://api.jqueryui.com/datepicker/#utility-formatDate
$(this).datepicker(
dateFormat:'yy.mm.dd'
);
// set minimum date from data attribute.
if (typeof $(this).data('mindate') != 'undefined')
$(this).datepicker('option','minDate',$(this).data('mindate'));
// set maximum date from data attribute.
if (typeof $(this).data('maxdate') != 'undefined')
$(this).datepicker('option','maxDate',$(this).data('maxdate'));
$(this).on('change',function()
parseInputDate(this);
// now, set date relations :)
if (typeof $(this).data('nextelem') != 'undefined')
$($(this).data('nextelem')).datepicker( "option", "minDate", getDate( this ) );
if (typeof $(this).data('prevelem') != 'undefined')
$($(this).data('prevelem')).datepicker( "option", "maxDate", getDate( this ) );
);
);
// get date function taken from : http://jqueryui.com/datepicker/#date-range
function getDate( element )
var date;
try
date = $.datepicker.parseDate( $(element).datepicker('option','dateFormat'), element.value );
catch( error )
date = null;
return date;
function parseInputDate(elm)
var currDate = new Date(),
monDt = (('0'+(currDate.getMonth()+1)).slice(-2)+('0'+currDate.getDate()).slice(-2)), // get current month+date to compare
inputVal = $(elm).val().match(/\d2/gi), // split date components into array of [dd,mm,yy,yy]
format = $(elm).datepicker("option", "dateFormat"); // get current element's datepicker format
// check if it's already a valid entry, then do nothing
if ($(elm).val() == $.datepicker.formatDate(format,$(elm).datepicker('getDate'))) return;
var isValidDate = function(yyyy,mm,dd)
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
return (dt.getFullYear()+'-'+('0'+(dt.getMonth()+1)).slice(-2)+'-'+('0'+dt.getDate()).slice(-2)) == yyyy+'-'+mm+'-'+dd;
var getDateString = function(yyyy,mm,dd)
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
// get datepicker format & get date string using datepicker's formatDate function
return $.datepicker.formatDate($(elm).datepicker("option", "dateFormat"),dt);
if (inputVal!=null && inputVal.length>=2)
var year = currDate.getFullYear();
if (monDt>(inputVal[1]+inputVal[0])) year++;
// generate formatted text based on date component count
// add date validation to catch invalid dates, & generate date string according to datepicker format
var result = (inputVal.length==2 && isValidDate(year,inputVal[1],inputVal[0]) && getDateString(year,inputVal[1],inputVal[0])) ||
(inputVal.length==3 && isValidDate('20'+inputVal[2],inputVal[1],inputVal[0]) && getDateString('20'+inputVal[2],inputVal[1],inputVal[0])) ||
(inputVal.length==4 && isValidDate(inputVal[2]+inputVal[3],inputVal[1],inputVal[0]) && getDateString(inputVal[2]+inputVal[3],inputVal[1],inputVal[0])) ||
''; // set empty on invalid dates
$(elm).val(result);
else $(elm).val('');
// add validation to invalidate out-of-range value
// get selected/entered date
var cdate = $(elm).datepicker('getDate');
// get range
var minDateAttr = $(elm).datepicker("option", "minDate");
var maxDateAttr = $(elm).datepicker("option", "maxDate");
// get datepicker instance
var inst = $('#myDate').data("datepicker");
var isValid = false;
if (minDateAttr!=null)
// get range as date object
var minDateObj = $.datepicker._determineDate(inst, minDateAttr, new Date());
if (minDateObj<=cdate) isValid = true
if (isValid && maxDateAttr!=null)
// get range as date object
var maxDateObj = $.datepicker._determineDate(inst, maxDateAttr, new Date());
if (maxDateObj>=cdate) isValid = true
if (!isValid) $(elm).val('');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
Dates :
<input type="text" id="myDate" class="datepicker" data-nextelem="#myDate2" data-mindate="-20" maxlength="10" style="width:80px" /> -
<input type="text" id="myDate2" class="datepicker" data-prevelem="#myDate" data-nextelem="#myDate3" maxlength="10" style="width:80px"/> -
<input type="text" id="myDate3" class="datepicker" data-prevelem="#myDate2" data-maxdate="+2y" maxlength="10" style="width:80px"/>
【讨论】:
这个示例效果很好,几乎与描述的一样。只缺少一件小事:输入字段也应该与标准 jQuery UI 日期选择器一起使用。应该可以使用选择器或直接输入。当我将您的函数添加到我当前的文本框中时,它仅适用于日期选择器,但不适用于直接输入。我已经使用选择器“.datepicker”以及“.hasDatepicker”进行了测试。第一个是 jQuery datepicker 用来生成选择器的类,第二个是生成的。 几乎不错!!我只需要找出如何验证解析的日期!目前有可能获得像例如“40.15.2050”或“30.02.2019”,不应该是这样。 @SchweizerSchoggi 应该没有任何问题。请查看我的更新答案:) 是的,这行得通。唯一剩下的问题是,用户仍然可以输入无效日期 @SchweizerSchoggi : 哎呀.. 抱歉,getMonth 应该加 1.. 答案已更新 :)以上是关于如何解决 jQuery UI Datepicker 的手动日期输入?的主要内容,如果未能解决你的问题,请参考以下文章
如何触发 jQuery UI DatePicker onclick?
Rails,如何在特定页面上显示 jquery-ui-datepicker 日历?
如何通过 npm jquery-ui-datepicker-with-i18n 导入 laravel?