使用JavaScript将秒数转换为ISO 8601持续时间

时间:2019-08-31 11:03:07

标签: javascript duration seconds

ISO 8601 durations很难计算。

我想尽可能有效地从几秒钟持续到几秒钟。我正在使用JavaScript。

我将在下面发布我的答案和笑话测试。

1 个答案:

答案 0 :(得分:0)

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${i}D`);
      }
    });

    it('should handle hours', () => {
      let i = 10;

      while (--i) {
        expect(secondsToDuration(SECONDS_PER_HOUR * i)).toEqual(`P${i}H`);
      }
    });

    it('should handle minutes', () => {
      let i = 10;

      while (--i) {
        expect(secondsToDuration(SECONDS_PER_MINUTE * i)).toEqual(`P${i}M`);
      }
    });

    it('should handle seconds', () => {
      let i = 10;

      while (--i) {
        expect(secondsToDuration(SECONDS_PER_SECOND * i)).toEqual(`P${i}S`);
      }
    });

    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${days}D${hours}H${minutes}M${seconds}S`.replace(/(?<=\D)0\w/g, '');
  const result = secondsToDuration(totalSeconds);

  if (result != expected) {
    console.info({ totalSeconds, expected, result });
  }

  expect(result).toEqual(expected);
}