拿到HTML5日期控件返回的2025-08-20字符串,如果直接展示在页面上会显得很生硬;如果先转成Date对象再格式化,又可能因为字符串被当作UTC解析而出现日期偏移。lodash本身并不是专业日期库,但它的字符串拆解、补零和模板能力,恰好可以组合出一套轻量的日期格式化方案,适合已经引入lodash的项目。

一、HTML5日期控件的值格式
HTML5提供了<input type="date">、<input type="datetime-local">、<input type="month">、<input type="week">和<input type="time">等日期时间控件。无论在浏览器中显示成什么语言,通过value属性拿到的都是固定格式的字符串。date类型固定为YYYY-MM-DD,datetime-local为YYYY-MM-DDTHH:mm,month为YYYY-MM,week为YYYY-Www,time为HH:mm。这里的T是字面量分隔符,用来表示时间部分开始。
这种格式对提交到后端很友好,因为它符合ISO 8601的排序习惯,字符串比较就能得到时间先后。但直接展示给用户时不够自然,例如2025-08-20不如2025年8月20日直观。我们要做的就是把它拆成年、月、日,再拼成目标格式。如果直接使用new Date('2025-08-20'),浏览器可能按UTC时间解析,东八区用户有时会得到前一天,这是后续必须避开的问题。
下面是一个简单示例,展示页面控件与脚本读取到的值:
<input type="date" id="meetingDate" value="2025-08-20"> <input type="datetime-local" id="meetingTime" value="2025-08-20T14:30"> <p>脚本读取 value 后得到的是固定格式字符串</p>
可以看到,日期部分和显示语言无关,始终是数字加连字符。这个稳定结构正是用lodash进行字符串拆解的前提。
二、用lodash做基础日期拆分与补零
lodash没有名为formatDate的方法,但_.split、_.nth和_.padStart足够拼出一个格式化函数。_.split可以把日期字符串按连字符拆成数组,_.nth负责从数组中安全取值,即使数组长度异常也不会像直接索引那样轻易返回undefined导致拼接出错。对于HTML5日期控件的值,我们只需要把数组第0、1、2项取出来,再按中文习惯拼接即可。
const _ = require('lodash');
function formatDateYMD(raw) {
const parts = _.split(raw, '-');
const year = _.nth(parts, 0);
const month = _.nth(parts, 1);
const day = _.nth(parts, 2);
return year + '年' + month + '月' + day + '日';
}
console.log(formatDateYMD('2025-08-20')); // 2025年08月20日
如果数据来源不是控件值,而是JavaScript的Date对象,就需要先补齐月份和日期。原生getMonth返回0到11,getDate在每月前几天可能返回个位数。lodash的_.padStart可以把数字字符串补到指定位数,用法与原生String.prototype.padStart类似,但在旧环境中更统一。
function formatDate(date) {
const y = date.getFullYear();
const m = _.padStart(String(date.getMonth() + 1), 2, '0');
const d = _.padStart(String(date.getDate()), 2, '0');
return y + '-' + m + '-' + d;
}
console.log(formatDate(new Date(2025, 7, 20))); // 2025-08-20
这段代码先用_.padStart把月份和日期补成两位,再拼成YYYY-MM-DD。它没有依赖日期解析,而是直接使用本地时间构造函数,因此不会触发UTC偏移问题。对于从HTML5控件拿到的值,也可以先把月份和日期中的前导零去掉,再按自己的格式重组,不过通常情况下保留前导零更符合数据规范。
三、借助_.template做灵活日期模板
当项目中存在多种日期显示格式时,反复拼接字符串容易出错。_.template可以把日期模板编译成函数,之后传入包含年、月、日的对象即可生成结果。它使用ERB风格的分隔符,<%= %>用于输出变量,<%- %>用于输出并转义HTML。对于纯数字日期,两者区别不大;但如果后续拼接的月份名或用户输入可能包含HTML字符,应优先选择<%- %>。
// 编译一次,重复使用
const dateTpl = _.template('<%= year %>年<%= month %>月<%= day %>日');
const raw = '2025-08-20';
const parts = _.split(raw, '-');
const data = {
year: _.nth(parts, 0),
month: _.nth(parts, 1),
day: _.nth(parts, 2)
};
console.log(dateTpl(data)); // 2025年08月20日
如果需要切换成英文习惯的月/日/年格式,只要替换模板字符串即可,不需要重写函数逻辑。
const usTpl = _.template('<%= month %>/<%= day %>/<%= year %>');
console.log(usTpl(data)); // 08/20/2025
_.template本身会做一定的编译工作,所以对于频繁调用的场景,应该把编译结果缓存起来,而不是每次格式化都重新调用_.template。此外,lodash还支持通过_.templateSettings修改插值正则,但默认的ERB风格已经足够处理大多数日期模板。
四、处理datetime-local与时间字符串
如果控件类型是datetime-local,它的值会多出一个T和时分部分,例如2025-08-20T14:30。我们仍然可以用lodash先按T拆分成日期和时间两段,再分别处理。这样日期部分可以复用前面的格式化函数,时间部分则可以单独输出或保存。
const rawDateTime = '2025-08-20T14:30'; const datePart = _.first(_.split(rawDateTime, 'T')); const timePart = _.last(_.split(rawDateTime, 'T')); console.log(datePart); // 2025-08-20 console.log(timePart); // 14:30
这里用_.split按字面量T拆分,再用_.first和_.last分别取出前后两段。注意不能直接把这个字符串丢给new Date后格式化,因为不同浏览器对没有时区信息的日期时间字符串解析规则并不完全一致,有的按本地时区,有的按UTC,最终可能导致小时数偏移。
如果确实需要把HTML5日期字符串转成Date对象,手动拆分再构造本地时间是更安全的方式。下面这个函数把年、月、日分别转成整数,再用new Date(year, monthIndex, day)创建对象,这样使用的是本地时区,不会出现前一天的问题。
function parseLocalDate(raw) {
const parts = _.split(raw, '-');
return new Date(
_.toInteger(_.nth(parts, 0)),
_.toInteger(_.nth(parts, 1)) - 1,
_.toInteger(_.nth(parts, 2))
);
}
const d = parseLocalDate('2025-08-20');
console.log(d.getFullYear(), d.getMonth() + 1, d.getDate());
这种方式绕过了字符串解析的歧义,让日期结果可控。对于datetime-local,还可以把时间部分拆成时和分,再传递给Date对象的对应参数,但多数场景中分开保存日期和字符串时间即可,不必强行合并。
五、lodash格式化日期的最佳实践与局限
lodash适合处理已经固定结构的日期字符串,尤其是在项目已经引入lodash的情况下,可以用很少的代码完成YYYY-MM-DD到中文或英文格式的转换。它的优势是小巧、无额外依赖、逻辑直观;劣势也很明显:没有月份名称、星期名称、时区换算、相对时间等能力。如果需求包含这些内容,继续用lodash硬拼会变得复杂且难维护。
对于需要国际化显示的场景,原生Intl.DateTimeFormat是更合适的选择。它可以直接输出本地语言的长月份或短月份,而且能根据浏览器语言环境自动调整。
const formatted = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(new Date(2025, 7, 20));
console.log(formatted); // 2025年8月20日
实际项目中可以采用混合方案:HTML5控件的值已经保证了格式稳定,用lodash处理拆分、补零和简单拼接;用户可见界面的本地化格式则交给Intl.DateTimeFormat,涉及复杂日期运算再考虑引入dayjs或date-fns。这样既能控制依赖体积,也能保证日期格式化的正确性和可读性。

