使用 JavaScript 将秒转换为 ISO 8601 持续时间
Posted
技术标签:
【中文标题】使用 JavaScript 将秒转换为 ISO 8601 持续时间【英文标题】:Convert seconds to ISO 8601 duration with JavaScript 【发布时间】:2019-08-31 11:03:07 【问题描述】:ISO 8601 durations 计算起来很麻烦。
我想尽可能高效地从秒到持续时间。我正在使用 javascript。
我将在下面发布我的答案和 Jest 测试。
【问题讨论】:
【参考方案1】:seconds-to-duration.js
export const SECONDS_PER_SECOND = 1;
export const SECONDS_PER_MINUTE = 60;
export const SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
export const SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;
const designations = [
['D', SECONDS_PER_DAY],
['H', SECONDS_PER_HOUR],
['M', SECONDS_PER_MINUTE],
['S', SECONDS_PER_SECOND],
];
export default function secondsToDuration(seconds)
let duration = 'P';
let remainder = seconds;
designations.forEach(([sign, seconds]) =>
const value = Math.floor(remainder / seconds);
remainder = remainder % seconds;
if (value)
duration += `$value$sign`;
);
if (duration == 'P')
duration = 'P0S';
return duration;
seconds-to-duration.spec.js
import secondsToDuration,
SECONDS_PER_SECOND,
SECONDS_PER_MINUTE,
SECONDS_PER_HOUR,
SECONDS_PER_DAY,
from './seconds-to-duration';
describe('secondsToDuration', () =>
describe('even units', () =>
it('should handle days', () =>
let i = 10;
while (--i)
expect(secondsToDuration(SECONDS_PER_DAY * i)).toEqual(`P$iD`);
);
it('should handle hours', () =>
let i = 10;
while (--i)
expect(secondsToDuration(SECONDS_PER_HOUR * i)).toEqual(`P$iH`);
);
it('should handle minutes', () =>
let i = 10;
while (--i)
expect(secondsToDuration(SECONDS_PER_MINUTE * i)).toEqual(`P$iM`);
);
it('should handle seconds', () =>
let i = 10;
while (--i)
expect(secondsToDuration(SECONDS_PER_SECOND * i)).toEqual(`P$iS`);
);
it('should handle zero seconds', () =>
expect(secondsToDuration(0)).toEqual('P0S');
);
);
describe('uneven', () =>
it('should break across periods', () =>
let days = 2;
while (days--)
let hours = 24;
while (hours--)
let minutes = 60;
while (minutes--)
testDuration( days, hours, minutes, seconds: 59 );
testDuration( days, hours, minutes, seconds: 1 );
);
);
);
function testDuration( days, hours, minutes, seconds )
const totalSeconds =
days * SECONDS_PER_DAY +
hours * SECONDS_PER_HOUR +
minutes * SECONDS_PER_MINUTE +
seconds * SECONDS_PER_SECOND;
const expected = `P$daysD$hoursH$minutesM$secondsS`.replace(/(?<=\D)0\w/g, '');
const result = secondsToDuration(totalSeconds);
if (result != expected)
console.info( totalSeconds, expected, result );
expect(result).toEqual(expected);
【讨论】:
上面的脚本有一个bug。secondsToDuration(60)
返回 'P1M'
codesandbox.io/s/…(看控制台)那将是 1 个月——不是一分钟:'为了解决歧义,“P1M”是一个月的持续时间,“PT1M”是一分钟持续时间(注意时间指示符 T,它位于时间值之前)。 en.wikipedia.org/wiki/ISO_8601#Durations使用这个NPM包tinyduration
,确认这个错误:codesandbox.io/s/tinyduration-js-test-wz3te?file=/src/index.js【参考方案2】:
该脚本有一个错误(请参阅我的评论),我建议改用这个包:https://www.npmjs.com/package/tinyduration
【讨论】:
以上是关于使用 JavaScript 将秒转换为 ISO 8601 持续时间的主要内容,如果未能解决你的问题,请参考以下文章