【前端实战】如何封装日期格式化工具,满足后端 LocalDate 和 LocalDateTime 格式需求

发布于:2025-08-13 ⋅ 阅读:(20) ⋅ 点赞:(0)

在前后端分离开发中,日期时间数据的传递是个常见的难点。后端往往用 Java 的 LocalDateLocalDateTime 类型接收日期数据:

  • LocalDate 要求字符串格式为 yyyy-MM-dd,不能有时间部分;

  • LocalDateTime 要求格式为 yyyy-MM-dd HH:mm:ss,包含时分秒。

如果前端传递的日期时间格式不符合要求,后端 Jackson 反序列化会报错,导致接口调用失败,常见错误如:

Cannot deserialize value of type `java.time.LocalDate` from String "2024-01-31 13:42:30.0": Text '2024-01-31 13:42:30.0' could not be parsed, unparsed text found at index 10

一、为什么要封装日期格式化工具?

  1. 避免重复代码:项目里日期处理场景多,重复写 substr 或者日期格式转换很麻烦。

  2. 统一日期格式:保证所有时间格式统一,方便维护和排查问题。

  3. 灵活适配后端需求:有时后端只需要日期,有时需要完整时间,封装函数可以灵活传参控制。

  4. 减少传参错误:前端统一调用工具函数,减少因格式不正确导致的接口调用失败

二、封装日期格式化函数示例

/**
 * 格式化日期为后端可识别字符串格式
 * @param {Date|string|null} date - 需要格式化的日期或字符串
 * @param {boolean} [includeTime=false] - 是否包含时间部分(时分秒),默认只输出年月日
 * @returns {string|null} 返回格式化后的字符串,如 '2024-08-12' 或 '2024-08-12 14:30:00',无效日期返回 null
 */
export function formatDateForBackend(date, includeTime = false) {
  if (!date) return null;

  const d = new Date(date);
  if (isNaN(d)) return null;

  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');

  if (!includeTime) {
    // 只返回年月日,满足 LocalDate 格式
    return `${y}-${m}-${day}`;
  } else {
    // 返回年月日时分秒,满足 LocalDateTime 格式
    const hh = String(d.getHours()).padStart(2, '0');
    const mm = String(d.getMinutes()).padStart(2, '0');
    const ss = String(d.getSeconds()).padStart(2, '0');
    return `${y}-${m}-${day} ${hh}:${mm}:${ss}`;
  }
}

三、示例分析

  • 参数说明

  • date:可以是 Date 对象,也可以是日期字符串;includeTime:控制是否输出时分秒,默认 false

  • 流程

  • 判断日期有效性,避免传空或非法值;

  • 使用 Date 对象拆解年、月、日、时、分、秒;

  • 根据 includeTime 选择返回格式;

  • 对月、日、时、分、秒补零确保格式正确。

四、项目中的实际应用

举例:你有一个接口获取报销单列表,字段里有 createdOn(时间戳或字符串),后端字段是 LocalDate 类型,必须是 yyyy-MM-dd

import { formatDateForBackend } from '@/utils/dateUtils'

erpCoverBillHeadAPI({ orderNumber }).then(res => {
  this.interestCoverList = res.data.map(item => ({
    reimbursementDate: formatDateForBackend(item.createdOn, false), // 只要年月日
    settlementDate: formatDateForBackend(item.settlementDate, false),
    reimbursementCode: item.doCno || '',
    expenName: item.expenName || '',
    reimburser: item.createdBy || '',
    reimbursementAmount: parseFloat(item.bxAmount || 0),
    // 其他字段...
  }));

  console.log('转换后的报销数据:', this.interestCoverList);
}).catch(console.error);

这样保存之后的结果就只有年月了:

五、为什么要格式化日期?

因为后端如果收到字符串 "2024-01-31 13:42:30.0" 作为 LocalDate 类型,Jackson 会报错,因为 LocalDate 不能识别时间部分:

Text '2024-01-31 13:42:30.0' could not be parsed, unparsed text found at index 10

所以必须把时间截取为 "2024-01-31" 形式,才能让反序列化成功

六、总结

  • 封装日期格式化工具是前端开发的好习惯,减少重复代码,提高代码质量;

  • 灵活传递是否包含时间,应对不同后端字段需求;

  • 保证接口传参的格式正确,避免接口调用失败

  • 与后端保持沟通,了解字段类型及格式要求,做好对应处理