Форматировать временной интервал в секундах как X час(ы) Y минут(ы) Z секунд(ы)

Можно ли отформатировать секунды в стиле обратного отсчета? Например, если у меня есть var seconds = 3662, как я могу показать: 1 hour 1 minute 2 seconds.

Я пытался использовать formatDistanceStrict(3662), но печатается только час: 1 hour.

Есть ли встроенный метод для отображения минут и секунд? Я не хочу писать 100 строк кода, чтобы это заработало (как и другие примеры из Интернета).


person Ionel Lupu    schedule 26.06.2020    source источник
comment
разве моменты не вариант?   -  person Mody    schedule 26.06.2020
comment
stackoverflow.com/questions/14157341/   -  person Orelsanpls    schedule 26.06.2020
comment
@ Моди, к сожалению, нет :(   -  person Ionel Lupu    schedule 26.06.2020


Ответы (4)


Самое простое решение, которое я смог найти, используя библиотеку date-fns, таково:

import { formatDuration, intervalToDuration } from 'date-fns';

function humanDuration(time: number) {
    return formatDuration(intervalToDuration({start: 0, end: time * 1000}));
};
humanDuration(463441); // 5 days 8 hours 44 minutes 1 second
person Ionel Lupu    schedule 26.06.2020
comment
Я использую набор пользовательского интерфейса NG-Zorro, и кажется, что он поставляется с date-fns ^ 2.10.0 - person Ionel Lupu; 26.06.2020
comment
Это просто и элегантно. Однако стоит отметить, что это число не делится на недели (т. е. если продолжительность составляет 1 неделю и 2 дня, оно преобразуется в 9 дней). - person YannP; 18.11.2020

Это то, что вы имели ввиду?

const seconds = 3662,

      formatCounter = s => {
        let _s = s        
        const units = {day: 864e2, hour: 3600, minute: 60, second: 1},
              str = Object
                .entries(units)
                .reduce((r, [unit, multiplier]) => {            
                  if(_s >= multiplier){
                    const count = _s/multiplier|0,
                          tail = count > 1 ? 's' : ''
                    r.push([count, unit+tail])              
                    _s = _s%multiplier
                  }
                  return r
                }, [])
        return str.flat().join(' ')               
      } 
      
console.log(formatCounter(seconds))
console.log(formatCounter(416920))

person Yevgen Gorbunkov    schedule 26.06.2020
comment
Да. Но я нашел массу решений, подобных этому, в Интернете. Я хотел бы решить эту проблему, используя date-fns с одним вызовом функции. Date-fns делает это наполовину, и я подумал, что что-то упускаю из их документов. Не могу поверить, что в этих больших библиотеках нет такой функциональности. - person Ionel Lupu; 26.06.2020
comment
Если это единственная цель использования date-fns в вашем проекте, я действительно не думаю, что 15 строк кода (дающие вам гибкость в настройке практически всего) - это большая головная боль по сравнению с загрузкой библиотеки 70 КБ и поддержанием ее совместимости. с остальной частью вашего окружения в будущем. - person Yevgen Gorbunkov; 26.06.2020
comment
Конечно, это не головная боль. Хотел узнать, есть ли действительно быстрый способ получить эту функциональность без большого количества строк кода. Я вижу, что есть проблема их репо по этому поводу. Кажется, нет простого способа сделать это - person Ionel Lupu; 26.06.2020
comment
@YevgenGorbunkov Отличный код. Кстати, date-fns поддерживает встряхивание дерева. - person rofrol; 20.01.2021

Вы ищете это.

Здесь я преобразовал секунды в минуты и часы

и вернул строку.

function format(time) {   
    // Hours, minutes and seconds
    var hrs = ~~(time / 3600);
    var mins = ~~((time % 3600) / 60);
    var secs = ~~time % 60;

    // Output like "1:01" or "4:03:59" or "123:03:59"
    var ret = "";
    if (hrs > 0) {
        ret += "" + hrs + " hour " + (mins < 10 ? "0" : "");
    }
    ret += "" + mins + " minutes " + (secs < 10 ? "0" : "");
    ret += "" + secs + " seconds";
    return ret;
}

console.log(format(3662));

person xMayank    schedule 26.06.2020
comment
Ожидаемый результат, очевидно, различается между множественным и единственным числом (обратите внимание на '1 минутус' и '1 часс' в вашем выводе. Кроме того, ожидаемый вывод — 1, а не 01. - person Yevgen Gorbunkov; 26.06.2020

Так просто как:

    const time = new Date(0,0,0)
    time.setSeconds(3662)
    console.log(time.getHours(), 
               time.getMinutes(), 
               time.getSeconds())

person Mody    schedule 26.06.2020
comment
Это не будет работать для секунд, превышающих 86400 (1 день), и есть небольшая разница в формате между вашим результатом и ожидаемым результатом. - person Yevgen Gorbunkov; 26.06.2020
comment
Если OP подтвердит, что ему нужно обрабатывать день +, я могу немного изменить его. Я думаю, что ОП готов поработать :) С небольшими изменениями, если он может поддерживать любое количество секунд. - person Mody; 26.06.2020
comment
У меня нет такой большой ментальной связи с ОП, чтобы сказать, что имеет место, а что нет. Однако это не меняет того факта, что приведенный выше код не дает ожидаемого результата и не масштабируется за пределы 1-дневного интервала. - person Yevgen Gorbunkov; 26.06.2020
comment
@YevgenGorbunkov Он хочет нашей помощи и не ищет кого-то, кто сделает это за него, не так ли? - person Mody; 26.06.2020
comment
Почему бы не new Date(3662 * 1000) и не сохранить немного кода? Или Date(3662 * 1000).toTimeString().split(' ')[0]. - person RobG; 26.06.2020