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

在Javascript/Node.js中解析不规则日期格式的方案咨询

在JavaScript/Node.js中解析多种不规则日期格式的最佳方案

你需要解析一组格式各异的日期字符串(如["December 15th", "31 of October", "22.10.2022"]等)并转换为MM/DD/YYYY或标准可处理格式,自行尝试的字符清理+Date.parse()方法通用性不足,以下是几种可行的解决方案:


一、使用第三方日期解析库(首推方案)

手动覆盖所有不规则格式成本极高,成熟的日期库已经封装了大量解析逻辑,能处理绝大多数场景:

1. date-fns(轻量模块化)

date-fns支持多格式尝试解析,配合序数词清理即可覆盖你的需求:

import { parse, format } from 'date-fns';

const dateStrings = ["December 15th", "October 31st", "31 of October", "November 25th 2022", "22.10.2022", "15 November 2022", "9th of April 2023", "Friday 25 November 2022"];

// 定义所有待匹配的格式模板(date-fns格式令牌)
const formats = [
  'MMMM do',       // December 15th
  'MMMM do yyyy',  // November 25th 2022
  'do of MMMM',    // 31 of October
  'do of MMMM yyyy',// 9th of April 2023
  'dd.MM.yyyy',    // 22.10.2022
  'dd MMMM yyyy',  // 15 November 2022
  'EEEE dd MMMM yyyy' // Friday 25 November 2022
];

const parseDate = (str) => {
  // 先移除序数词(st/nd/rd/th)
  const cleanedStr = str.replace(/(st|nd|rd|th)/gi, '');
  // 遍历所有格式尝试解析
  for (const fmt of formats) {
    try {
      const date = parse(cleanedStr, fmt, new Date());
      if (date.toString() !== 'Invalid Date') {
        return format(date, 'MM/dd/yyyy');
      }
    } catch (e) {
      continue;
    }
  }
  return '无法解析的日期';
};

// 测试解析
dateStrings.forEach(str => {
  console.log(`${str} -> ${parseDate(str)}`);
});

2. Luxon(强类型+时区友好)

Luxon的fromString方法支持多格式配置,错误处理更严谨:

import { DateTime } from 'luxon';

const dateStrings = ["December 15th", "October 31st", "31 of October", "November 25th 2022", "22.10.2022", "15 November 2022", "9th of April 2023", "Friday 25 November 2022"];

const parseDate = (str) => {
  const cleanedStr = str.replace(/(st|nd|rd|th)/gi, '');
  const date = DateTime.fromString(cleanedStr, {
    formats: [
      'MMMM d',
      'MMMM d yyyy',
      'd of MMMM',
      'd of MMMM yyyy',
      'dd.MM.yyyy',
      'd MMMM yyyy',
      'EEEE d MMMM yyyy'
    ],
    zone: 'utc'
  });
  return date.isValid ? date.toFormat('MM/dd/yyyy') : '无法解析的日期';
};

// 测试解析
dateStrings.forEach(str => {
  console.log(`${str} -> ${parseDate(str)}`);
});

二、自定义正则解析(无依赖场景)

如果不想引入第三方库,可以针对已知格式编写正则匹配逻辑:

const dateStrings = ["December 15th", "October 31st", "31 of October", "November 25th 2022", "22.10.2022", "15 November 2022", "9th of April 2023", "Friday 25 November 2022"];

// 月份名称转数字映射(0-11对应1-12月)
const monthMap = {
  january: 0, february: 1, march: 2, april: 3, may: 4, june: 5,
  july: 6, august: 7, september: 8, october: 9, november: 10, december: 11
};

const parseDate = (str) => {
  const cleaned = str.toLowerCase().replace(/(st|nd|rd|th|,|\.)/gi, '').trim();
  let year = new Date().getFullYear(); // 默认当年
  let month, day;

  // 匹配 "December 15" / "December 15 2022"
  const mdYMatch = cleaned.match(/^(\w+) (\d+)(?: (\d{4}))?$/);
  if (mdYMatch) {
    month = monthMap[mdYMatch[1]];
    day = parseInt(mdYMatch[2], 10);
    year = mdYMatch[3] ? parseInt(mdYMatch[3], 10) : year;
  }

  // 匹配 "31 of October" / "9 of April 2023"
  else if (cleaned.match(/^\d+ of \w+(?: \d{4})?$/)) {
    const [dayPart, rest] = cleaned.split(' of ');
    day = parseInt(dayPart, 10);
    const [monthName, yearStr] = rest.split(' ');
    month = monthMap[monthName];
    year = yearStr ? parseInt(yearStr, 10) : year;
  }

  // 匹配 "22.10.2022"(日.月.年)
  else if (cleaned.match(/^\d{2}\s*\d{2}\s*\d{4}$/)) {
    const [dayStr, monthStr, yearStr] = cleaned.split(/\s+/);
    day = parseInt(dayStr, 10);
    month = parseInt(monthStr, 10) - 1;
    year = parseInt(yearStr, 10);
  }

  // 匹配 "Friday 25 November 2022"
  else if (cleaned.match(/^\w+ \d+ \w+ \d{4}$/)) {
    const [_, dayStr, monthName, yearStr] = cleaned.split(' ');
    day = parseInt(dayStr, 10);
    month = monthMap[monthName];
    year = parseInt(yearStr, 10);
  }

  // 验证日期有效性并格式化
  if (month !== undefined && day !== undefined) {
    const date = new Date(year, month, day);
    if (date.getFullYear() === year && date.getMonth() === month && date.getDate() === day) {
      return `${(month + 1).toString().padStart(2, '0')}/${day.toString().padStart(2, '0')}/${year}`;
    }
  }

  return '无法解析的日期';
};

// 测试解析
dateStrings.forEach(str => {
  console.log(`${str} -> ${parseDate(str)}`);
});

注意:这种方法仅适用于格式固定的场景,新增格式需要手动更新正则。


三、极端场景方案(机器学习/第三方API)

如果日期格式极度多样且无法枚举:

  • 机器学习模型:用TensorFlow.js训练一个实体提取模型,输入日期字符串输出年、月、日,但需要大量标注数据,开发成本高。
  • 第三方NLP API:借助自然语言处理API提取日期实体(如Google Cloud NLP、AWS Comprehend),再转换为标准格式,但需要付费且依赖网络。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:50:51