MatthiasDD has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/287449

Change subject: jquery.tablesorter: Improve detection and handling of isoDate
......................................................................

jquery.tablesorter: Improve detection and handling of isoDate

* Detect years 0...99 correct.
* Short forms possible: JJJJ, JJJJ-MM, JJJJMM, JJJJMMTT
  QUnit Test sorts now with parser 'isoDate' (because of 2009 former test sorts 
with parser 'text')
* Prefix and postfix allowed.
* Between date and time a 'T' or 'any white space' is allowed (Bug: T126886)

Change-Id: I664b4cc9d5fb472ea0bc0e36a3c209f04048e769
---
M resources/src/jquery/jquery.tablesorter.js
M tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
M tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
3 files changed, 70 insertions(+), 41 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/49/287449/1

diff --git a/resources/src/jquery/jquery.tablesorter.js 
b/resources/src/jquery/jquery.tablesorter.js
index 50bfa87..7f639e4 100644
--- a/resources/src/jquery/jquery.tablesorter.js
+++ b/resources/src/jquery/jquery.tablesorter.js
@@ -90,6 +90,7 @@
                        config = $( table ).data( 'tablesorter' ).config,
                        cellIndex,
                        nodeValue,
+                       nextRow = false,
                        // Start with 1 because 0 is the fallback parser
                        i = 1,
                        lastRowIndex = -1,
@@ -113,24 +114,34 @@
                        if ( nodeValue !== '' ) {
                                if ( parsers[ i ].is( nodeValue, table ) ) {
                                        concurrent++;
-                                       rowIndex++;
+                                       nextRow = true;
                                        if ( concurrent >= needed ) {
                                                // Confirmed the parser for 
multiple cells, let's return it
                                                return parsers[ i ];
                                        }
+                               } else if ( parsers[ i ].id.match(/isoDate/) && 
/^\D*(\d{1,4}) ?(\[.+\])?$/.test( nodeValue ) ) {
+                                       //For 1-4 digits and maybe reference(s) 
parser "isoDate", "date" or "number" is possible, check next row
+                                       empty++;
+                                       nextRow = true;
                                } else {
                                        // Check next parser, reset rows
                                        i++;
                                        rowIndex = 0;
                                        concurrent = 0;
                                        empty = 0;
+                                       nextRow = false;
                                }
                        } else {
                                // Empty cell
                                empty++;
+                               nextRow = true;
+                       }
+
+                       if( nextRow ) {
+                               nextRow = false;
                                rowIndex++;
                                if ( rowIndex >= rows.length ) {
-                                       if ( concurrent >= rows.length - empty 
) {
+                                       if ( concurrent > 0 && concurrent >= 
rows.length - empty ) {
                                                // Confirmed the parser for all 
filled cells
                                                return parsers[ i ];
                                        }
@@ -722,8 +733,8 @@
                                new RegExp( /(https?|ftp|file):\/\// )
                        ],
                        isoDate: [
-                               new RegExp( 
/^([-+]?\d{1,4})-([01]\d)-([0-3]\d)([T\s]((([01]\d|2[0-3])(:?[0-5]\d)?|24:?00)?(:?([0-5]\d|60))?([.,]\d+)?)([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?/
 ),
-                               new RegExp( 
/^([-+]?\d{1,4})-([01]\d)-([0-3]\d)/ )
+                               new RegExp( 
/^[^-\d]*(-?\d{1,4})-(0\d|1[0-2])(-([0-3]\d))?([T\s]([01]\d|2[0-4]):?(([0-5]\d):?(([0-5]\d|60)([.,]\d{1,3})?)?)?([zZ]|([-+])([01]\d|2[0-3]):?([0-5]\d)?)?)?/
 ),
+                               new RegExp( 
/^[^-\d]*(-?\d{1,4})-?(\d\d)?(-?(\d\d))?([T\s](\d\d):?((\d\d)?:?((\d\d)?([.,]\d{1,3})?)?)?([zZ]|([-+])(\d\d):?(\d\d)?)?)?/
 )
                        ],
                        usLongDate: [
                                new RegExp( /^[A-Za-z]{3,10}\.? [0-9]{1,2}, 
([0-9]{4}|'?[0-9]{2}) 
(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/ )
@@ -1128,22 +1139,34 @@
                        return ts.rgx.isoDate[ 0 ].test( s );
                },
                format: function ( s ) {
-                       var isodate, matches;
-                       if ( !Date.prototype.toISOString ) {
-                               // Old browsers don't understand iso, Fallback 
to US date parsing and ignore the time part.
-                               matches = $.trim( s ).match( ts.rgx.isoDate[ 1 
] );
-                               if ( !matches ) {
-                                       return $.tablesorter.formatFloat( 0 );
-                               }
-                               isodate = new Date( matches[ 2 ]  + '/' + 
matches[ 3 ] + '/' + matches[ 1 ] );
-                       } else {
-                               matches = s.match( ts.rgx.isoDate[ 0 ] );
-                               if ( !matches ) {
-                                       return $.tablesorter.formatFloat( 0 );
-                               }
-                               isodate = new Date( $.trim( matches[ 0 ] ) );
+                       var match, i, isodate, ms, hOffset, mOffset;
+                       if ( ( match = s.match( ts.rgx.isoDate[ 0 ] ) ) == null 
) {
+                               //otherwise a signed number with 1-4 digit is 
parsed as isoDate
+                               match = s.match( ts.rgx.isoDate[ 1 ] ); 
                        }
-                       return $.tablesorter.formatFloat( ( isodate !== 
undefined ) ? isodate.getTime() : 0 );
+                       if ( match ) {
+                               for ( i = 2; i <= 4; i += 2 ) { //Month and Day
+                                       if ( !match[ i ] || match[ i ].length 
=== 0) {
+                                               match[ i ] = 1;
+                                       }
+                               }
+                               for ( i = 6; i <= 15; i++ ) { //Time
+                                       if ( !match[ i ] || match[ i ].length 
=== 0) {
+                                               match[ i ] = '0';
+                                       }
+                               }
+                               ms = parseFloat( match[ 11 ].replace( /,/ , '.' 
)) * 1000;
+                               hOffset = $.tablesorter.formatInt( match[ 13 ] 
+ match[ 14 ] );
+                               mOffset = $.tablesorter.formatInt( match[ 13 ] 
+ match[ 15 ] );
+                               
+                               isodate = new Date( 0 );
+                               //because all constructors change year 0...99 
to 1900...1999, we use setUTCFullYear()
+                               isodate.setUTCFullYear( match[ 1 ], match[ 2 ] 
- 1, match[ 4 ] );
+                               isodate.setUTCHours( match[ 6 ] - hOffset, 
match[ 8 ] - mOffset, match[ 10 ], ms );
+                               return isodate.getTime();
+                       } else {
+                               return 0;
+                       }
                },
                type: 'numeric'
        } );
diff --git 
a/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js 
b/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
index 11ceeea2..944bb37 100644
--- a/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
@@ -174,39 +174,45 @@
        parserTest( 'Y Dates', 'date', YDates );
 
        ISODates = [
-               [ '2000',               false, 0, 'Plain 4-digit year' ],
-               [ '2000-01',            false, 0, 'Year with month' ],
-               [ '2000-01-01', true, 946684800000, 'Year with month and day' ],
-               [ '2000-13-01', true, 0, 'Non existant month' ],
-               [ '2000-01-32', true, 0, 'Non existant day' ],
-               [ '2000-01-01T12:30:30',                true, 946729830000, 
'Date with a time' ],
+               [ '2000',               false,  946684800000, 'Plain 4-digit 
year' ],
+               [ '2000-01',    true,   946684800000, 'Year with month' ],
+               [ '2000-01-01', true,   946684800000, 'Year with month and day' 
],
+               [ '2000-13-01', false,  978307200000, 'Non existant month' ],
+               [ '2000-01-32', true,   949363200000, 'Non existant day' ],
+               [ '2000-01-01T12:30:30',        true, 946729830000, 'Date with 
a time' ],
                [ '2000-01-01T12:30:30Z',       true, 946729830000, 'Date with 
a UTC+0 time' ],
-               [ '2000-01-01T24:30:30Z',       true, 0, 'Date with invalid 
hours' ],
-               [ '2000-01-01T12:60:30Z',       true, 0, 'Date with invalid 
minutes' ],
+               [ '2000-01-01T24:30:30Z',       true, 946773030000, 'Date with 
invalid hours' ],
+               [ '2000-01-01T12:60:30Z',       true, 946728000000, 'Date with 
invalid minutes' ],
                [ '2000-01-01T12:30:61Z',       true, 946729800000, 'Date with 
invalid amount of seconds, drops seconds' ],
                [ '2000-01-01T23:59:59Z',       true, 946771199000, 'Edges of 
time' ],
                [ '2000-01-01T12:30:30.111Z',   true, 946729830111, 'Date with 
milliseconds' ],
                [ '2000-01-01T12:30:30.11111Z', true, 946729830111, 'Date with 
too high precision' ],
-               [ '2000-01-01T12:30:30,111Z',   true, 0, 'Date with 
milliseconds and , separator' ],
+               [ '2000-01-01T12:30:30,111Z',   true, 946729830111, 'Date with 
milliseconds and , separator' ],
                [ '2000-01-01T12:30:30+01:00',  true, 946726230000, 'Date time 
in UTC+1' ],
                [ '2000-01-01T12:30:30+01:30',  true, 946724430000, 'Date time 
in UTC+1:30' ],
                [ '2000-01-01T12:30:30-01:00',  true, 946733430000, 'Date time 
in UTC-1' ],
                [ '2000-01-01T12:30:30-01:30',  true, 946735230000, 'Date time 
in UTC-1:30' ],
                [ '2000-01-01T12:30:30.111+01:00', true, 946726230111, 'Date 
time and milliseconds in UTC+1 ' ],
                [ '2000-01-01Postfix', true, 946684800000, 'Date with appended 
postfix' ],
-               [ '2000-01-01 Postfix', true, 946684800000, 'Date with separate 
postfix' ]
-               /* Disable testcases, because behavior is browser dependant */
-               /*
-               [ '2000-11-31', true, 0, '31 days in 30 day month' ],
-               [ '50-01-01',   false, -60589296000000, 'Year with just two 
digits' ],
-               [ '-1000-01-01',        true, -93724128000000, 'Year BC' ],
-               [ '+1000-01-01',        true, -30610224000000, 'Date with 
+sign' ],
-               [ '2000-01-01 12:30:30Z',       true, 0, 'Date and time with no 
T marker' ],
+               [ '2000-01-01 Postfix', true, 946684800000, 'Date with separate 
postfix' ],
+               [ '2 Postfix',  false, -62104060800000, 'One digit with 
separate postfix' ],
+               [ 'ca. 2',              false, -62104060800000, 'Three digit 
with separate prefix' ],
+               [ '~200',               false, -55855785600000, 'Three digit 
with appended prefix' ],
+               [ 'ca. 200[1]', false, -55855785600000, 'Three digit with 
separate prefix and postfix' ],
+               [ '2000-11-31', true,   975628800000, '31 days in 30 day month' 
],
+               [ '50-01-01',   true,   -60589296000000, 'Year with just two 
digits' ],
+               [ '2',                  false,  -62104060800000, 'Year with one 
digit' ],
+               [ '02-01',              true,   -62104060800000, 'Year with one 
digit and leading zero' ],
+               [ ' 2-01',              true,   -62104060800000, 'Year with one 
digit and leading space' ],
+               [ '-2-10',              true,   -62206704000000, 'Year BC with 
month' ],
+               [ '-9999',              false,  -377705116800000, 'max. Year 
BC' ],
+               [ '+9999-12',   true,   253399622400000, 'max. Date with +sign' 
],
+               [ '2000-01-01 12:30:30Z',       true, 946729830000, 'Date and 
time with no T marker' ],
                [ '2000-01-01T12:30:60Z',       true, 946729860000, 'Date with 
leap second' ],
-               [ '2000-01-01T12:30:30-24:00',  true, 946816230000, 'Date time 
in UTC-24' ],
-               [ '2000-01-01T12:30:30+24:00',  true, 946643430000, 'Date time 
in UTC+24' ],
-               [ '2000-01-01T12:30:30+0100',   true, 946726230000, 'Time 
without separator in timezone offset' ]
-               */
+               [ '2000-01-01T12:30:30-23:59',  true, 946816170000, 'Date time 
in UTC-23:59' ],
+               [ '2000-01-01T12:30:30+23:59',  true, 946643490000, 'Date time 
in UTC+23:59' ],
+               [ '2000-01-01T123030+0100',     true,   946726230000, 'Time 
without separators' ],
+               [ '20000101T123030+0100',       false,  946726230000, 'All 
without separators' ]
        ];
        parserTest( 'ISO Dates', 'isoDate', ISODates );
 
diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js 
b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
index b09bb28..a4095c9 100644
--- a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
@@ -166,8 +166,8 @@
                ],
                isoDateSortingSorted = [
                        [ '2009' ],
-                       [ '2009-12-25T12:30:45' ],
                        [ '2009-12-25T12:30:45+01:00' ],
+                       [ '2009-12-25T12:30:45' ],
                        [ '2009-12-25T12:30:45.001Z' ],
                        [ '2009-12-25T12:30:45.111' ],
                        [ '2010-01-31' ],

-- 
To view, visit https://gerrit.wikimedia.org/r/287449
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I664b4cc9d5fb472ea0bc0e36a3c209f04048e769
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: MatthiasDD <matthias...@gmx.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to