如何正确格式化日期?自定义特定可读日期格式的技术问询
如何将日期格式化为"January 7th, 2018 7:30am"这种可读形式?
我完全懂这种纠结——想要那种看起来特别友好的日期格式,带序数词(像1st、7th)和12小时制的上午/下午标识,但又摸不准该在哪里加需要的扩展工具对吧?下面我分几种最常用的开发场景给你讲明白怎么实现:
核心需求拆解
首先明确你要的格式包含三个关键部分:
- 月份全称(比如January)
- 带序数词的日期(比如7th)
- 12小时制时间(小写am/pm)(比如7:30am)
大部分语言的原生日期库都不直接支持序数词格式化,所以要么自己写小工具函数,要么引入成熟的第三方扩展库来简化操作。
JavaScript 场景
方案1:用原生代码自定义实现(无需扩展)
如果不想引入第三方库,可以自己写个序数词处理函数,配合原生Date对象的方法:
// 生成日期序数词的工具函数 const getOrdinalSuffix = (day) => { if (day > 3 && day < 21) return `${day}th`; switch (day % 10) { case 1: return `${day}st`; case 2: return `${day}nd`; case 3: return `${day}rd`; default: return `${day}th`; } }; // 格式化主函数 const formatFriendlyDate = (date) => { const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; const month = monthNames[date.getMonth()]; const dayWithSuffix = getOrdinalSuffix(date.getDate()); const year = date.getFullYear(); // 处理12小时制时间,转小写am/pm,去掉小时前的0 const hours = date.getHours() % 12 || 12; const minutes = date.getMinutes().toString().padStart(2, '0'); const period = date.getHours() < 12 ? 'am' : 'pm'; return `${month} ${dayWithSuffix}, ${year} ${hours}:${minutes}${period}`; }; // 测试 const testDate = new Date('2018-01-07T07:30:00'); console.log(formatFriendlyDate(testDate)); // 输出: January 7th, 2018 7:30am
方案2:引入第三方扩展库(更简洁)
推荐用date-fns(轻量、模块化)或者luxon(现代日期库),这里以date-fns为例:
- 安装扩展库(在你的项目根目录执行):
npm install date-fns date-fns/locale/en-US
- 在代码中引入并使用:
import { format, addOrdinalSuffix } from 'date-fns'; import { enUS } from 'date-fns/locale'; const formattedDate = format( new Date('2018-01-07T07:30:00'), "MMMM do, yyyy h:mma", { locale: enUS } ).toLowerCase(); // 调整月份首字母大写 const finalDate = formattedDate.replace(/^[a-z]/, c => c.toUpperCase()); console.log(finalDate); // 输出: January 7th, 2018 7:30am
如果是纯静态HTML页面,可以通过CDN引入扩展库(不需要npm安装):
<script src="https://cdn.jsdelivr.net/npm/date-fns@2.30.0/dist/date-fns.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/date-fns@2.30.0/locale/en-US/index.min.js"></script>
然后在<script>标签里直接调用即可。
Python 场景
方案1:用arrow扩展库(最省心)
arrow是Python生态中非常友好的日期处理库,直接支持序数词格式化:
- 安装扩展库:
pip install arrow
- 代码实现:
import arrow # 解析目标日期 target_date = arrow.get('2018-01-07T07:30:00') # 直接格式化,Do表示带序数词的日期 formatted_date = target_date.format('MMMM Do, YYYY h:mma').lower() # 调整月份首字母大写 final_date = formatted_date.capitalize() print(final_date) # 输出: January 7th, 2018 7:30am
方案2:原生代码自定义实现
如果不想用第三方库,自己写序数词函数配合datetime模块:
from datetime import datetime def get_ordinal_suffix(day): if 4 <= day <= 20 or 24 <= day <= 30: return f"{day}th" return f"{day}{['st', 'nd', 'rd'][day % 10 - 1]}" target_date = datetime(2018, 1, 7, 7, 30) month = target_date.strftime('%B') day_with_suffix = get_ordinal_suffix(target_date.day) year = target_date.strftime('%Y') # 处理12小时制时间,去掉前导0,转小写am/pm time_part = target_date.strftime('%I:%M%p').lower().lstrip('0') final_date = f"{month} {day_with_suffix}, {year} {time_part}" print(final_date) # 输出: January 7th, 2018 7:30am
关于「扩展添加位置」的补充
你提到的“扩展”其实就是第三方日期处理库,添加位置分两种情况:
- 后端/本地项目:通过包管理工具(npm/pip/composer等)在项目根目录安装,然后在代码文件顶部引入使用。
- 前端静态页面:通过CDN链接直接在HTML的
<head>或<body>中引入,之后在脚本里调用库的方法即可。
内容的提问来源于stack exchange,提问作者hg56




