You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Luxon DateTime.toFormat('t')生成非断空格问题及解决方法咨询

如何让Luxon使用自带格式't'时输出普通空格而非非断空格?

在从MomentJS迁移到Luxon的过程中,实现BusinessHours的getter方法时,用Luxon的toFormat('t')替代Moment的format('LT')后,Jest测试失败。原因是toFormat('t')生成的时间字符串中,数字和AM/PM之间是非断空格(NNBSP,Unicode编码\u00A0),而测试预期是普通空格。手动改用h:mm a格式可以解决问题,但希望能保留使用Luxon自带格式t的方式。

相关代码

迁移后的Luxon代码:

get KeyBusinessHours(): string {
    if (this.Report.Type === ReportType.InternetHealth) {
        let start = DateTime.fromMillis(0);
        start = start.plus(GetDurationAmount('minutes', this.Options['KeyBusinessHoursStart']));
        let end = DateTime.fromMillis(0);
        end = end.plus(GetDurationAmount('minutes', this.Options['KeyBusinessHoursEnd']));
        // 不转换到用户时区,仅展示所选时间及对应时区 - 使用UTC
        return `${start.toUTC().toFormat('t')} - ${end.toUTC().toFormat('t')}${this.Options['TimezoneForReport'] != null ?
            `(${this.Options['TimezoneForReport']})` : ''}`;
    }
    return undefined;
}

原MomentJS代码:

get KeyBusinessHours(): string {
    if (this.Report.Type === ReportType.InternetHealth) {
        let start = moment(0);
        start.add(this.Options['KeyBusinessHoursStart'], 'minutes');
        let end = moment(0);
        end.add(this.Options['KeyBusinessHoursEnd'], 'minutes');
        // 不转换到用户时区,仅展示所选时间及对应时区 - 使用UTC
        return `${start.utc().format('LT')} - ${end.utc().format('LT')} (${this.Options['TimezoneForReport']})`;
    }
    return undefined;
}

测试失败信息

Expected substring: "2:00 AM - 4:00 AM"
Received string:    "2:00 AM - 4:00 AM"

解决方案

Luxon的't'格式对应本地化配置中的shortTime,默认使用非断空格是符合部分地区排版规范的,但可以通过以下方式修改为普通空格:

1. 全局修改本地化格式

通过Settings.updateLocale修改对应语言的shortTime格式,将其中的非断空格替换为普通空格。以英文(en-US)为例:

import { Settings } from 'luxon';

// 先设置默认locale(如果项目已设置可省略)
Settings.defaultLocale = 'en-US';
// 更新locale的shortTime格式
Settings.updateLocale('en-US', {
  formats: {
    shortTime: 'h:mm a'
  }
});

修改后,所有调用toFormat('t')的地方都会使用你定义的格式,输出普通空格,一劳永逸适配整个项目。

2. 格式化后局部替换空格

如果不想修改全局配置,可在格式化完成后直接替换非断空格:

// 替换单个时间字符串的非断空格
start.toUTC().toFormat('t').replace(/\u00A0/g, ' ')

在你的getter方法中修改为:

return `${start.toUTC().toFormat('t').replace(/\u00A0/g, ' ')} - ${end.toUTC().toFormat('t').replace(/\u00A0/g, ' ')}${this.Options['TimezoneForReport'] != null ?
    `(${this.Options['TimezoneForReport']})` : ''}`;

这种方式更灵活,适合仅局部需要替换的场景。

3. 自定义格式别名(兼容Moment用法)

可以自定义一个和Moment一致的'LT'格式别名,配置到本地化中:

Settings.updateLocale('en-US', {
  formats: {
    LT: 'h:mm a'
  }
});

之后就可以像Moment一样使用toFormat('LT'),输出带普通空格的时间字符串,减少迁移后的代码改动。


内容的提问来源于stack exchange,提问作者IMeyers20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:53:13