前端XLSX解析Excel数据处理多种日期格式转换问题

一、实现思路

最近在开发一个Excel解析预览的功能,发现在解析Excel导入时间的时候会存在一个离谱的问题就是Excel的时间和XlSX解析之后获取的时间会不一致
例如 2024/6/19 获取的时间为 Wed Jun 19 2024 23:59:17 GMT+0800,少了43秒,为了解决这个问题,需要特别处理一下。

  // 处理包含 "23:59:17" 的日期字符串,转换date类型则加1天,datetime则加43秒
  if (dateString.includes("23:59:17")) {
    dateString = dayjs(dateString)
      .add(isDateTime ? 43 : 1, isDateTime ? "second" : "day")
      .format(isDateTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD");
  }

支持一下多种时间格式转换为标准时间格式"YYYY-MM-DD"或"YYYY-MM-DD HH:mm:ss"
支持转换的时间格式

  • 2019.07.09
  • 2019/07/09
  • 2019年07月09日
  • 44642; // Excel 日期
formatDateString("2023年06月18日 12:30:45", true) 会输出 2023-06-18 12:30:45
formatDateString("2024.06.20", false) 会输出 2024-06-20
formatDateString(44642, true) 会输出 2022-02-14 00:00:00
formatDateString(44642, false) 会输出 2022-02-14

实现代码

import dayjs from "dayjs";

const workbook = XLSX.read(data, { type: "array", cellDates: true }); // 使用xlsx库解析Excel文件
/**
 * 解析日期字符串并返回指定格式的日期。
 *
 * @param {string|number} dateString - 要解析的日期字符串或 Excel 日期数字。
 * @param {boolean} isDateTime - 是否需要返回日期和时间格式。
 * @returns {string} - 格式化后的日期字符串。
 */
const formatDateString = (dateString, isDateTime) => {
  // 帮助函数:将 Date 对象格式化为 yyyy-MM-dd HH:mm:ss
  const formatDateTime = date => {
    return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
  };

  // 帮助函数:将 Date 对象格式化为 yyyy-MM-dd
  const formatDate = date => {
    return dayjs(date).format("YYYY-MM-DD");
  };

  // 将非字符串的日期转换为字符串
  if (typeof dateString !== "string") {
    dateString = String(dateString);
  }

  // 处理包含 "23:59:17" 的日期字符串
  if (dateString.includes("23:59:17")) {
    dateString = dayjs(dateString)
      .add(isDateTime ? 43 : 1, isDateTime ? "second" : "day")
      .format(isDateTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD");
  }

  // 检查日期字符串是否为数字(Excel 日期格式)
  if (!isNaN(dateString) && !isNaN(parseFloat(dateString))) {
    const excelDate = parseFloat(dateString);
    const excelEpoch = new Date(Date.UTC(1899, 11, 30));
    const dayInMs = 24 * 60 * 60 * 1000;
    const parsedDate = new Date(
      excelEpoch.getTime() + excelDate * dayInMs
    );
    return isDateTime
      ? formatDateTime(parsedDate)
      : formatDate(parsedDate);
  }

  // 处理各种日期格式
  let date;
  const chineseDateTimeRegex = /^(\d{4})年(\d{1,2})月(\d{1,2})日 (\d{2}):(\d{2}):(\d{2})$/;
  const chineseDateRegex = /^(\d{4})年(\d{1,2})月(\d{1,2})日$/;
  const chineseMatch = dateString.match(chineseDateTimeRegex);
  const chineseDateMatch = dateString.match(chineseDateRegex);
  const dotDateRegex = /^(\d{4})\.(\d{1,2})\.(\d{1,2})$/; // 匹配 2024.06.20 格式的正则表达式
  const dotDateMatch = dateString.match(dotDateRegex);

  if (chineseMatch) {
    const [_, year, month, day, hour, minute, second] = chineseMatch;
    date = new Date(year, month - 1, day, hour, minute, second);
  } else if (chineseDateMatch) {
    const [_, year, month, day] = chineseDateMatch;
    date = new Date(year, month - 1, day);
  } else if (dotDateMatch) {
    const [_, year, month, day] = dotDateMatch;
    date = new Date(year, month - 1, day);
  } else {
    const slashDateTimeRegex = /^(\d{4})\/(\d{1,2})\/(\d{1,2})( \d{2}:\d{2}:\d{2})?$/;
    const slashMatch = dateString.match(slashDateTimeRegex);
    if (slashMatch) {
      const [_, year, month, day, time] = slashMatch;
      date = new Date(
        `${year}-${month}-${day}T${time ? time.trim() : "00:00:00"}`
      );
    } else {
      date = new Date(dateString);
      if (!isDateTime) {
        date.setUTCHours(0, 0, 0, 0);
      }
    }
  }

  if (isNaN(date.getTime())) {
    console.error(`Invalid date object: ${dateString}`);
    return dateString;
  }

  return isDateTime ? formatDateTime(date) : formatDate(date);
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值