input输入日期时间,自动格式化组件/工具
组件/工具使用说明
只能输入日期时间,不能选择 日期时间格式 yyyy-MM-dd HH:mm:ss 基于VUE框架 输入效果见下图
组件/工具解决的痛点
组件库日期时间组件,选日期时间很花时间 例如想快速得到 2021-12-14 20:10:22,需要先选日期,然后再选时间 可以快速输入目标日期和时间,不用关注日期和时间分隔符 - : 空格
组件/工具需要实现的功能
只允许输入数字 限制输入日期范围 按键删除时自动补入合法数字 输入数字自动删除后一位数字 输入和删除时光标位置移动 检测复制粘贴到输入框的内容 输入完成时,按回车键自动失焦 处理输入的不符合规则的日期
功能代码实现
< input v-model = " inOutTime" @focus = " onFocus" @blur = " onBlur" @input = " inputDateTime($event)" @keydown = " onKeydown" ref = " inputDate" class = " inputDate" :class = " [`xxxx-${size}`]" />
< style scoped >
.inputDate { width : 100%; height : 40px; line-height : 40px; padding-left : 10px; border : none; outline : none; border-radius : 4px; border : 1px solid #dcdfe6;
}
.inputDate:focus { border-color : #409eff;
}
.xxxx-default { height : 40px; line-height : 40px;
}
.xxxx-medium { height : 36px; line-height : 36px;
}
.xxxx-small { height : 32px; line-height : 32px;
}
.xxxx-mini { height : 28px; line-height : 28px;
}
</ style>
function inputDateTime ( ev ) { let selectionStart = this . $refs. inputDate. selectionStart; let selectionEnd = this . $refs. inputDate. selectionEnd; console. log ( ev. target. value) ; }
function dateToStr ( datetime ) { if ( ! datetime) { return '' ; } let year = datetime. getFullYear ( ) ; let month = datetime. getMonth ( ) + 1 ; let date = datetime. getDate ( ) ; let hour = datetime. getHours ( ) ; let minutes = datetime. getMinutes ( ) ; let second = datetime. getSeconds ( ) ; if ( month < 10 ) { month = "0" + month; } if ( date < 10 ) { date = "0" + date; } if ( hour < 10 ) { hour = "0" + hour; } if ( minutes < 10 ) { minutes = "0" + minutes; } if ( second < 10 ) { second = "0" + second; } let time = year + "-" + month + "-" + date + " " + hour + ":" + minutes + ":" + second; return time;
}
const del = { 4 : '-' , 7 : '-' , 10 : ' ' , 13 : ':' , 16 : ':'
}
export function formatStringDate ( str, selectionStart ) { if ( ! / ^[0-9-:\s]{18,20}$ / . test ( str) || str. length < 18 ) { return { newDate : dateToStr ( new Date ( ) ) , startB : 19 } ; } let numStr = str. replace ( / -|:|s|\s / g , '' ) ; if ( numStr. length < 13 ) { return { newDate : dateToStr ( new Date ( ) ) , startB : 19 } ; } const num = / ^[0-9]$ / ; let startB = selectionStart; selectionStart = selectionStart - 1 ; let arrDate = str. split ( '' ) ; if ( arrDate. length < 19 ) { if ( del[ startB] ) { arrDate. splice ( startB, 0 , del[ startB] ) } else { let obj = { 0 : '2' , 1 : '0' , 5 : '0' } arrDate. splice ( startB, 0 , obj[ startB] || '1' ) } str = arrDate. join ( '' ) ; } else { const str2 = str. slice ( selectionStart, selectionStart + 1 ) ; if ( ! num. test ( str2) ) { arrDate. splice ( selectionStart, 1 ) ; return { newDate : arrDate. join ( '' ) , startB} ; } const str3 = str. slice ( selectionStart + 1 , selectionStart + 2 ) ; const reg1 = / ^(-|:|s|\s)$ / ; if ( reg1. test ( str3) ) { arrDate. splice ( selectionStart + 2 , 1 ) ; startB++ ; } if ( num. test ( str3) ) { arrDate. splice ( selectionStart + 1 , 1 ) ; } } let str1 = arrDate. join ( '' ) . replace ( / -|:|s|\s / g , '' ) ; const regDate = / ^20([0-9][0-9])-(0[1-9]|1[0-2])-([0-2][0-9]|3[01])$ / ; const regTime = / ^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] / ; let ymd = '' ; if ( str1. length >= 8 ) { ymd = ( str1) . match ( / (\d{4})(\d{2})(\d{2}) / ) . filter ( ( item, index ) => index > 0 ) . join ( '-' ) ; } if ( ! regDate. test ( ymd) ) { const reArr = str. split ( '' ) ; reArr. splice ( selectionStart, 1 ) ; return { newDate : reArr. join ( '' ) , startB} ; } let hmsStr = ( str1) . slice ( 8 ) , hms; if ( hmsStr. length >= 6 ) { hms = hmsStr. match ( / (\d{2})(\d{2})(\d{2}) / ) . filter ( ( item, index ) => index > 0 ) . join ( ':' ) ; } if ( ! regTime. test ( hms) ) { const reArr = str. split ( '' ) ; reArr. splice ( selectionStart, 1 ) ; return { newDate : reArr. join ( '' ) , startB} ; } return { newDate : ` ${ ymd} ${ hms} ` , startB} ;
}
function strDateTime ( str ) { var reg = / ^(\d{4})(-|\/)(\d{2})\2(\d{2}) (\d{2}):(\d{2}):(\d{2})$ / ; var r = str. match ( reg) ; if ( r == null ) return false ; var d = new Date ( r[ 1 ] , r[ 3 ] - 1 , r[ 4 ] , r[ 5 ] , r[ 6 ] , r[ 7 ] ) ; return ( d. getFullYear ( ) === Number ( r[ 1 ] ) && ( d. getMonth ( ) + 1 ) === Number ( r[ 3 ] ) && d. getDate ( ) === Number ( r[ 4 ] ) && d. getHours ( ) === Number ( r[ 5 ] ) && d. getMinutes ( ) === Number ( r[ 6 ] ) && d. getSeconds ( ) === Number ( r[ 7 ] ) ) ;
}
this . $refs. inputDate. setSelectionRange ( selectionStart, selectionStart) ;
< template> < div> < input v- model= "inOutTime" @focus= "onFocus" @blur= "onBlur" @input= "inputDateTime($event)" @keydown= "onKeydown" ref= "inputDate" class = "inputDate" : class = "[`xxxx-${size}`]" / > < / div>
< / template>
< script>
import { formatStringDate } from "utils" ;
import { dateToStr } from "public" ;
export default { props : { initTime : { type : String, required : true , default : dateToStr ( new Date ( ) ) } , size : { type : String, default : 'small' } } , data ( ) { return { inOutTime : this . initTime} } , methods : { inputDateTime ( ev ) { let selectionStart = this . $refs. inputDate. selectionStart; const options = formatStringDate ( ev. target. value, selectionStart) ; this . inOutTime = options. newDate; if ( options. startB !== selectionStart) { selectionStart = options. startB; } this . $nextTick ( ( ) => { this . $refs. inputDate. setSelectionRange ( selectionStart, selectionStart) ; } ) } , onFocus ( ) { } , onBlur ( ) { if ( ! this . strDateTime ( this . inOutTime) ) { this . inOutTime = dateToStr ( new Date ( ) ) ; } } , onKeydown ( e ) { let keyCode = window. event ? e. keyCode : e. which; if ( keyCode === 13 ) { this . $refs. inputDate. blur ( ) ; if ( ! this . strDateTime ( this . inOutTime) ) { this . inOutTime = dateToStr ( new Date ( ) ) ; } this . $emit ( 'getTime' , this . inOutTime) ; } } , strDateTime ( str ) { var reg = / ^(\d{4})(-|\/)(\d{2})\2(\d{2}) (\d{2}):(\d{2}):(\d{2})$ / ; var r = str. match ( reg) ; if ( r == null ) return false ; var d = new Date ( r[ 1 ] , r[ 3 ] - 1 , r[ 4 ] , r[ 5 ] , r[ 6 ] , r[ 7 ] ) ; return ( d. getFullYear ( ) === Number ( r[ 1 ] ) && ( d. getMonth ( ) + 1 ) === Number ( r[ 3 ] ) && d. getDate ( ) === Number ( r[ 4 ] ) && d. getHours ( ) === Number ( r[ 5 ] ) && d. getMinutes ( ) === Number ( r[ 6 ] ) && d. getSeconds ( ) === Number ( r[ 7 ] ) ) ; } }
}
< / script>
补充说明
若需要实时获取处理之后的日期时间,可以在组件上使用v-model,具体代码请参考vue文档 组件基于VUE编写,核心方法formatStringDate不依赖框架,原生JS、react均可使用