You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改原生JS表格排序函数以支持dd/mm/yyyy日期排序

Fixing dd/mm/yyyy Date Column Sorting in Native JavaScript Table Sort Function

Hey there! I get it—your current table sort works great for regular text and numbers, but it’s totally messing up dates in dd/mm/yyyy format because it’s just comparing strings alphabetically instead of chronologically. Let’s fix this without any jQuery, and even add some extra polish for numeric columns while we’re at it!

The Root Problem

When you compare date strings like "25/11/2020" and "20/09/2020" as plain text, "25..." gets treated as "larger" than "20..." because the second character 5 is bigger than 0—which is wrong for actual date order. We need to convert these strings into proper JavaScript Date objects so we can compare their real chronological values.

Modified Sort Function with Date Handling

Here’s the updated function that handles dates, numbers, and text correctly:

function sortMaoDeObraPrintItemList(n) {
  var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  table = document.getElementById("MaoDeObraNaoFaturadasPerClientControlPanelPrint");
  switching = true;
  dir = "asc";

  // Helper to convert dd/mm/yyyy strings to valid Date objects
  function convertDMYtoDate(dateStr) {
    const parts = dateStr.split('/');
    // Validate the date format before converting
    if (parts.length === 3 && !isNaN(parts[0]) && !isNaN(parts[1]) && !isNaN(parts[2])) {
      // Months are 0-indexed in JS, so subtract 1 from the month value
      return new Date(parts[2], parts[1] - 1, parts[0]);
    }
    return null; // Not a valid date—fall back to other comparison methods
  }

  while (switching) {
    switching = false;
    rows = table.rows;
    for (i = 1; i < (rows.length - 1); i++) {
      shouldSwitch = false;
      x = rows[i].getElementsByTagName("TD")[n];
      y = rows[i + 1].getElementsByTagName("TD")[n];
      
      // Use textContent instead of innerHTML for cleaner raw text extraction
      let xVal = x.textContent.trim();
      let yVal = y.textContent.trim();
      
      // Try converting to dates first
      let xDate = convertDMYtoDate(xVal);
      let yDate = convertDMYtoDate(yVal);

      if (xDate && yDate) {
        // Compare date timestamps for proper chronological order
        if (dir === "asc") {
          shouldSwitch = xDate > yDate;
        } else {
          shouldSwitch = xDate < yDate;
        }
      } else {
        // Check if values are numeric (handle commas for decimal separators)
        let xNum = parseFloat(xVal.replace(',', '.'));
        let yNum = parseFloat(yVal.replace(',', '.'));
        
        if (!isNaN(xNum) && !isNaN(yNum)) {
          // Numeric comparison for IDs, ages, amounts
          if (dir === "asc") {
            shouldSwitch = xNum > yNum;
          } else {
            shouldSwitch = xNum < yNum;
          }
        } else {
          // Fall back to case-insensitive string comparison
          if (dir === "asc") {
            shouldSwitch = xVal.toLowerCase() > yVal.toLowerCase();
          } else {
            shouldSwitch = xVal.toLowerCase() < yVal.toLowerCase();
          }
        }
      }

      if (shouldSwitch) break;
    }
    if (shouldSwitch) {
      rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
      switching = true;
      switchcount ++;
    } else {
      // If no switches happened, reverse direction and try again
      if (switchcount == 0 && dir == "asc") {
        dir = "desc";
        switching = true;
      }
    }
  }
}

Key Improvements Explained

  • Date Conversion: The convertDMYtoDate function splits the date string, adjusts the month (since JS dates use 0-indexed months), and validates the input to avoid invalid dates.
  • Smart Comparison: The function first checks if values are valid dates, then checks if they’re numbers (handling comma decimal separators), and falls back to text comparison if neither applies.
  • Cleaner Text Extraction: Using textContent instead of innerHTML avoids issues with hidden HTML elements and gives us raw, unformatted text.

Your Updated Table (No Changes Needed!)

You can keep your existing table structure—just use the new function above:

<table id='MaoDeObraNaoFaturadasPerClientControlPanelPrint' border='0'>
  <tr>
    <th onclick='sortMaoDeObraPrintItemList(0)'>ID</th>
    <th onclick='sortMaoDeObraPrintItemList(1)'>DATE</th>
    <th onclick='sortMaoDeObraPrintItemList(2)'>FUNCIONARIO</th>
    <th onclick='sortMaoDeObraPrintItemList(3)'>AGE</th>
    <th onclick='sortMaoDeObraPrintItemList(4)'>DESCRICAO</th>
    <th onclick='sortMaoDeObraPrintItemList(5)'>AMOUNT</th>
  </tr>
  <tr>
    <td>106</td>
    <td>25/11/2020</td>
    <td>John</td>
    <td>33</td>
    <td>Red</td>
    <td>100,00</td>
  </tr>
  <tr>
    <td>102</td>
    <td>20/09/2020</td>
    <td>Maria</td>
    <td>34</td>
    <td>white</td>
    <td>200,00</td>
  </tr>
  <tr>
    <td>101</td>
    <td>29/12/2020</td>
    <td>Roger</td>
    <td>20</td>
    <td>blue</td>
    <td>50,00</td>
  </tr>
  <tr>
    <td>107</td>
    <td>28/01/2020</td>
    <td>Robert</td>
    <td>10</td>
    <td>Green</td>
    <td>1050,00</td>
  </tr>
</table>

Now when you click the DATE header, your dates will sort correctly chronologically (ascending order will show 28/01/2020 first, then 20/09/2020, etc.), and all other columns will work better too—numeric columns like ID and AMOUNT will sort by actual value instead of string order.

内容的提问来源于stack exchange,提问作者user2916405

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:57:45