首页 > 解决方案 > 转换日期 JavaScript

问题描述

我目前正在使用来自肥皂网络服务的数据填充表格,日期以字符串形式出现(例如 44250)。我创建了一个函数将其格式化为 yyyy/mm/dd 格式。

在循环之外我有这个功能:

Date.prototype.addDays = function (days) {
          var date = new Date(this.valueOf());
          date.setDate(date.getDate() + days);
          return date;
        };

在循环内我有:

else if (detailsItem == details[i].children[1].innerHTML) {
          const dbDays = days[i].innerHTML;
          const daysInt = parseInt(dbDays, 0);
          const newDate = firstDate.addDays(daysInt);
          // Format the date to a readable value
          const partsDate = {
            date: newDate.getDate(),
            month: newDate.getMonth() + 1,
            year: newDate.getYear() + 1900,
          };
          finalDate = `${partsDate.date}/${partsDate.month}/${partsDate.year}`;
          const td = document.createElement("td");
          td.textContent = finalDate;
          tr.appendChild(td);
          }

else if 只是在填充时检查何时将日期添加到表中。

我现在需要再次使用日期向服务发送请求,但使用以前的格式,但日期必须与按钮单击在同一行,服务只接受日期的字符串格式,我目前卡住并不确定如何格式化它。

这是按钮单击功能,它必须将日期格式化回诸如 44250 之类的格式。

btn.onclick = function () {
                // Loops through the table to find the slot and date when clicking the button on the same row
                var tableRow = document.getElementById("booking-table"),
                  rIndex;
                for (var i = 0; i < tableRow.rows.length; i++) {
                  tableRow.rows[i].onclick = function () {
                    rIndex = this.rowIndex;
                    bookingDay = this.cells[1].innerHTML;
                    bookingSlot = this.cells[2].innerHTML;
                    console.log(bookingSlot, bookingDay);
                  };
                }

任何有关如何实现此目的的帮助将不胜感激。

标签: javascriptdatesoap

解决方案


值“44250”看起来像自 1899 年 12 月 31 日(纪元)以来的天数,这意味着值“1”转换为 1900 年 1 月 1 日。如果这是正确的,您可以使用它创建一个日期:

let dbDays = '44250';
let date = new Date(1900, 0, dbDays); // 24 Feb 2021

在这个算法中,1 是 1900 年 1 月 1 日,0 是 1899 年 12 月 31 日。

您可以使用反向算法将其转换回纪元偏移量:

let dbDays = Math.round((date.getTime() - new Date(1899, 11, 31) / 8.64e7);

它得到自日期和纪元以来的毫秒差异,然后在一天内除以毫秒并四舍五入以考虑可能的夏令时影响,其中天数不完全是 24 小时。此方法仅适用于全天,不适用于部分天。

如果 1900 年 1 月 1 日应该是 0 而不是 1,那么该算法可能会提前一天失效,只需调整函数中使用的基准日期即可。

dbDateDate实例并返回的简单函数是:

// Convert epoch days to Date
function toDate(dbDays) {
  return new Date(1900, 0, +dbDays);
}

// Convert Date to epoch days
function toDBDays(date) {
  return Math.round((date - new Date(1899,11,31)) / 8.64e7);
}

// Format date as dd/mm/yyyy
function formatDate(d) {
  let z = n => ('0'+n).slice(-2);
  return z(d.getDate()) + '/' + z(d.getMonth()+1) + '/' + d.getFullYear();
}

// Parse date in d/m/y format, any non-digit separator
function parseDate(s) {
  let [d,m,y] = s.split(/\D/);
  return new Date(y, m - 1, d)
}

// Example
let dbDays = '44250';
let d1 = toDate(dbDays);  // 24 Feb 2021
let ts = formatDate(d1);  // 24/02/2021

let d2 = parseDate(ts);   // date object

console.log(dbDays + ' to Date: ' + ts);
console.log(ts + ' to dbDays: ' + toDBDays(d2));

PS 鉴于纪元不会改变,而不是创建 1899 年 12 月 31 日的日期并获取其时间值,可以使用常量 -2209111200000。

关于您的代码的注释:

const daysInt = parseInt(dbDays, 0);

parseInt的第二个参数是用于转换为数字的基数或基数。值 0 被替换为 10(默认基数),所以上面的等价于:

const daysInt = parseInt(dbDays, 10);

然后是:

const partsDate = {
  date: newDate.getDate(),
  month: newDate.getMonth() + 1,
  year: newDate.getYear() + 1900,
};

getYear方法返回一个 2 位数的年份,不建议这样做,并且主要出于历史原因支持,请改用getFullYear

使用对象进行临时存储并不是最佳选择,只需使用变量即可:

let date = newDate.getDate(),
    month = newDate.getMonth() + 1,
    year = newDate.getFullYear();

请注意,这不会用前导零填充个位数的日期或月份,因此会产生像 2021 年 1 月 1 日而不是 2021 年 1 月 1 日这样的时间戳。


推荐阅读