【免费下载链接】decap-cms
A Git-based CMS for Static Site Generators
本文以packages/decap-cms-widget-datetime的 CHANGELOG.md 为脉络,结合该组件 DateTimeControl.js、schema.js 等源码与单元测试,系统讲解 Decap CMS 中 datetime 组件的配置方式、底层行为、时区处理与关键版本变更。读完本文,你将掌握该组件的全部字段参数、{{now}}默认值机制、UTC/本地时间差异,以及从 moment 迁移到 dayjs 背后的设计取舍。
datetime 组件在 Decap CMS 中的定位
Decap CMS 是一个基于 Git 的静态站点 CMS,其编辑界面由一系列"组件(Widget)"构成,每个组件对应一种字段类型。datetime组件专门负责日期、时间以及日期时间的输入与展示,用于发布日、更新时间、事件时间等场景。
从 package.json 可以看到,该包是独立发布、可单独安装的 npm 包,通过 index.js 对外注册:
function Widget(opts = {}) { return { name: 'datetime', controlComponent, previewComponent, schema, ...opts, }; }其中controlComponent(编辑控件)、previewComponent(预览组件)与schema(配置项校验规则)共同组成了组件的完整能力。在 dev-test/config.yml 中可以看到它的真实使用示例:
- { label: 'Publish Date', name: 'date', widget: 'datetime', format: 'YYYY-MM-DD HH:mm', default: '{{now}}', }配置参数详解:四个核心字段
组件的可配置参数由 schema.js 声明并校验:
| 参数 | 类型 | 说明 |
|---|---|---|
format | string | 最终写入内容文件(YAML/Markdown 等)的日期格式,优先级最高 |
date_format | string 或 boolean | 日期部分格式;true时使用默认YYYY-MM-DD,false时隐藏日期部分 |
time_format | string 或 boolean | 时间部分格式;true时使用默认HH:mm,false时隐藏时间部分 |
picker_utc | boolean | 是否以 UTC 时区解析与展示日期时间,默认false |
format:最终存储格式
format决定字段值以何种字符串形式写入内容文件。在 DateTimeControl.js 中,一旦配置了format,它就会覆盖由date_format/time_format拼装出的默认格式,并将输入控件类型固定为datetime-local。
未配置format时的默认格式(源码 getFormat()):
- 本地时区:
YYYY-MM-DDTHH:mm:ss.SSSZ(如2026-09-30T10:30:00.000+08:00) - UTC 时区(
picker_utc: true):YYYY-MM-DDTHH:mm:ss.SSS[Z],Z被转义为字面量
这一行为经历过两次调整:3.1.0-beta.3 变更了 datetime 组件的值格式,3.1.3 又回退为包含时区的默认格式(见 CHANGELOG 中 "revert default date format to include timezone"),最终形成了上面带时区后缀的稳定默认值。
date_format 与 time_format:拆分控制
这两个参数允许只显示日期或只显示时间:
- 只配置
date_format: 'YYYY-MM-DD':输入控件降级为原生date类型,存储格式即该日期格式; - 只配置
time_format: 'HH:mm':输入控件降级为原生time类型; date_format: false强制隐藏日期、time_format: false强制隐藏时间(DateTimeControl.js#L116-L117);- 两者同时配置且均为字符串时,按
${dateFormat}T${timeFormat}拼接为完整格式(DateTimeControl.js#L101-L102)。
对应的输入控件原生类型也随配置切换:datetime-local、date、time,分别匹配YYYY-MM-DDTHH:mm、YYYY-MM-DD、HH:mm三种输入格式。
picker_utc:UTC 与本地时间
picker_utc于 2.5.0 引入(CHANGELOG "add pickerUtc option to datetime widget")。开启后:
- 日期解析、当前时间获取均基于
dayjs.utc()(DateTimeControl.js#L127-L130); - 输入框旁会显示 "UTC" 标识(DateTimeControl.js#L196-L205);
- 用户自定义格式中的
Z会被 escapeZ() 转义为[Z],避免被 dayjs 误解析为时区占位符。
# 使用 UTC 的配置示例 - { label: 'Event Time', name: 'event_time', widget: 'datetime', picker_utc: true }default 与 {{now}}:默认值机制(重要行为变更)
这是 CHANGELOG 中最关键的行为变化:
3.2.0(2024-08-12)破坏性变更:datetime 字段默认不再预填当前日期(此前会自动预填),如需预填当前时间必须显式配置
default: '{{now}}'。
在 DateTimeControl.js#L65-L73 中,组件挂载时会检测值是否为'{{now}}'字面量,若是则调用getNow()将其替换为当前时间并触发onChange:
componentDidMount() { const { value } = this.props; if (value === '{{now}}') { this.handleChange(this.getNow()); } }3.2.3 又修复了 "trigger change if default is {{now}}"(#7272),确保{{now}}能正确触发变更通知。升级到 3.2.0 及以后版本时,若希望字段自动填充当前时间,必须显式声明default: '{{now}}',这是迁移时最需要留意的兼容点。
底层实现:值的双向转换链路
datetime 组件的核心逻辑集中在 DateTimeControl.js 中,整个数据流可以概括为三条链路:
读取回显:
formatInputValue(value)把存储格式的值转换为输入框所需的格式。它优先用dayjs(value, format)按存储格式解析后重新格式化;解析失败(如format未提供、值本身不可解析)时,会回退到dayjs(value)的宽松解析(DateTimeControl.js#L132-L144)。3.1.4 修复了 "formatInputValue ignoring format" 问题,3.1.5 修复了未提供format时解析展示值的问题,这两处正是本方法的演进痕迹。用户输入:
onInputChange把输入框值交给handleChange,先通过isValidDate校验(合法的输入格式值或空串),再按存储格式格式化后写入内容(DateTimeControl.js#L146-L157):
handleChange = datetime => { if (!this.isValidDate(datetime)) return; if (datetime === '') { onChange(''); } else { const { format, inputFormat } = this.getFormat(); const formattedValue = dayjs(datetime, inputFormat).format(format); onChange(formattedValue); } };- 快捷操作:
Now按钮写入getNow()的当前时间,Clear按钮写入空串。这两个按钮由Buttons组件渲染(DateTimeControl.js#L14-L46),对应 2.4.0 "add now to datepicker" 与 2.7.3 "make 'now' button consistent" 两次迭代。
预览侧则非常简单:DateTimePreview仅将值原样渲染(DateTimePreview.js)。
日期解析引擎的演进:从 moment 到 dayjs
CHANGELOG 记录了组件底层依赖的两次关键升级:
- 3.1.0-beta.1(2023-11-23):用 dayjs 替换 moment(#6980),标注为性能优化;
- 3.1.0-beta.2(2024-01-16):将 dayjs 改为按包独立依赖(#6992)。
当前 package.json 中dependencies仅剩dayjs,并通过插件扩展能力启用三个能力(DateTimeControl.js#L4-L12):
dayjs.extend(customParseFormat); // 按指定格式解析 dayjs.extend(localizedFormat); // 本地化格式 dayjs.extend(utc); // UTC 时区支持这解释了{{now}}、picker_utc、自定义格式解析等能力为何都能在更轻量的 dayjs 上实现——三个插件恰好覆盖了组件全部的时间处理需求。
工程化与可访问性细节
- Schema 校验(2.6.0 引入):组件配置在保存前即通过 schema.js 校验参数类型,非法配置会提前报错。
- 无障碍(a11y):3.4.1 为按钮补充了
aria-label(#7720)。在 DateTimeControl.js#L23-L25 中,Now按钮的 aria-label 由国际化函数t('editor.editorWidgets.datetime.setToNow', { fieldLabel: fieldName })动态生成,可随语言包本地化。 - 构建产物(2019 年前后):2.2.0 增加 ES Module 构建、2.1.0-beta.0 提供 UMD 构建、2.2.1-beta.1 修复 ESM 的 source map 导出,这些确保了组件能被
decap-cms主包以多种模块方式消费。 - 依赖清理:3.5.0 移除未使用依赖并补全缺失依赖(#7833),2.7.4/2.7.1 分别升级了历史版本使用的
react-datetime至 v3,2.7.0 将 React 17 加入 peerDependencies。
单元测试如何验证组件行为
组件的测试用例位于 DateTimeControl.spec.js,覆盖了 CHANGELOG 中多项关键行为,可作为理解组件语义的"活文档":
- Now 按钮:点击后
onChange收到按配置格式(如DD.MM.YYYY)格式化的当前时间; - Clear 按钮:点击后
onChange收到空串,对应 2.2.5 "allow empty value" 与 3.2.0 默认空值的语义; - 本地时区输入:输入
2024-03-15T10:30:00,期望输出YYYY-MM-DDTHH:mm:ss.SSSZ格式(含本地时区偏移); - UTC 输入:开启
picker_utc后,期望输出YYYY-MM-DDTHH:mm:ss.SSS[Z]格式(字面量Z后缀)。
测试通过jest.useFakeTimers()固定系统时间(2025-01-01T12:00:00.000Z),保证 Now 按钮相关断言稳定可复现。
升级与迁移建议
综合 CHANGELOG 与源码,升级到当前版本(3.6.0)时建议关注:
- 默认值变化(3.2.0 破坏性变更):若依赖旧版自动预填当前时间的行为,需为 datetime 字段补充
default: '{{now}}'; - 默认格式含时区:3.1.0-beta.3 起默认值格式为带时区的
YYYY-MM-DDTHH:mm:ss.SSSZ(UTC 模式为[Z]),如果内容文件中已有旧格式数据,建议显式配置format以保持历史兼容; - dayjs 解析差异:moment 迁移到 dayjs 后,个别宽松解析场景的行为可能略有差异(3.1.4/3.1.5 的修复即与此相关),若遇到展示异常,优先检查是否配置了完整的
format。
小结
decap-cms-widget-datetime是一个"小而不简单"的组件:四个配置参数控制着存储格式、日期时间拆分、时区模式三类核心行为,{{now}}默认值机制经历了破坏性变更,底层解析引擎从 moment 平稳迁移到 dayjs。通过 CHANGELOG 与 DateTimeControl.js、schema.js、DateTimeControl.spec.js 等源码和测试相互印证,你可以准确预判组件在任何配置组合下的存储值与展示行为,避免踩中时区与默认值的坑。
【免费下载链接】decap-cms
A Git-based CMS for Static Site Generators
相关推荐
Decap CMS colorstring 颜色组件:配置指南与源码演进解析
Decap CMS colorstring 颜色组件:配置指南与源码演进解析 Decap CMS 是一个基于 Git 的静态站点内容管理系统,其编辑界面由大量可
Blueprint 日期时间组件包 @blueprintjs/datetime 完全指南:安装、组件与源码解析
Blueprint 日期时间组件包 @blueprintjs/datetime 完全指南:安装、组件与源码解析 导读 @blueprintjs/datetime
前端UI组件设计系统Material DateTime Picker:现代化时间日期选择组件的完整指南
Material DateTime Picker:现代化时间日期选择组件的完整指南 Material DateTime Picker是一个遵循Material
UI组件移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考