首页
/ freeCodeCamp 实战:使用 HTML5 time 元素与 datetime 属性标准化页面中的时间表达

freeCodeCamp 实战:使用 HTML5 time 元素与 datetime 属性标准化页面中的时间表达

2026-09-06 14:27:46作者:裴锟轩Denise

本文基于 freeCodeCamp 响应式网页设计认证(Responsive Web Design)中 "Applied Accessibility"(应用无障碍)模块的一道实战挑战(标准题文件),讲解 HTML5 time 元素与 datetime 属性的用法。读完本文,你将掌握如何用机器可读的标准化格式标注页面中的日期与时间、如何在无障碍场景中为辅助技术提供可靠数据,并能独立完成这道挑战的完整解法与测试验证。

挑战背景:freeCodeCamp 无障碍课程体系中的定位

该挑战属于 freeCodeCamp 课程库中的 Applied Accessibility 模块。从课程结构文件 responsive-web-design.json 可以看到,该模块是 "Responsive Web Design" 认证 superblock 下的第 4 个 block,排在基础 HTML、基础 CSS 与应用视觉设计之后。

模块内部的题目顺序由 applied-accessibility.json 中的 challengeOrder 数组定义。本文对应的挑战 "Standardize Times with the HTML5 datetime Attribute" 排在第 14 位,前面紧邻 "Add an Accessible Date Picker"(使用 <input type="date"> 构建无障碍日期选择器),后面则进入 "Make Elements Only Visible to a Screen Reader by Using Custom CSS"(CSS 视觉隐藏技术)。也就是说,这是一条围绕"日期与时间"主题的连续学习链:先学习表单中的日期输入控件,再学习正文中对时间的语义化标注。

该模块所有题目共享一个贯穿始终的 Camper Cat(忍者猫主题)叙事场景——本页挑战的场景是 Camper Cat 举办《真人快打》(Mortal Kombat)锦标赛后的问卷调查结果公告。

核心概念:time 元素与 datetime 属性

延续日期主题,HTML5 引入了 time 元素和 datetime 属性来标准化页面中的时间表达:

  • time 元素:一个行内(inline)元素,用于包裹页面中的日期或时间文本;
  • datetime 属性:承载该日期/时间的标准化格式值。辅助技术(如屏幕阅读器)访问的正是这个属性值,而非元素的可见文本。

其核心价值在于:即使正文中的时间是用非正式、口语化的方式书写(例如 "last Wednesday"),datetime 属性仍然能提供一份标准化、无歧义的时间表述,既帮助辅助设备正确播报,也方便搜索引擎和脚本进行机器可读的解析。

原文档给出的示例如下:

<p>Master Camper Cat officiated the cage match between Goro and Scorpion <time datetime="2013-02-13">last Wednesday</time>, which ended in a draw.</p>

注意可见文本是口语化的 "last Wednesday",但 datetime="2013-02-13" 给出了精确的 ISO 格式日期——这正是"人机双友好"的写法。

datetime 属性支持的格式在挑战的起始代码(seed)中恰好都有体现:

格式 示例 说明
仅日期 datetime="2016-09-15" 形如 YYYY-MM-DD,本题要求使用
日期加时间(UTC) datetime="2016-08-13T20:01Z" 完整日期时间,T 分隔符 + Z 表示 UTC 时区,见 seed 中的评论区时间戳

实战题目:为调查结果的日期添加 time 标签

任务要求

Camper Cat 的《真人快打》调查结果出炉了!题目要求:time 标签包裹文本 Thursday, September 15<sup>th</sup>,并为其添加值为 2016-09-15datetime 属性。

起始代码(seed)

挑战的编辑区起始代码如下(节选自 挑战文件--seed-- 部分):

<body>
  <header>
    <h1>Tournaments</h1>
  </header>
  <article>
    <h2>Mortal Kombat Tournament Survey Results</h2>

    <!-- Only change code below this line -->

    <p>Thank you to everyone for responding to Master Camper Cat's survey. The best day to host the vaunted Mortal Kombat tournament is Thursday, September 15<sup>th</sup>. May the best ninja win!</p>

    <!-- Only change code above this line -->

    <section>
      <h3>Comments:</h3>
      <article>
        <p>Posted by: Sub-Zero on <time datetime="2016-08-13T20:01Z">August 13<sup>th</sup></time></p>
        <p>Johnny Cage better be there, I'll finish him!</p>
      </article>
      <article>
        <p>Posted by: Doge on <time datetime="2016-08-15T08:12Z">August 15<sup>th</sup></time></p>
        <p>Wow, much combat, so mortal.</p>
      </article>
      <article>
        <p>Posted by: The Grim Reaper on <time datetime="2016-08-16T00:00Z">August 16<sup>th</sup></time></p>
        <p>Looks like I'll be busy that day.</p>
      </article>
    </section>
  </article>
  <footer>&copy; 2018 Camper Cat</footer>
</body>

可以看到,页面下方的评论区已经用 <time datetime="..."> 正确标注了日期——这就是需要模仿的参照写法;而正文中 "Thursday, September 15th" 这一处还是裸文本,等待你的改造。

参考解答

将目标日期文本用 <time> 包裹并加上 datetime 属性后,目标段落应变为:

<p>Thank you to everyone for responding to Master Camper Cat's survey. The best day to host the vaunted Mortal Kombat tournament is <time datetime="2016-09-15">Thursday, September 15<sup>th</sup></time>. May the best ninja win!</p>

完整解答与起始代码的差异仅在于该 <p> 元素(其余 header、评论区、footer 均保持不变)。

几个实现要点:

  1. <time> 必须恰好包裹 Thursday, September 15<sup>th</sup> 这段内容——包含其中的 <sup>th</sup> 上标标签,但不要把句尾的句号或前后文字包进去;
  2. datetime 属性值为仅日期格式 2016-09-15YYYY-MM-DD),与评论区使用的完整日期时间格式不同,因为此处文本只表达了"某一天",没有具体时刻。

测试断言如何验证你的答案

该挑战的自动判题逻辑(位于挑战文件的 --before-all----hints-- 部分)通过 DOM 查询来验证答案,其辅助函数结构如下:

const getTimeElement = () => {
  const pElement = [...document.querySelectorAll("article > p")]
  .filter(x => x?.textContent?.includes("Thank you to everyone for responding to Master Camper Cat's survey."));

  return pElement[0] ? pElement[0].querySelector("time") : null;
};

const getDatetimeAttr = () => {
  const timeElement = getTimeElement();
  return timeElement?.getAttribute("datetime");
};

从源码结构看,判题器先定位包含 "Thank you to everyone..." 文本的 article > p 元素,再在其中查找 time 子元素,最后读取其 datetime 属性值。对应的四条断言依次检查:

// 1. 目标段落中必须存在 time 元素
assert.exists(getTimeElement());

// 2. time 元素内部 HTML 必须精确等于目标文本(含 sup 标签)
assert.strictEqual(getTimeElement()?.innerHTML?.trim(), 'Thursday, September 15<sup>th</sup>');

// 3. datetime 属性不能为空
assert(getDatetimeAttr()?.length != 0);

// 4. datetime 属性值必须精确等于 2016-09-15
assert.equal(getDatetimeAttr(), '2016-09-15');

这组断言揭示了两个容易踩坑的细节:

  • 断言 2 用 strictEqual 比较 innerHTML,意味着包裹范围必须分毫不差——多包一个句号、少包一个 <sup> 都会失败;
  • 断言 3 与 4 分开校验"属性存在"和"属性值正确",因此即使写成了 2016-09-15T00:00Z(合法但非题目要求的格式),第 4 条仍会失败。

为什么这对无障碍很重要

time 元素的价值在三个层面:

  1. 辅助技术层面:屏幕阅读器可以播报 datetime 属性给出的标准化时间,而不是逐字朗读口语化文本;
  2. 语义层面<time> 是 HTML5 的语义化元素,它明确告诉浏览器"这里的时间是一个时间实体",配合 datetime 形成机器可读的元数据;
  3. 可维护层面:正文可以保留自然的语言风格("last Wednesday"、"Thursday, September 15th"),机器解析则依赖标准化格式,两者互不干扰。

在 freeCodeCamp 的这套模块中,<time> 与上一题的 <input type="date"> 形成互补:前者负责展示层的时间语义化,后者负责表单输入层的日期采集。完成本题后,下一题(仅对屏幕阅读器可见的元素)将转向 CSS 视觉隐藏技术(sr-only),继续延伸"视觉呈现与辅助技术访问解耦"这一核心无障碍思想。

小结

  • HTML5 time 是行内元素,datetime 属性存放标准化的日期/时间值,是辅助设备实际访问的数据源;
  • datetime 可取仅日期格式(2016-09-15)或完整日期时间格式(2016-08-13T20:01Z),应按文本实际表达的精度选择;
  • 本题的关键是把 <time datetime="2016-09-15"> 精确包裹在 Thursday, September 15<sup>th</sup> 周围,判题器会通过 querySelectorgetAttribute("datetime") 做精确比对;
  • 相关素材均可在当前仓库中查阅:挑战文件模块顺序配置 以及 superblock 结构
登录后查看全文
热门项目推荐
相关项目推荐