@@ -233,112 +233,28 @@ $.extend(Timepicker.prototype, {
233233 // parse the time string from input value or _setTime
234234 //########################################################################
235235 _parseTime : function ( timeString , withDate ) {
236- var regstr = this . _defaults . timeFormat . toString ( )
237- . replace ( / h { 1 , 2 } / ig, '(\\d?\\d)' )
238- . replace ( / m { 1 , 2 } / ig, '(\\d?\\d)' )
239- . replace ( / s { 1 , 2 } / ig, '(\\d?\\d)' )
240- . replace ( / l { 1 } / ig, '(\\d?\\d?\\d)' )
241- . replace ( / t { 1 , 2 } / ig, this . _getPatternAmpm ( ) )
242- . replace ( / z { 1 } / ig, '(z|[-+]\\d\\d:?\\d\\d)?' )
243- . replace ( / \s / g, '\\s?' ) + this . _defaults . timeSuffix + '$' ,
244- order = this . _getFormatPositions ( ) ,
245- ampm = '' ,
246- treg ;
247-
248- if ( ! this . inst ) this . inst = $ . datepicker . _getInst ( this . $input [ 0 ] ) ;
249-
250- if ( withDate || ! this . _defaults . timeOnly ) {
251- // the time should come after x number of characters and a space.
252- // x = at least the length of text specified by the date format
236+ if ( withDate || ! this . _defaults . timeOnly )
237+ {
238+ if ( ! this . inst ) this . inst = $ . datepicker . _getInst ( this . $input [ 0 ] ) ;
253239 var dp_dateFormat = $ . datepicker . _get ( this . inst , 'dateFormat' ) ;
254- // escape special regex characters in the seperator
255- var specials = new RegExp ( "[.*+?|()\\[\\]{}\\\\]" , "g" ) ;
256- regstr = '^.{' + dp_dateFormat . length + ',}?' + this . _defaults . separator . replace ( specials , "\\$&" ) + regstr ;
257- }
258-
259- treg = timeString . match ( new RegExp ( regstr , 'i' ) ) ;
260-
261- if ( treg ) {
262- if ( order . t !== - 1 ) {
263- if ( treg [ order . t ] === undefined || treg [ order . t ] . length === 0 ) {
264- ampm = '' ;
265- this . ampm = '' ;
266- } else {
267- ampm = $ . inArray ( treg [ order . t ] . toUpperCase ( ) , this . amNames ) !== - 1 ? 'AM' : 'PM' ;
268- this . ampm = this . _defaults [ ampm == 'AM' ? 'amNames' : 'pmNames' ] [ 0 ] ;
269- }
270- }
271-
272- if ( order . h !== - 1 ) {
273- if ( ampm == 'AM' && treg [ order . h ] == '12' )
274- this . hour = 0 ; // 12am = 0 hour
275- else if ( ampm == 'PM' && treg [ order . h ] != '12' )
276- this . hour = ( parseFloat ( treg [ order . h ] ) + 12 ) . toFixed ( 0 ) ; // 12pm = 12 hour, any other pm = hour + 12
277- else this . hour = Number ( treg [ order . h ] ) ;
278- }
279-
280- if ( order . m !== - 1 ) this . minute = Number ( treg [ order . m ] ) ;
281- if ( order . s !== - 1 ) this . second = Number ( treg [ order . s ] ) ;
282- if ( order . l !== - 1 ) this . millisec = Number ( treg [ order . l ] ) ;
283- if ( order . z !== - 1 && treg [ order . z ] !== undefined ) {
284- var tz = treg [ order . z ] . toUpperCase ( ) ;
285- switch ( tz . length ) {
286- case 1 : // Z
287- tz = this . _defaults . timezoneIso8601 ? 'Z' : '+0000' ;
288- break ;
289- case 5 : // +hhmm
290- if ( this . _defaults . timezoneIso8601 )
291- tz = tz . substring ( 1 ) == '0000'
292- ? 'Z'
293- : tz . substring ( 0 , 3 ) + ':' + tz . substring ( 3 ) ;
294- break ;
295- case 6 : // +hh:mm
296- if ( ! this . _defaults . timezoneIso8601 )
297- tz = tz == 'Z' || tz . substring ( 1 ) == '00:00'
298- ? '+0000'
299- : tz . replace ( / : / , '' ) ;
300- else if ( tz . substring ( 1 ) == '00:00' )
301- tz = 'Z' ;
302- break ;
303- }
304- this . timezone = tz ;
305- }
306-
307- return true ;
308-
309- }
310- return false ;
311- } ,
312-
313- //########################################################################
314- // pattern for standard and localized AM/PM markers
315- //########################################################################
316- _getPatternAmpm : function ( ) {
317- var markers = [ ] ,
318- o = this . _defaults ;
319- if ( o . amNames )
320- $ . merge ( markers , o . amNames ) ;
321- if ( o . pmNames )
322- $ . merge ( markers , o . pmNames ) ;
323- markers = $ . map ( markers , function ( val ) { return val . replace ( / [ . * + ? | ( ) \[ \] { } \\ ] / g, '\\$&' ) ; } ) ;
324- return '(' + markers . join ( '|' ) + ')?' ;
325- } ,
326-
327- //########################################################################
328- // figure out position of time elements.. cause js cant do named captures
329- //########################################################################
330- _getFormatPositions : function ( ) {
331- var finds = this . _defaults . timeFormat . toLowerCase ( ) . match ( / ( h { 1 , 2 } | m { 1 , 2 } | s { 1 , 2 } | l { 1 } | t { 1 , 2 } | z ) / g) ,
332- orders = { h : - 1 , m : - 1 , s : - 1 , l : - 1 , t : - 1 , z : - 1 } ;
333-
334- if ( finds )
335- for ( var i = 0 ; i < finds . length ; i ++ )
336- if ( orders [ finds [ i ] . toString ( ) . charAt ( 0 ) ] == - 1 )
337- orders [ finds [ i ] . toString ( ) . charAt ( 0 ) ] = i + 1 ;
338-
339- return orders ;
240+ try {
241+ var parseRes = parseDateTimeInternal ( dp_dateFormat , this . _defaults . timeFormat , timeString , $ . datepicker . _getFormatConfig ( this . inst ) , this . _defaults ) ;
242+ if ( ! parseRes . timeObj ) return false ;
243+ $ . extend ( this , parseRes . timeObj ) ;
244+ } catch ( err )
245+ {
246+ return false ;
247+ }
248+ return true ;
249+ }
250+ else
251+ {
252+ var timeObj = $ . datepicker . parseTime ( this . _defaults . timeFormat , timeString , this . _defaults ) ;
253+ $ . extend ( this , parseRes . timeObj ) ;
254+ return true ;
255+ }
340256 } ,
341-
257+
342258 //########################################################################
343259 // generate and inject html for timepicker into ui datepicker
344260 //########################################################################
@@ -934,6 +850,117 @@ $.fn.extend({
934850 }
935851} ) ;
936852
853+ $ . datepicker . parseDateTime = function ( dateFormat , timeFormat , dateTimeString , dateSettings , timeSettings ) {
854+ var parseRes = parseDateTimeInternal ( dateFormat , timeFormat , dateTimeString , dateSettings , timeSettings ) ;
855+ if ( parseRes . timeObj )
856+ {
857+ var t = parseRes . timeObj ;
858+ parseRes . date . setHours ( t . hour , t . minute , t . second , t . millisec ) ;
859+ }
860+
861+ return parseRes . date ;
862+ }
863+
864+ $ . datepicker . parseTime = function ( timeFormat , timeString , options ) {
865+
866+ //########################################################################
867+ // pattern for standard and localized AM/PM markers
868+ //########################################################################
869+ var getPatternAmpm = function ( amNames , pmNames ) {
870+ var markers = [ ] ;
871+ if ( amNames )
872+ $ . merge ( markers , amNames ) ;
873+ if ( pmNames )
874+ $ . merge ( markers , pmNames ) ;
875+ markers = $ . map ( markers , function ( val ) { return val . replace ( / [ . * + ? | ( ) \[ \] { } \\ ] / g, '\\$&' ) ; } ) ;
876+ return '(' + markers . join ( '|' ) + ')?' ;
877+ }
878+
879+ //########################################################################
880+ // figure out position of time elements.. cause js cant do named captures
881+ //########################################################################
882+ var getFormatPositions = function ( timeFormat ) {
883+ var finds = timeFormat . toLowerCase ( ) . match ( / ( h { 1 , 2 } | m { 1 , 2 } | s { 1 , 2 } | l { 1 } | t { 1 , 2 } | z ) / g) ,
884+ orders = { h : - 1 , m : - 1 , s : - 1 , l : - 1 , t : - 1 , z : - 1 } ;
885+
886+ if ( finds )
887+ for ( var i = 0 ; i < finds . length ; i ++ )
888+ if ( orders [ finds [ i ] . toString ( ) . charAt ( 0 ) ] == - 1 )
889+ orders [ finds [ i ] . toString ( ) . charAt ( 0 ) ] = i + 1 ;
890+
891+ return orders ;
892+ }
893+
894+ var o = extendRemove ( extendRemove ( { } , $ . timepicker . _defaults ) , options || { } ) ;
895+
896+ var regstr = '^' + timeFormat . toString ( )
897+ . replace ( / h { 1 , 2 } / ig, '(\\d?\\d)' )
898+ . replace ( / m { 1 , 2 } / ig, '(\\d?\\d)' )
899+ . replace ( / s { 1 , 2 } / ig, '(\\d?\\d)' )
900+ . replace ( / l { 1 } / ig, '(\\d?\\d?\\d)' )
901+ . replace ( / t { 1 , 2 } / ig, getPatternAmpm ( o . amNames , o . pmNames ) )
902+ . replace ( / z { 1 } / ig, '(z|[-+]\\d\\d:?\\d\\d)?' )
903+ . replace ( / \s / g, '\\s?' ) + o . timeSuffix + '$' ,
904+ order = getFormatPositions ( timeFormat ) ,
905+ ampm = '' ,
906+ treg ;
907+
908+ treg = timeString . match ( new RegExp ( regstr , 'i' ) ) ;
909+
910+ var resTime = { hour : 0 , minute : 0 , second : 0 , millisec : 0 } ;
911+
912+ if ( treg ) {
913+ if ( order . t !== - 1 ) {
914+ if ( treg [ order . t ] === undefined || treg [ order . t ] . length === 0 ) {
915+ ampm = '' ;
916+ resTime . ampm = '' ;
917+ } else {
918+ ampm = $ . inArray ( treg [ order . t ] , o . amNames ) !== - 1 ? 'AM' : 'PM' ;
919+ resTime . ampm = o [ ampm == 'AM' ? 'amNames' : 'pmNames' ] [ 0 ] ;
920+ }
921+ }
922+
923+ if ( order . h !== - 1 ) {
924+ if ( ampm == 'AM' && treg [ order . h ] == '12' )
925+ resTime . hour = 0 ; // 12am = 0 hour
926+ else if ( ampm == 'PM' && treg [ order . h ] != '12' )
927+ resTime . hour = parseInt ( treg [ order . h ] , 10 ) + 12 ; // 12pm = 12 hour, any other pm = hour + 12
928+ else resTime . hour = Number ( treg [ order . h ] ) ;
929+ }
930+
931+ if ( order . m !== - 1 ) resTime . minute = Number ( treg [ order . m ] ) ;
932+ if ( order . s !== - 1 ) resTime . second = Number ( treg [ order . s ] ) ;
933+ if ( order . l !== - 1 ) resTime . millisec = Number ( treg [ order . l ] ) ;
934+ if ( order . z !== - 1 && treg [ order . z ] !== undefined ) {
935+ var tz = treg [ order . z ] . toUpperCase ( ) ;
936+ switch ( tz . length ) {
937+ case 1 : // Z
938+ tz = o . timezoneIso8601 ? 'Z' : '+0000' ;
939+ break ;
940+ case 5 : // +hhmm
941+ if ( o . timezoneIso8601 )
942+ tz = tz . substring ( 1 ) == '0000'
943+ ? 'Z'
944+ : tz . substring ( 0 , 3 ) + ':' + tz . substring ( 3 ) ;
945+ break ;
946+ case 6 : // +hh:mm
947+ if ( ! o . timezoneIso8601 )
948+ tz = tz == 'Z' || tz . substring ( 1 ) == '00:00'
949+ ? '+0000'
950+ : tz . replace ( / : / , '' ) ;
951+ else if ( tz . substring ( 1 ) == '00:00' )
952+ tz = 'Z' ;
953+ break ;
954+ }
955+ resTime . timezone = tz ;
956+ }
957+
958+ return resTime ;
959+
960+ }
961+ return null ;
962+ } ,
963+
937964//########################################################################
938965// format the time all pretty...
939966// format = string format of the time
@@ -1240,21 +1267,8 @@ $.datepicker._getDateDatepicker = function(target, noDefault) {
12401267//#######################################################################################
12411268$ . datepicker . _base_parseDate = $ . datepicker . parseDate ;
12421269$ . datepicker . parseDate = function ( format , value , settings ) {
1243- var date ;
1244- try {
1245- date = this . _base_parseDate ( format , value , settings ) ;
1246- } catch ( err ) {
1247- if ( err . indexOf ( ":" ) >= 0 ) {
1248- // Hack! The error message ends with a colon, a space, and
1249- // the "extra" characters. We rely on that instead of
1250- // attempting to perfectly reproduce the parsing algorithm.
1251- date = this . _base_parseDate ( format , value . substring ( 0 , value . length - ( err . length - err . indexOf ( ':' ) - 2 ) ) , settings ) ;
1252- } else {
1253- // The underlying error was not related to the time
1254- throw err ;
1255- }
1256- }
1257- return date ;
1270+ var splitRes = splitDateTime ( dateFormat , dateTimeString , dateSettings ) ;
1271+ return $ . datepicker . _base_parseDate ( dateFormat , splitRes [ 0 ] , dateSettings ) ;
12581272} ;
12591273
12601274//#######################################################################################
@@ -1332,7 +1346,60 @@ function extendRemove(target, props) {
13321346 return target ;
13331347} ;
13341348
1349+ //#######################################################################################
1350+ // Splits datetime string into date ans time substrings.
1351+ // Throws exception when date can't be parsed
1352+ // If only date is present, time substring eill be ''
1353+ //#######################################################################################
1354+ var splitDateTime = function ( dateFormat , dateTimeString , dateSettings )
1355+ {
1356+ try {
1357+ var date = $ . datepicker . _base_parseDate ( dateFormat , dateTimeString , dateSettings ) ;
1358+ } catch ( err ) {
1359+ if ( err . indexOf ( ":" ) >= 0 ) {
1360+ // Hack! The error message ends with a colon, a space, and
1361+ // the "extra" characters. We rely on that instead of
1362+ // attempting to perfectly reproduce the parsing algorithm.
1363+ var dateStringLength = dateTimeString . length - ( err . length - err . indexOf ( ':' ) - 2 ) ;
1364+ var timeString = dateTimeString . substring ( dateStringLength ) ;
1365+
1366+ return [ dateTimeString . substring ( 0 , dateStringLength ) , dateTimeString . substring ( dateStringLength ) ]
1367+
1368+ } else {
1369+ throw err ;
1370+ }
1371+ }
1372+ return [ dateTimeString , '' ] ;
1373+ }
1374+
1375+ //#######################################################################################
1376+ // Internal function to parse datetime interval
1377+ // Returns: {date: Date, timeObj: Object}, where
1378+ // date - parsed date without time (type Date)
1379+ // timeObj = {hour: , minute: , second: , millisec: } - parsed time. Optional
1380+ //#######################################################################################
1381+ var parseDateTimeInternal = function ( dateFormat , timeFormat , dateTimeString , dateSettings , timeSettings )
1382+ {
1383+ var date ;
1384+ var splitRes = splitDateTime ( dateFormat , dateTimeString , dateSettings ) ;
1385+ date = $ . datepicker . _base_parseDate ( dateFormat , splitRes [ 0 ] , dateSettings ) ;
1386+ if ( splitRes [ 1 ] != '' )
1387+ {
1388+ var timeString = splitRes [ 1 ] ;
1389+ var separator = timeSettings && timeSettings . separator ? timeSettings . separator : $ . timepicker . _defaults . separator ;
1390+ if ( timeString . indexOf ( separator ) != 0 )
1391+ throw 'Missing time separator' ;
1392+ timeString = timeString . substring ( separator . length ) ;
1393+ var parsedTime = $ . datepicker . parseTime ( timeFormat , timeString , timeSettings ) ;
1394+ if ( parsedTime === null )
1395+ throw 'Wrong time format' ;
1396+ return { date : date , timeObj : parsedTime } ;
1397+ }
1398+ else
1399+ return { date : date } ;
1400+ }
1401+
13351402$ . timepicker = new Timepicker ( ) ; // singleton instance
13361403$ . timepicker . version = "1.0.1" ;
13371404
1338- } ) ( jQuery ) ;
1405+ } ) ( jQuery ) ;
0 commit comments