npm.io
2.1.0 • Published 3 weeks ago

timelong

Licence
MIT
Version
2.1.0
Deps
0
Size
23 kB
Vulns
0
Weekly
24

简体中文 | English

badge badge

简介

将1h2m3s4ms这种格式的字符串转为指定单位的时长

timelong.ms1h2m3s4ms => 3723004 (ms)
timelong.s1h2m3s4ms => 3723.004 (s)

零依赖,无运行时开销(除首次属性访问的解析),支持 TypeScript 编译期校验。

使用

import timelong from "timelong";

console.log(timelong.ms1d);

属性名第一段是单位:

单位 含义
w 星期
d 天
h 小时
m 分钟
s 秒
ms 毫秒

后面是具体的时间长度,数字后面跟的具体单位: 1d4m 表示1天4分钟。

如timelong.m1d4m会换算成具体分钟数24*60+4=1444

也可以用中文,但不能中英文混用

中文单位有:

星期、周、天、日、小时、时、分钟、分、秒、毫秒

例如:

timelong.时1天

注意事项

1. 单位必须按 w d h m s ms 的顺序书写

时长部分允许缺省部分单位,但不能颠倒顺序、也不能重复。顺序错误会返回 undefined:

timelong.ms1h30m; // ✅ 5400000
timelong.ms30m1h; // ❌ undefined(顺序错误)
timelong.ms1d2d;  // ❌ undefined(单位重复)

2. 无法解析时返回 undefined,不抛错

为符合 JS 对象语义,拼错单位的属性访问返回 undefined 而非抛错(v2 的破坏性变更)。 若需要拼错时立即报错,使用 parseStrict,或在调用点做校验:

import timelong, { parse, parseStrict } from "timelong";

// 直接访问:拼错返回 undefined(注意 undefined 参与运算会变成 NaN)
timelong.ms1xyz; // undefined

// 运行时解析动态字符串
parse("1h30m");        // 5400000
parse("abc");          // undefined
parseStrict("abc");    // 抛 TypeError

// 代理上也挂了同样的方法
timelong.parse("1h30m"); // 5400000

3. 非 ms 单位返回浮点数

换算除不尽时会引入浮点误差,比较时建议用容差或统一换算到 ms:

timelong.s1ms; // 0.001
timelong.m1ms; // 1.6666666666666667e-5

运行时解析

除属性访问外,也可以解析变量或配置中的字符串:

import { parse, parseStrict } from "timelong";

parse("1d4m");        // 86640000
parse("1天");         // 86400000
parseStrict("1d4m");  // 86640000

parse 返回毫秒数,无法解析时返回 undefined;parseStrict 在无法解析时抛出 TypeError。

背景

代码中经常会有定义时长的常量,例如:

// axios默认超时时间
export const AXIOS_TIMEOUT_DEFAULT = 5000; // ms

简单的还好,还有稍微需要计算的需要在脑袋里过一遍,例如:

export const TASK_TIMEOUT_PERIOD = 20 * 60 * 1000; // ms

时间单位有可能是分钟、秒等非毫秒数,如果代码里不写注释和毫秒数的时间放在一起,可能会让人感到疑惑,例如:

// redis 过期时间
export const REDIS_EXPIRE_TIME = 7 * 24 * 60 * 60; // s

如果有一个工具能按照一定格式自动生成想要的时长,我们就能偷点懒了,可读性也强些。

上面的例子就会变成

export const AXIOS_TIMEOUT_DEFAULT = timelong.ms5s;
export const TASK_TIMEOUT_PERIOD = timelong.ms20m;
export const REDIS_EXPIRE_TIME = timelong.s7d;

示例

expect(timelong.ms1ms).toBe(1);
expect(timelong.ms1s).toBe(1 * 1000);
expect(timelong.ms1m).toBe(1 * 60 * 1000);
expect(timelong.ms1h).toBe(1 * 60 * 60 * 1000);
expect(timelong.ms1d).toBe(1 * 24 * 60 * 60 * 1000);
expect(timelong.ms1w).toBe(1 * 7 * 24 * 60 * 60 * 1000);
expect(timelong.ms12w34d56h78m9s10ms).toBe(
    12 * timelong.ms1w +
    34 * timelong.ms1d +
    56 * timelong.ms1h +
    78 * timelong.ms1m +
    9 * timelong.ms1s +
    10
);
expect(timelong.m1ms).toBeCloseTo(1 / 1000 / 60);
expect(timelong.m1s).toBeCloseTo(1 / 60);
expect(timelong.m1m).toBe(1);
expect(timelong.m1h).toBe(1 * 60);
expect(timelong.m1d).toBe(1 * 24 * 60);
expect(timelong.m1w).toBe(1 * 7 * 24 * 60);
expect(timelong.m12w34d56h78m9s10ms).toBeCloseTo(
    12 * timelong.m1w +
    34 * timelong.m1d +
    56 * timelong.m1h +
    78 * timelong.m1m +
    9 * timelong.m1s +
    10 * timelong.m1ms
);
expect(timelong.时1日).toBe(1 * 24);
expect(timelong.小时1日).toBe(1 * 24);
expect(timelong.时1天).toBe(1 * 24);
expect(timelong.小时1天).toBe(1 * 24);

以此类推

实现原理

Proxy解析属性名为具体的单位、星期数、天数、小时数、分数、秒数和毫秒数再累加相除

Keywords