如何在 moment.js 持续时间内使用 format()?

Posted

技术标签:

【中文标题】如何在 moment.js 持续时间内使用 format()?【英文标题】:How to use format() on a moment.js duration? 【发布时间】:2012-10-27 02:09:35 【问题描述】:

有什么方法可以在持续时间对象上使用moment.jsformat 方法吗?我在文档中的任何地方都找不到它,而且它也不是持续时间对象的属性。

我希望能够做类似的事情:

var diff = moment(end).unix() - moment(start).unix();
moment.duration(diff).format('hh:mm:ss')

另外,如果有任何其他库可以轻松容纳此类功能,我会对推荐感兴趣。

谢谢!

【问题讨论】:

moment.utc(duration.asMilliseconds()).format('hh:mm:ss'); - 持续时间是一个向量。通过将其尾部放在原点上,您可以使用日期格式来获取 hh:mm:ss。 moment.utc(moment.duration(23, 'seconds').asMilliseconds()).format('hh:mm:ss') => "12:00:23" 没有工作得很好 啊,我发现了问题,HH:mm:ss 将在我之前的示例中给出00:00:23。所以只是小时部分的错误大小写 【参考方案1】:
// set up
let start = moment("2018-05-16 12:00:00"); // some random moment in time (in ms)
let end = moment("2018-05-16 12:22:00"); // some random moment after start (in ms)
let diff = end.diff(start);

// execution
let f = moment.utc(diff).format("HH:mm:ss.SSS");
alert(f);

Have a look at the JSFiddle

【讨论】:

好方法。尽管如果我也想显示日期,它也不起作用:DDD HH:mm:ss.SSS(其中DDD 是一年中的某天)在我想要0 时显示1。有什么快速解决办法吗? 不容易。我做了这个 jsfiddle.net/fhdd8/14 ,这可能是你所做的,但我不认为 moment 有任何开箱即用的东西 将 10 万亿毫秒显示为 mm:ss 没有任何意义 这在 24 小时后不起作用(即,如果我想显示 117 小时)。否则很好的解决方案! @Phil 如果您想显示天数,可以使用“D”或“DD”。【参考方案2】:

将持续时间转换为毫秒,然后转换为时刻:

moment.utc(duration.as('milliseconds')).format('HH:mm:ss')

【讨论】:

因此,如果您的持续时间超过 24 小时,这将不起作用.. 24 小时被重置为 0 小时 @S.Robijns 是一个有用的观察,但只是为了向其他人强调 - 这 .format('HH:mm:ss') 的预期行为。 See the docs【参考方案3】:

我们正在考虑在 moment.js 中为持续时间添加某种格式。见https://github.com/timrwood/moment/issues/463

http://countdownjs.org/ 和 https://github.com/icambron/twix.js 等其他几个库可能会有所帮助

【讨论】:

我也期待持续时间格式。现在看一下 countdownjs,但 twix 似乎只做“智能”格式化,没有太多自定义。 虽然 twix 努力进行智能格式化,但它有很多格式化选项,包括所涉及的标记:github.com/icambron/twix.js/wiki/Formatting。免责声明:我是 twix 的作者。 Countdown.js 非常好,作者超好用(因为我的一些建议,他当天才发布2个版本)! 我投了反对票,因为这个答案中链接的 github 问题只是一个永无止境的意见、愿望和咆哮,无处可去,4 年后问题仍然存在,没有任何用处 为什么它不能与库中其他地方使用的其他 .format 相同?这是精神错乱。 5年了还没有完成?真的吗?!【参考方案4】:

使用这个插件Moment Duration Format。

例子:

moment.duration(123, "minutes").format("h:mm");

【讨论】:

该格式无法正常工作,持续时间方面很好,但如果我指定 hh:mm:mm 并且只有 10 秒,它会显示 10 而不是 00:00:10(即使打开 forcelength)如果它不是格式化......那么它应该被称为别的东西,格式应该是标准化的。 @ppumkin 我知道这是旧的,但如果你指定 trim: false 它将停止这种行为。 这是我更喜欢使用的:假设你有持续时间,比如const duration = moment.duration(value, 'seconds');,而不是我可以使用格式化:moment.utc(duration.as('milliseconds')).format('HH:mm:ss').toString(); @EvgenyBobkin 如果您的持续时间超过一天,它将无法工作,但图书馆会处理它【参考方案5】:

使用这行代码:

moment.utc(moment.duration(4500, "seconds").asMilliseconds()).format("HH:mm:ss")

【讨论】:

如果持续时间 > of 86400''(即 24 小时),这将不起作用。 excel中也是一样,24小时翻转。如果您知道 24 小时限制,这是一个很好的解决方法。 所以当我使用 .utc 时,时间是 waaaaayyyy 关闭。为什么?【参考方案6】:
var diff = moment(end).unix() - moment(start).unix();
moment.utc(moment.duration(diff).asMilliseconds()).format("HH:mm:ss.SSS");

【讨论】:

一般来说,如果答案包括对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。 (该帖子至少被一位用户标记,大概是因为他们认为应该删除没有解释的答案。) 无法解释,这对我来说是什么。谢谢:) 不需要解释。 Moment.js 文档可以展示这个解决方案是如何实现的。 没用。像这个问题的大多数其他答案一样,返回持续时间的部分小时而不是总小时。例如。持续时间返回 12:00 moment.duration(days: 2, hours: 12) moment.duration(diff).asMilliseconds() 过多。您可以只使用 diff,它已经在毫秒内。【参考方案7】:

我的特定用例的最佳方案是:

var duration = moment.duration("09:30"),
    formatted = moment.utc(duration.asMilliseconds()).format("HH:mm");

这改进了 @Wilson 的回答,因为它不访问私有内部属性 _data。

【讨论】:

【参考方案8】:

您不需要 .format。像这样使用持续时间:

const duration = moment.duration(83, 'seconds');
console.log(duration.minutes() + ':' +duration.seconds());
// output: 1:23

我在这里找到了这个解决方案:https://github.com/moment/moment/issues/463

编辑:

还有秒、分和小时的填充:

const withPadding = (duration) => 
    if (duration.asDays() > 0) 
        return 'at least one day';
     else 
        return [
            ('0' + duration.hours()).slice(-2),
            ('0' + duration.minutes()).slice(-2),
            ('0' + duration.seconds()).slice(-2),
        ].join(':')
    


withPadding(moment.duration(83, 'seconds'))
// 00:01:23

withPadding(moment.duration(6048000, 'seconds'))
// at least one day

【讨论】:

如果 duration.seconds() 小于 10,这将不包括前导零... 如果秒数超过一小时会怎样?那么你有超过 60 秒的时间可以吗? 前导零有效,但duration = moment.duration(7200, 'seconds'); withPadding(duration); 会说“00:00”。 @shaedrich 我再次更新了我的答案以包括小时数;如果您需要几天、几周,也可以将它们添加到数组中 if (duration.asDays() > 0) return 'at least one day'; - 我读对了吗?【参考方案9】:

我用:

var duration = moment.duration("09:30");
var str = moment(duration._data).format("HH:mm");

我在 var str 中得到“09:30”。

【讨论】:

太棒了!这只是工作......你到底是怎么想出这个的:) 避免这种解决方案,_data 是一个内部属性,可能会在没有警告的情况下更改。 不幸的是,它不会总是按预期工作:moment(moment.duration(1200000)._data).format('hh:mm:ss') 将返回 12:20 而不是 00:20 @AnnaR h 在 1-12 范围内,所以这是可以预料的。使用H 而不是docs - hour tokens 这是错误的,不仅你忽略了DAYS,所以1day和1hour会显示为01:00。此外,您完全忽略了时区,这是一个更好的解决方案,但 也不是完整的 将是 moment.utc(...).format("HH:mm");【参考方案10】:

我需要这样做以作为以这种格式显示小时数的要求。 一开始我试过这个。

moment.utc(totalMilliseconds).format("HH:mm:ss")

但是,超过 24 小时的任何时间都将重置为 0。 但分钟和秒是准确的。 所以我只用那部分来表示分钟和秒。

var minutesSeconds = moment.utc(totalMilliseconds).format("mm:ss")

现在我只需要总小时数。

var hours = moment.duration(totalMilliseconds).asHours().toFixed()

为了获得我们都想要的格式,我们只需将它们粘合在一起即可。

var formatted = hours + ":" + minutesSeconds

如果totalMilliseconds894600000,这将返回249:30:00

希望对您有所帮助。在 cmets 中留下任何问题。 ;)

【讨论】:

不会'toFixed()' 将数字四舍五入吗?例如:“76.35”将变为“77”,而您想要的是“76”,然后将小时和分钟附加到它上面。我使用了 var hours = Math.floor(moment.duration(totalMilliseconds).asHours())。代码中的其他所有内容都很酷。感谢您的回答。【参考方案11】:

如果差异是一瞬间

var diff = moment(20111031) - moment(20111010);
var formated1 = moment(diff).format("hh:mm:ss");
console.log("format 1: "+formated1);

【讨论】:

面对时区等,这似乎并不可靠。你在生产中使用它吗? 这个问题没有提到时区。 每个人都生活在一个时区。时刻(0)是否总是在每个时区注册为 12:00 AM? 我只是询问您答案中的代码是否有效,因为我持怀疑态度。我用许多编程语言编写了很多与日期一起使用的代码。根据我的经验,您的代码似乎只能在某些时区工作——但我之所以这么问,是因为我可能不知道 javascript 如何表示 Unix 时代附近的日期。 第二行将创建一个从时间开始(1970)开始的时刻。这不行。【参考方案12】:

如果您愿意使用不同的 javascript 库,numeral.js 可以将秒格式化如下(示例为 1000 秒):

var string = numeral(1000).format('00:00');
// '00:16:40'

【讨论】:

绝对是要走的路。正如预期的那样。【参考方案13】:

如果必须显示所有小时数(超过 24 个)并且如果小时数之前不需要“0”,则可以使用一小行代码进行格式化:

Math.floor(duration.as('h')) + moment.utc(duration.as('ms')).format(':mm:ss')

【讨论】:

这是最好的 h:mm 答案,但我认为最好的显示只是 moment.duration(val,'seconds').humanize() 对于我的用例,用mmss 显示所有小时是最好的方法,因为它很紧凑,看起来类似于逗号分隔的值,因此有利于视觉比较。 【参考方案14】:

基于ni-ko-o-kin's answer:

meassurements = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"];
withPadding = (duration) => 
    var step = null;
    return meassurements.map((m) => duration[m]()).filter((n,i,a) => 
        var nonEmpty = Boolean(n);
        if (nonEmpty || step || i >= a.length - 2) 
            step = true;
        
        return step;
    ).map((n) => ('0' + n).slice(-2)).join(':')


duration1 = moment.duration(1, 'seconds');
duration2 = moment.duration(7200, 'seconds');
duration3 = moment.duration(604800, 'seconds');

withPadding(duration1); // 00:01
withPadding(duration2); // 02:00:00
withPadding(duration3); // 01:07:00:00:00

【讨论】:

我不认为它的可读性很强。你想在这里解决什么问题?你的用例是什么? 我再次更新了我的答案以处理超过一天。它适用于我的用例。 问题在于,在大多数情况下,您的解决方案并不理想,因为它包含太多前导零。谁想要返回“00:00:00:00:01”?我的解决方案是“可扩展的”,并根据需要添加尽可能多的前导零。 完美运行。非常简单的输出。如果没有天数,则显示天数等不会为零。【参考方案15】:

在这些情况下我使用经典的格式化功能:

var diff = moment(end).unix() - moment(start).unix();

//use unix function instead of difference
moment.unix(diff).format('hh:mm:ss')

这是一个 hack,因为时间差异被视为标准时刻日期,早期纪元日期时间,但这与我们的目标无关,您不需要任何插件

【讨论】:

【参考方案16】:

将持续时间格式化为字符串

var duration = moment.duration(86400000); //value in milliseconds
var hours = duration.hours();
var minutes = duration.minutes();
var seconds = duration.seconds();
var milliseconds = duration.milliseconds();

var date = moment().hours(hours).minutes(minutes).seconds(seconds).millisecond(milliseconds);
if (is12hr)
    return date.format("hh:mm:ss a");
else
    return date.format("HH:mm:ss");

【讨论】:

【参考方案17】:

如果您使用 Angular,请将其添加到您的过滤器中:

.filter('durationFormat', function () 
    return function (value) 
        var days = Math.floor(value/86400000);
        value = value%86400000;
        var hours = Math.floor(value/3600000);
        value = value%3600000;
        var minutes = Math.floor(value/60000);
        value = value%60000;
        var seconds = Math.floor(value/1000);
        return (days? days + ' days ': '') + (hours? hours + ' hours ': '') + (minutes? minutes + ' minutes ': '') + (seconds? seconds + ' seconds ': '')
    
)

使用示例

<div> diff | durationFormat </div>

【讨论】:

确实很好。我一直在寻找这样的“漂亮格式”。谢谢!【参考方案18】:

我的解决方案不涉及任何其他库,它适用于 diff > 24h

var momentInSeconds = moment.duration(n,'seconds')
console.log(("0" + Math.floor(momentInSeconds.asHours())).slice(-2) + ':' + ("0" + momentInSeconds.minutes()).slice(-2) + ':' + ("0" + momentInSeconds.seconds()).slice(-2))

【讨论】:

【参考方案19】:

原生 javascript 怎么样?

var formatTime = function(integer) 
    if(integer < 10) 
        return "0" + integer; 
     else 
        return integer;
    


function getDuration(ms) 
    var s1 = Math.floor(ms/1000);
    var s2 = s1%60;
    var m1 = Math.floor(s1/60);
    var m2 = m1%60;
    var h1 = Math.floor(m1/60);
    var string = formatTime(h1) +":" + formatTime(m2) + ":" + formatTime(s2);
    return string;

【讨论】:

【参考方案20】:

moment.duration(x).format() 已被弃用。 您可以使用moment.utc(4366589).format("HH:mm:ss") 来获得所需的响应。

console.log(moment.utc(4366589).format("HH:mm:ss"))
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

【讨论】:

【参考方案21】:

如何正确使用 moment.js 持续时间? | 在代码中使用 moment.duration()

首先你需要导入momentmoment-duration-format

import moment from 'moment';
import 'moment-duration-format';

然后,使用持续时间函数。让我们应用上面的例子:28800 = 8 am。

moment.duration(28800, "seconds").format("h:mm a");

?好吧,你没有上述类型错误。 ?早上 8:00 得到正确的值吗?不……,您得到的值是 8:00 a。 Moment.js 格式无法正常工作。

?解决方法是将秒转换为毫秒,并使用UTC时间。

moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a')

好的,我们现在是上午 8:00。如果你想要 8 am 而不是 8:00 am 作为整数时间,我们需要做 RegExp

const time = moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a');
time.replace(/:00/g, '')

【讨论】:

【参考方案22】:

短版(单行):

moment.duration(durationInMs).asHours()|0||"00" + ":" + moment.utc(durationInMs).format("mm:ss")

加长版:

export const formatDuration = (durationInMs) => 
    const hours = Math.floor(moment.duration(durationInMs).asHours()) || "00"
    return hours + ":" + moment.utc(durationInMs).format("mm:ss")

例子:

【讨论】:

【参考方案23】:

使用moment-duration-format。

客户端框架(例如:React)

import moment from 'moment';
import momentDurationFormatSetup from 'moment-duration-format';
momentDurationFormatSetup(moment);

const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');

服务器(node.js)

const moment = require("moment-timezone");
const momentDurationFormatSetup = require("moment-duration-format");

momentDurationFormatSetup(moment);

const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');

【讨论】:

【参考方案24】:

不再需要(如果有的话)将持续时间转换为 UTC 来解决此问题。这就像将 base10 的“1”转换为二进制,然后说由于输出“1”看起来像 base10,我们假设这是一个 base10 值,可以进行任何进一步的操作。

使用moment-duration-format 并注意使用 trim: false 可以防止修剪:

moment.duration(1000000, "seconds").format("hh:mm:ss",  trim: false )
> "277:46:40"
moment.duration(0, "seconds").format("hh:mm:ss",  trim: false )
> "00:00:00"

我们把这个和不推荐的using滥用utc的方法对比一下:

moment.utc(moment.duration(1000000, "seconds").asMilliseconds()).format('HH:mm:ss')
> "13:46:40"

【讨论】:

【参考方案25】:
const duration = moment.duration(62, 'hours');
const n = 24 * 60 * 60 * 1000;
const days = Math.floor(duration / n);
const str = moment.utc(duration % n).format('H [h] mm [min] ss [s]');
console.log(`$days > 0 ? `$days $days == 1 ? 'day' : 'days' ` : ''$str`);

打印:

2 天 14 小时 00 分 00 秒

【讨论】:

【参考方案26】:
import * as moment from 'moment'
var sleep = require('sleep-promise');

(async function () 
    var t1 = new Date().getTime();
    await sleep(1000); 
    var t2 = new Date().getTime();
    var dur = moment.duration(t2-t1); 
    console.log(`$dur.hours()h:$dur.minutes()m:$dur.seconds()s`);
)();

0h:0m:1s

【讨论】:

【参考方案27】:

您可以使用numeral.js 来格式化您的时长:

numeral(your_duration.asSeconds()).format('00:00:00') // result: hh:mm:ss

【讨论】:

【参考方案28】:

这可用于将前两个字符作为小时,将后两个字符作为分钟。同样的逻辑也可以应用于秒。

/**
     * PT1H30M -> 0130
     * @param ISO String isoString
     * @return string absolute 4 digit number HH:mm
     */

    const parseIsoToAbsolute = (isoString) => 
    
      const durations = moment.duration(isoString).as('seconds');
      const momentInSeconds = moment.duration(durations, 'seconds');
    
      let hours = momentInSeconds.asHours().toString().length < 2
        ? momentInSeconds.asHours().toString().padStart(2, '0') : momentInSeconds.asHours().toString();
        
      if (!Number.isInteger(Number(hours))) hours = '0'+ Math.floor(hours);
    
      const minutes = momentInSeconds.minutes().toString().length < 2
        ? momentInSeconds.minutes().toString().padEnd(2, '0') : momentInSeconds.minutes().toString();
    
      const absolute = hours + minutes;
      return absolute;
    ;
    
    console.log(parseIsoToAbsolute('PT1H30M'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

【讨论】:

如果您将代码作为 sn-p 插入,您将能够测试该方法并向控制台显示一些输出。 没问题!刚刚更新了 sn-p 以进行快速测试。【参考方案29】:

只有 moment.js 没有任何其他插件

moment().startOf('day').seconds(duration).format('HH:mm:ss')

【讨论】:

【参考方案30】:

如果您使用 Angular >2,我制作了一个受 @hai-alaluf 答案启发的管道。

import Pipe, PipeTransform from "@angular/core";

@Pipe(
  name: "duration",
)

export class DurationPipe implements PipeTransform 

  public transform(value: any, args?: any): any 

    // secs to ms
    value = value * 1000;
    const days = Math.floor(value / 86400000);
    value = value % 86400000;
    const hours = Math.floor(value / 3600000);
    value = value % 3600000;
    const minutes = Math.floor(value / 60000);
    value = value % 60000;
    const seconds = Math.floor(value / 1000);
    return (days ? days + " days " : "") +
      (hours ? hours + " hours " : "") +
      (minutes ? minutes + " minutes " : "") +
      (seconds ? seconds + " seconds " : "") +
      (!days && !hours && !minutes && !seconds ? 0 : "");
  

【讨论】:

以上是关于如何在 moment.js 持续时间内使用 format()?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Vue 模板内的 Moment.js 格式化程序上转义 HTML 字符串?

如何使用 Moment JS 计算范围之间的给定工作日数?

使用 Rollup for Angular 2 的 AoT 编译器并导入 Moment.js

Moment.js - 显示选定范围内关于用户时区的历史数据

在 Moment Js 中获取两个日期之间的小时差

如何使用 Moment.js 返回当前时间戳?