NocoBase 模板打印时间间隔格式化::formatI 语法、单位换算与人性化输出完全指南
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
时间间隔(时长)格式化是业务单据打印中最高频的需求之一:工单耗时、服务时长、保修周期、倒计时提示,都需要把原始的毫秒数值或 ISO 8601 时长字符串翻译成人类可读的文本。NocoBase 模板打印提供的:formatI(patternOut, patternIn)格式化器,专门用于完成这类转换——它既能输出2、60、28这样的纯数值时长,也能输出"a few seconds"、"in a few seconds"、"a few seconds ago"这样的人性化文案,还能直接解析P1M、P1Y2M3DT4H5M6S等 ISO 8601 时长字符串。读完本文,你将完整掌握formatI的全部输出单位、单位换算规则、人性化模式以及在实际打印模板中的组合用法。
1. formatI 在模板打印格式化器体系中的位置
NocoBase 模板打印的格式化器(formatter)是一组把原始数据转换成可读文本的处理器,统一通过冒号(:)应用于数据,且可以链式调用——每个格式化器的输出会作为下一个格式化器的输入,详见 格式化工具总览。其基本调用形式为:
{d.属性:formatter1:formatter2(...)}例如,先lowerCase再ucFirst,可以把"JOHN"渲染为"John":
My name is {d.name:lowerCase:ucFirst}. I was born on {d.birthday:formatD(LL)}.formatI正是这套格式化器体系中负责"时长 / 时间间隔"处理的成员,与负责"日期时刻"的formatD(见 日期格式化)形成互补:formatD回答"这一刻是哪天几点",formatI回答"这段时间有多长、怎么读"。
2. :formatI(patternOut, patternIn) 语法说明
{值:formatI(patternOut, patternIn)}参数定义:
| 参数 | 是否必填 | 说明 |
|---|---|---|
patternOut | 必填 | 输出格式,例如'second'、'human+',决定结果以什么单位或什么风格呈现 |
patternIn | 可选 | 输入单位,例如'milliseconds'、's',用于声明原始值的单位;省略时默认按毫秒(milliseconds)解析 |
其中patternOut支持两大类输出格式:
- 人性化显示:
human+、human(适合直接展示给最终用户阅读); - 数值单位:
millisecond(s)、second(s)、minute(s)、hour(s)、year(s)、month(s)、week(s)、day(s)等单位(或其简写),适合后续参与计算或按固定单位对齐展示。
单位简写约定与 diffD 日期差值计算 保持一致,例如s表示秒、ms表示毫秒、h表示小时、d表示天。此外,格式化器的常量参数如果包含逗号或空格,需要用单引号包裹(如prepend('my prefix')),formatI的格式参数同样遵循这一约定。
3. 数值输出:把毫秒换算成指定单位
当patternOut指定为某个时间单位时,formatI会将输入值换算到该单位并返回数值。以下示例默认输入单位为毫秒(ms):
2000:formatI('second') // 输出 2 2000:formatI('seconds') // 输出 2 2000:formatI('s') // 输出 2 3600000:formatI('minute') // 输出 60 3600000:formatI('hour') // 输出 1 2419200000:formatI('days') // 输出 28从这些示例可以归纳出单位换算关系与典型取值:
| 输入(毫秒) | 换算关系 | 输出单位 | 结果 |
|---|---|---|---|
2000 | 2000 ÷ 1000 | second(s)/s | 2 |
3600000 | 3600000 ÷ 60000 | minute(s) | 60 |
3600000 | 3600000 ÷ 3600000 | hour(s) | 1 |
2419200000 | 2419200000 ÷ 86400000 | day(s)/days | 28 |
可见单数(second、minute、hour、day)与复数(seconds、minutes、hours、days)写法等效,简写(如s)同样被接受。换算按标准进制执行:1 秒 = 1000 毫秒,1 分钟 = 60 秒,1 小时 = 60 分钟,1 天 = 24 小时,1 周 = 7 天。需要注意的是,月(month)与年(year)属于非整数倍单位,具体折算系数见第 6 节关于 ISO 8601 解析的说明。
4. 人性化输出:human 与 human+
当patternOut为human或human+时,结果不再是纯数值,而是适合界面展示的自然语言文案:
2000:formatI('human') // 输出 "a few seconds" 2000:formatI('human+') // 输出 "in a few seconds" -2000:formatI('human+') // 输出 "a few seconds ago"从输出风格看,formatI的人性化文案遵循 humanize-duration 一类库的约定,human与human+的差异在于:
human:直接输出时长描述,如"a few seconds"(数秒);human+:针对正值附加"未来"语义前缀,输出"in a few seconds"(在几秒后);针对负值附加"过去"语义后缀,输出"a few seconds ago"(几秒前)。
这一特性特别适合倒计时、有效期剩余时间、任务执行耗时等场景。例如"距离任务开始还有几秒"可以这样渲染:
距离开标还有 {d.timeLeft:formatI('human+')}当d.timeLeft为正值时显示"in …",为负值时自动切换为"… ago",模板无需自己判断正负号。
5. 单位换算:通过 patternIn 声明输入单位
当原始数据不是毫秒时,可以通过第二个参数patternIn声明输入单位,formatI会先把输入换算成毫秒,再按patternOut输出:
60:formatI('ms', 'minute') // 输出 3600000 4:formatI('ms', 'weeks') // 输出 2419200000- 第一个示例:输入值为
60、单位为minute(分钟),先换算为 60 × 60000 = 3600000 毫秒,再以ms(毫秒)输出,结果为3600000; - 第二个示例:输入值为
4、单位为weeks(周),先换算为 4 × 7 × 86400000 = 2419200000 毫秒,再以ms输出,结果为2419200000。
这一能力让模板可以直接消费来自不同数据源、不同单位约定的字段:数据库里存的是分钟,就写patternIn = 'minute';表单提交的是周数,就写patternIn = 'weeks',无需在数据入库前预先做单位归一化。
6. 直接解析 ISO 8601 时长字符串
除了纯数值,formatI还能直接解析 ISO 8601 时长字符串(P...T...格式),这是处理跨系统时长数据时非常实用的能力:
'P1M':formatI('ms') // 输出 2628000000 'P1Y2M3DT4H5M6S':formatI('hour') // 输出 10296.085P1M表示 1 个月,按"月 = 365 ÷ 12 天"折算为 30.416666… 天,即 2628000000 毫秒;P1Y2M3DT4H5M6S表示 1 年 2 个月 3 天 4 小时 5 分 6 秒,按"年 = 365 天、月 = 365 ÷ 12 天"折算后以小时输出,结果为 10296.085 小时(即 8760 + 1460 + 72 + 4 + 0.0833… + 0.00166… ≈ 10296.085)。
由此可以推断formatI对非整数单位的折算采用以下基准(与上述官方示例的计算结果完全吻合):
- 1 年 = 365 天
- 1 月 = 365 ÷ 12 ≈ 30.4166667 天
- 1 周 = 7 天
- 1 天 = 24 小时 = 86400000 毫秒
因此在对"月 / 年"级时长做精确换算时,应留意结果包含小数(如10296.085小时),模板中若需取整展示,可再结合数值格式化器处理。
7. 与日期类格式化器组合的实战场景
formatI与模板打印中的日期格式化器搭配,可以覆盖"起止时间 → 时长 → 可读文案"的完整链路:
- 计算两个日期的差值再人性化展示:先用
diffD求出两个日期之间的毫秒差,再交给formatI输出。diffD默认输出单位为毫秒(详见 日期格式化),其返回值正好可以作为formatI的输入:
{d.endDate:diffD(d.startDate):formatI('human')} // 例如 "a few seconds" {d.endDate:diffD(d.startDate, 'minutes'):formatI('hour')} // 先按分钟求差,再换算为小时- 到期提醒文案:用
diffD求出"当前时间 - 截止时间"的差值(负值表示已过期),再以formatI('human+')输出,自动得到"还有 X"或"X 之前"的文案; - 工期 / 服务时长统计:直接用毫秒字段
formatI('days')输出精确到天的时长,或用formatI('hours')输出精确到小时的工时。
由于格式化器支持链式调用(前一个的输出作为后一个的输入),上述组合无需编写脚本,纯模板即可实现。
8. 使用注意事项
- 默认输入单位是毫秒:省略
patternIn时,数值输入一律按毫秒解析。如果字段实际单位是秒或分钟,务必显式声明patternIn,否则结果会差几个数量级; patternOut使用字符串字面量:与格式化器常量参数约定一致,格式串建议用单引号包裹,如formatI('seconds');- 月 / 年换算存在小数:ISO 8601 与"月 / 年"单位的折算基于 365 天/年、365÷12 天/月,结果可能为小数,按需配合取整格式化器;
- 数值与人性化输出并存:需要参与后续计算时用单位输出(
second、hour等),仅需展示时用human/human+,避免把可读文案再喂给数值计算; - 适用版本:本文语法以当前仓库 模板打印文档 及其 安装说明 为准,模板打印为商业插件,使用时请先按官方商业插件激活流程完成激活(Docker 环境如需生成 PDF,还需按 安装文档 安装 LibreOffice)。
综上,formatI以两个参数覆盖了"数值 → 指定单位"、"数值 → 人性化文案"、"指定输入单位 → 毫秒归一"、"ISO 8601 字符串 → 任意单位"四类转换,是 NocoBase 模板打印中处理时长类字段的核心工具,值得在每张涉及时间的单据模板中优先选用。
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考