news 2026/9/19 9:14:16

date-fns 意大利语(it)locale 完整指南:format/parse 令牌、距离与时长格式化对照速查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
date-fns 意大利语(it)locale 完整指南:format/parse 令牌、距离与时长格式化对照速查

date-fns 意大利语(it)locale 完整指南:format/parse 令牌、距离与时长格式化对照速查

【免费下载链接】date-fns⏳ Modern JavaScript date utility library ⌛️项目地址: https://gitcode.com/gh_mirrors/da/date-fns

本篇指南以 date-fns 仓库中 pkgs/core/src/locale/it/snapshot.md 为骨架,系统梳理意大利语 locale 在formatparseformatDistanceformatDistanceStrictformatRelativeformatDuration六大 API 下的全部本地化输出。读者可将其作为意大利语日期格式化的“预期行为对照表”,用于调试输出、编写测试断言,并理解 date-fns 多语言 locale 的数据组织方式与底层实现原理。

一、snapshot.md 是什么:locale 的“行为快照”

在 date-fns 仓库中,每个语言 locale 目录下都有一份snapshot.md文件。以意大利语为例,其路径为 pkgs/core/src/locale/it/snapshot.md,它由构建脚本 pkgs/core/scripts/build/localeSnapshots/index.ts 自动生成:脚本遍历所有 locale,对format/parse/formatDistance/formatDistanceStrict/formatRelative/formatDuration六个 API 分别渲染固定输入,把输出结果以 Markdown 表格的形式写入每个 locale 目录下的snapshot.md。该脚本支持generate(默认,重新生成快照)与test(比对磁盘快照与生成结果,不一致即报错)两种模式,并要求在TZ=utc环境下运行。

快照的用途在 pkgs/core/docs/i18nContributionGuide.md 中有明确说明:快照即 locale 的测试基准。新增或修改语言后,需运行pnpm run locale-snapshots重新生成快照,人工审查输出值是否符合该语言的语法习惯,再随代码一并提交。快照与实现不一致时,test模式会直接失败,从机制上防止本地化文案悄悄回归。

意大利语 locale 的入口为 pkgs/core/src/locale/it/index.ts,其导出对象由五个数据模块拼装而成:

export const it: Locale = { code: "it", formatDistance: formatDistance, formatLong: formatLong, formatRelative: formatRelative, localize: localize, match: match, options: { weekStartsOn: 1 /* Monday */, firstWeekContainsDate: 4, }, };

其中options.weekStartsOn: 1表示意大利语一周从星期一开始,firstWeekContainsDate: 4表示每年的第一周包含当年 1 月 4 日(符合 ISO 8601 周历约定)。这两个选项直接影响快照中 “Local week-numbering year”“Local week of year”“Local day of week” 等令牌的计算结果。

二、format 与 parse:令牌到意大利语文本的完整映射

快照中formatparse两个 API 共用一张大表:左边输入固定的 UTC 时间戳,中间是令牌字符串,右边分别是format的输出与parse的输出。parse的结果会解析回“该文本所代表的当日起点/时段起点”,因此表中parse result常出现整点(如T00:00:00.000Z)或时段起始(如T04:00:00.000Z)。

2.1 年份与季度

标题令牌format 示例说明
Calendar year(历年)yo1987/5序数形式,直接输出数字,无后缀
Local week-numbering yearYo1987/4基于本地周历(周一起始、含 1 月 4 日)的年份
Quarter(formatting)Qo/QQQ/QQQQ/QQQQQ1T11º trimestre1缩写用T1~T4,宽式用1º trimestre
Quarter(stand-alone)qo/qqq/qqqq/qqqqq同 Q 系列独立上下文(如列表)使用

从源码 pkgs/core/src/locale/it/_lib/localize/index.ts 可看到季度数据:

const quarterValues = { narrow: ["1", "2", "3", "4"], abbreviated: ["T1", "T2", "T3", "T4"], wide: ["1º trimestre", "2º trimestre", "3º trimestre", "4º trimestre"], };

注意年份Yo的差异:1987-02-11在本地周历中仍属 1987 年,但0005-01-01(公历 1 月 1 日)在意大利周历中属于上一年的第 52 周,因此Yo输出为4parse结果回退到0003-12-29。这是weekStartsOn: 1firstWeekContainsDate: 4联合作用的典型表现。

2.2 月份:格式化的五种宽度

月份是本地化最丰富的部分,M(formatting)与L(stand-alone)各有五种宽度:

宽度令牌示例(1 月/5 月)对应数据
数字序数Mo/Lo1ordinalNumber
缩写MMM/LLLgen/magmonthValues.abbreviated
全称MMMM/LLLLgennaio/maggiomonthValues.wide
单个字母MMMMM/LLLLLG/MmonthValues.narrow

意大利语月份缩写全部取前三个字母gen, feb, mar, apr, mag, giu, lug, ago, set, ott, nov, dic),与英文的Jan式缩写形成鲜明对比。窄式单字母存在歧义(M同时代表 marzo 和 maggio,A代表 aprile 和 agosto),快照中MMMMM对 5 月与 3 月都输出M即为此歧义的体现,这类歧义由 pkgs/core/src/locale/it/_lib/match/index.ts 中的解析正则处理(窄式按首字母匹配、any宽度按ge/f/mar/ap/mag/gi/l/ag/s/o/n/d前缀区分)。

2.3 星期:格式化、ISO 与本地三种体系

快照中星期相关令牌分三大类,每类五种宽度(o/E/i/e/c后缀的数字序数 + 三/四/五/六字母):

  • Day of week(E系列,格式化)EEElunEEEElunedìEEEEEL(首字母,Lunedì 取L),EEEEEElun
  • ISO day of week(i系列)io输出 1~7(周一=1),iiiilunedì
  • Local day of week(e/c系列):意大利语本地周从周一开始,因此eo对周一输出1c系列为 stand-alone。

一个值得注意的细节:EEEEEEiiiiii/eeeee/cccccc这类最短宽度的 parse 结果是Invalid Date。快照原样记录了该行为——三字母缩写lun同时对应“短格式”与“窄格式”数据(见源码dayValues.shortdayValues.abbreviated内容相同),解析器无法把lun唯一映射回某个宽度,故返回Invalid Date。这是快照作为“行为基准”最有价值的部分:它如实记录边界行为,而非掩盖。

2.4 一天中的时段:AM/PM、正午午夜与弹性时段

意大利语的时段表达相当讲究,快照覆盖三类令牌:

  • a/b系列(AM/PM 与 正午/午夜):宽式均为AM/PM(意大利语书面语直接使用拉丁缩写);窄式aaaaa/bbbbb输出m.p.。快照显示m.可解析回当天T00:00:00.000Z,而p.的 parse 结果为Invalid Date(因为p.与日期的“前一天/后一天”判断存在歧义,解析器无法确定基准时刻)。
  • B系列(Flexible day period,弹性时段):意大利语按一天四段表达:
时间点format 输出parse 结果
11:13di mattina(早上)T04:00:00.000Z(凌晨 4 点起)
14:13del pomeriggio(下午)T12:00:00.000Z(正午起)
19:13di sera(晚上)T17:00:00.000Z(17 点起)
02:13di notte(夜里)T00:00:00.000Z(零点起)

其数据源见 localize/index.ts 中的formattingDayPeriodValuesmorning/afternoon/evening/night分别对应di mattina/del pomeriggio/di sera/di notte),解析端由 match/index.ts 的matchDayPeriodPatterns正则((di|del) (mattina|pomeriggio|sera|notte))负责回读。

2.5 小时、分钟、秒与序数

ho/Ho/Ko/ko四种小时制(1-12、0-23、0-11、1-24)、mo(分钟)、so(秒)均为序数令牌,意大利语序数输出即普通数字(ordinalNumber直接String(number),无º后缀——注意matchOrdinalNumberPattern虽允许º输入,但输出不带)。快照显示Ho对 23 点输出23ho对 23 点输出11(12 小时制),Ko对 23 点输出11(0-11 制),ko对 23 点输出23(1-24 制)。

2.6 本地化长格式:P/p 系列组合

formatLong定义了意大利语的长格式模板,见 pkgs/core/src/locale/it/_lib/formatLong/index.ts:

const dateFormats = { full: "EEEE d MMMM y", long: "d MMMM y", medium: "d MMM y", short: "dd/MM/y", }; const timeFormats = { full: "HH:mm:ss zzzz", long: "HH:mm:ss z", medium: "HH:mm:ss", short: "HH:mm", };

对应的快照输出:

  • P(短日期)→11/01/1987(日/月/年,意大利语顺序)
  • PP(中日期)→11 gen 1987
  • PPP(长日期)→11 gennaio 1987
  • PPPP(完整日期)→domenica 11 gennaio 1987(含星期)
  • p12:13pp12:13:14
  • ppp/pppp12:13:14 GMT+0/12:13:14 GMT+00:00,其 parse 结果为Errored(带时区缩写/偏移的长时间无法被parse回读,快照如实标注)
  • Pp11/01/1987 12:13PPpp11 gen 1987 12:13:14,依此类推PPPppp/PPPPpppp组合同样 Errored

日期时间组合模板dateTimeFormats使用{{date}} {{time}}占位符拼接。快照中1453-05-29这一历史日期(君士坦丁堡陷落日)用于验证任意年份的兼容性,PP输出29 mag 1453PPPP输出domenica 29 maggio 1453

三、formatDistance:模糊距离的意大利语表达

快照假设now = 2000-01-01 00:00,列出目标日期对应的模糊距离文本。意大利语的量词体系与英文类似但更细致,核心规则(见 formatDistance/index.ts)为:count === 1时取one形式,否则用other模板替换{{count}}

时间差默认输出includeSeconds: trueaddSuffix: true
25 秒内meno di un minutomeno di 20 secondi/meno di 10 secondi/meno di 5 secondi/alcuni seconditra meno di un minuto/meno di un minuto fa
1 分钟un minutoun minutotra un minuto/un minuto fa
45 分钟circa un'ora同左tra circa un'ora
1 天un giorno同左tra un giorno
2 个月2 mesi同左tra 2 mesi
1 年circa un anno同左tra circa un anno
6 年以上circa 6 anni同左tra circa 6 anni

关键细节:

  • 单复数形态un giorno(1 天)对{{count}} giorni(多天);un mese/mesiun anno/anni同理。
  • 约数表达circa(大约)用于小时、周、月、年级别,如circa 6 orecirca un anno;超过 1 年 6 个月则升级为più di un anno(超过一年)。
  • 秒级细分includeSeconds: true时按 5/10/20 秒分档,halfAMinute输出alcuni secondi(若干秒)。
  • 方向后缀addSuffix: true时未来加前缀tra(“在……之后”),过去加后缀fa(“……之前”),例如tra 5 mesi5 mesi fa。该逻辑位于源码 formatDistance/index.ts:
if (options?.addSuffix) { if (options.comparison && options.comparison > 0) { return "tra " + result; } else { return result + " fa"; } }
  • 注意meno di un minuto(不到一分钟)在未来方向是tra meno di un minuto,过去方向是meno di un minuto fa——fa紧跟量词而非minuto

四、formatDistanceStrict:精确距离与强制单位

formatDistanceStrict不做约化,直接给出精确数值;配合unit选项可强制以指定单位输出。快照第三列展示了强制小时(hour)单位时的换算结果:

日期默认结果addSuffix: true强制hour
2001-01-01un annotra un anno8784 ore
2000-06-015 mesitra 5 mesi3648 ore
2000-01-02un giornotra un giorno24 ore
2000-01-01 06:006 oretra 6 ore6 ore
1999-12-31 23:59un minutoun minuto fa0 ore
1994-01-016 anni6 anni fa52584 ore

三个可验证的细节:

  1. 严格量化:45 分钟默认输出45 minuti(不同于formatDistancecirca un'ora)。
  2. 单位换算:强制小时时,1 年 =8760 ore(平年)、2001 年跨闰日故 2000-06-01 至 2001-06-01 为8784 ore(闰年 366 天),6 年跨 2000 闰年 =52584 ore(= 6×8760 + 24)。快照中的数值与公历闰年规则完全吻合。
  3. 过去后缀addSuffix: true对过去输出un anno fa6 anni fa

五、formatRelative:相对日期文案

formatRelative把“今天/昨天/明天/本周内”等相对关系转成带时间的地道文案(now = 2000-01-01 00:00):

日期输出
2000-01-1010/01/2000(超出周范围,回退为短日期P
2000-01-05mercoledì prossimo alle 00:00
2000-01-02domani alle 00:00
2000-01-01oggi alle 00:00
1999-12-31ieri alle 00:00
1999-12-27lunedì alle 00:00
1999-12-2121/12/1999

实现位于 formatRelative/index.ts,要点:

  • today/tomorrow/yesterday模板为'oggi alle' p'domani alle' p'ieri alle' pp是短时间HH:mm)。
  • 上周/下周模板按星期几分单复数:domenica scorsa alle/domenica prossima alle(阴/阳性特殊),其他星期用lunedì scorso allemercoledì prossimo alle等——注意scorso/prossimo的性数随星期名词变化(domenica 为阴性)。
  • lastWeek/nextWeek通过isSameWeek(复用 pkgs/core/src/isSameWeek/index.ts,并透传 locale 的weekStartsOn: 1选项)判断目标日期是否与基准日同属一周,若同周则退化为thisWeek'lunedì alle' p形式。
  • 超出上述范围的日期回退到other: "P",即dd/MM/y短日期。

六、formatDuration:时长对象的本地化

formatDuration接收形如{"years":2, "months":1}的时长对象,按单位键逐项输出意大利语文本(快照只验证单键情况):

时长输出
{"years":1}un anno
{"years":2}2 anni
{"months":1}un mese
{"months":2}2 mesi
{"weeks":1}una settimana
{"weeks":2}2 settimane
{"days":1}un giorno
{"hours":1}un'ora
{"minutes":1}un minuto
{"seconds":2}2 secondi

值得注意的形态变化:un'ora(一元音省略,una 遇 ora 省略 a)、una settimana(阴性单数)、2 ore0 anni(零值也走复数形式)。这些文案同样定义在 formatDistance/index.ts 的量词表中,formatDurationformatDistance共用同一套单复数数据,保证两类 API 的措辞一致。

七、如何验证与复现:快照的生成与检查

快照本身既是文档又是测试基准,若需在本地复现或更新意大利语快照:

  1. 在仓库根目录安装依赖后,以 UTC 时区运行快照生成命令(该脚本强制要求TZ=utc,见 localeSnapshots/index.ts):
    TZ=utc pnpm run locale-snapshots

    生成结果会覆盖写入pkgs/core/src/locale/it/snapshot.md

  2. 若要检查磁盘上的快照与当前实现是否一致(CI 校验模式):
    TZ=utc pnpm run locale-snapshots test

    不一致时脚本会抛出The snapshot on the disk doesn't match the generated snapshot...错误,提示重新生成并提交。

在应用层验证意大利语输出,可直接引入 locale 并与format/formatDistance组合使用(示例):

import { format, formatDistance, formatRelative, formatDuration } from "date-fns"; import { it } from "date-fns/locale"; const date = new Date("1987-02-11T12:13:14.000Z"); format(date, "PPPP", { locale: it }); // "mercoledì 11 febbraio 1987" format(date, "PPpp", { locale: it }); // "11 feb 1987 12:13:14" formatDistance(new Date("2000-06-01T00:00:00.000Z"), new Date("2000-01-01T00:00:00.000Z"), { locale: it, addSuffix: true, }); // "tra 5 mesi" formatRelative(new Date("2000-01-02T00:00:00.000Z"), new Date("2000-01-01T00:00:00.000Z"), { locale: it, }); // "domani alle 00:00" formatDuration({ years: 1, months: 2, days: 3 }, { locale: it }); // "un anno 2 mesi 3 giorni"

八、小结

意大利语 snapshot 展示了一个高质量 locale 的全部要素:五种宽度的月份/星期词汇、1º trimestre式季度表达、di mattina/del pomeriggio/di sera/di notte弹性时段、tra … / … fa方向后缀、circa/più di模糊量词,以及scorso/prossimo的性数变化。同时快照如实记录了若干边界行为(最短宽度星期的Invalid Date、带时区长度的 Errored),这些正是调试parse回读时最容易被忽视的坑。

对开发者的实用建议:

  • 需要“预期值”时,直接查阅本快照对应语言的文件(如意大利语为 pkgs/core/src/locale/it/snapshot.md),无需运行代码即可断言输出;
  • 修改任何 locale 实现后,务必重新生成并审查快照,再提交到版本库;
  • 若发现format能输出但parse返回Invalid Date或 Errored,请先对照快照确认是否为该语言已知的固有行为,再决定是否值得为解析器补充歧义消解规则。

关联参考文件:locale 入口、本地化数据、匹配/解析正则、长格式模板、相对格式实现、距离量词表、快照生成脚本、i18n 贡献指南。

【免费下载链接】date-fns⏳ Modern JavaScript date utility library ⌛️项目地址: https://gitcode.com/gh_mirrors/da/date-fns

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 9:12:22

Flutter折叠屏适配实战:窗口布局、双栏路由与状态连续性

折叠屏早就不是发布会上的概念机了,身边拿三星 Z Fold、华为 Mate X 系列、小米 MIX Fold 当主力机的人越来越多,OPPO Find N 也有一批忠实用户。但很多 Flutter 开发者还没意识到,折叠屏不能简单粗暴地当成“大屏手机”来处理。屏幕从合上到…

作者头像 李华
网站建设 2026/9/19 9:09:55

BCIC IV 2a数据集实战:从下载到CSP分类的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 9:06:04

Git核心操作全解析:add、commit、push的原理与实战

只要你写过几天代码,就应该听过Git那句经典口诀:add、commit、push。很多教程把它叫作“向仓库提交代码三步走”,听起来简单到不能再简单,可真到了实际项目里,我见过太多人在这一步上栽跟头。有人习惯性git add .&…

作者头像 李华
网站建设 2026/9/19 9:04:42

UE4 Marschner头发渲染实战:从塑料假发到次世代发丝

头发渲染一直是实时渲染里最容易被低估的一块。很多团队把角色皮肤打磨得很细,结果一顶头发上去,整个角色的质感直接掉一个档次——要么像塑料假发,要么像一坨糊在一起的毛线。我在几个UE4项目里反复折腾过头发,从最早的各向同性高…

作者头像 李华
网站建设 2026/9/19 9:03:38

Spring Boot微服务容器化部署实战指南

1. 从零开始构建Spring Boot微服务并容器化部署作为一名长期奋战在一线的Java开发者,我亲历了微服务架构从概念到落地的全过程。今天要分享的是一个看似简单但极具代表性的实战案例:将一个Spring Boot微服务打包成Docker镜像并运行。这个案例涵盖了从项目…

作者头像 李华
网站建设 2026/9/19 9:02:04

SMPTE 274M标准解析:1080p视频时序、SAV/EAV与YCbCr采样

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华