使用Javascript将毫秒转换为分钟和秒钟

119

Soundcloud的API以毫秒为单位给出其音轨的持续时间。JSON看起来像这样:

"duration": 298999

我已经尝试了这里找到的许多函数,但都没有用。我只是在寻找一些能将那个数字转换为类似于这样的东西的方法:

4:59

这个方法接近正确,但是并不可行。它不能在秒钟到达60时停止计时。而是继续到99,这没有意义。例如,尝试将“187810”输入为毫秒值。

var ms = 298999,
min = Math.floor((ms/1000/60) << 0),
sec = Math.floor((ms/1000) % 60);

console.log(min + ':' + sec);

感谢您的帮助!

如果您也可以支持小时数,我将不胜感激。


你是什么意思,"它一直到99"? 你的脚本对我来说有效,正确输出 4:58。 请提供导致意外输出的输入。 - Bergi
这对我来说产生了“3:7”(可能应该是“3:07”)。你在哪里看到99? - Bergi
我不知道,我复制了这段代码,Bergi。 - ElliotD
从哪里来的?引用一下来源会很好 :-) - Bergi
2
这里加入了Math.floor,因为我复制了它。https://dev59.com/sW035IYBdhLWcg3wKsqa - ElliotD
显示剩余3条评论
15个回答

259
function millisToMinutesAndSeconds(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}

millisToMinutesAndSeconds(298999); // "4:59"
millisToMinutesAndSeconds(60999);  // "1:01"

正如用户HelpingHand在评论中指出的那样,返回语句应该是:

return (
  seconds == 60 ?
  (minutes+1) + ":00" :
  minutes + ":" + (seconds < 10 ? "0" : "") + seconds
);

9
请注意,此解决方案在接近下一分钟转换时有时会导致“第二位”出现60秒的情况(例如 1:60)。我通过在最后一行添加一个内联if语句来防止这种情况发生:return (seconds == 60 ? (minutes+1) + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds); 您可以在这里看到它的效果。 - HelpingHand
1
这是HelpingHand提出的一个好观点 - 您可以通过运行millisToMinutesAndSeconds(299900)来重现此问题。 - SubJunk
9
“@maerics 应该将 ((millis % 60000) / 1000).toFixed(0) 改为 Math.floor((millis % 60000) / 1000),这样 seconds 就是一个数字而不是一个字符串,可以与另一个数字进行比较。” - Courtney Pattison
返回应该是 return minutes + ":" + seconds.ToString("00"),其中秒应为 Math.Round(millis % 60000 / 1000, 0, MidpointRounding.ToEven); - Circus Ranger
请不要这样做。使用本地JS日期/时间函数。无论您使用哪种编程语言,如果您发现自己需要手动进行时间转换/操作,请立即停止。几乎总是已经有解决方案了。请查看我的答案。 - Madbreaks
显示剩余2条评论

29

我不太确定为什么这些答案都这么复杂。 Date类提供了您所需的内容:

const date = new Date(298999);

alert(`${date.getMinutes()}:${date.getSeconds()}`);

虽然上述内容满足了OP的要求,但由于@ianstarz评论提到时区独立性,因此在此添加更新版本:

const d = new Date(Date.UTC(0,0,0,0,0,0,298999)),
  // Pull out parts of interest
  parts = [
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
  ],
  // Zero-pad
  formatted = parts.map(s => String(s).padStart(2,'0')).join(':');

document.write(formatted);


看起来 OP 确实只需要秒和分钟。然而,这个解决方案对于小时和天不起作用。date.getHours() // => 16(在我的时区) - ianstarz
1
@ianstarz 更新了我的解决方案,使其更具普适性。 - Madbreaks
应该放在列表的较高位置,但如果秒数小于10,则输出类似于“4:5”的内容。 - Tunn
1
@Tunn 更新了一个更完整的示例。 - Madbreaks
1
@Madbreaks,你可能也想在第一个例子中这样做,否则它的简单性会误导人。 - Tunn
1
这应该是被接受的答案,因为它比其他解决方案更简单、更少出错,并且使用了语言内置的资源。 - Eduardo Matsuoka

22

使用小时数,0填充分钟和秒数:

var ms = 298999;
var d = new Date(1000*Math.round(ms/1000)); // round to nearest second
function pad(i) { return ('0'+i).slice(-2); }
var str = d.getUTCHours() + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds());
console.log(str); // 0:04:59


在某些情况下,删除第二行(四舍五入到最近的秒)可能更好。例如,如果我们想知道剩余的完整秒数,这将返回“4:58”。 - b00t
假设您超过60分钟,您想要添加 getUTCHours 吗? - Thomas
@Madbreaks 如果你认为 pad 是在重复造轮子,那么请注意这个答案是来自2014年的,而你使用的 padStart 是 EMCAScript 2017 的一部分。 - Matt
@Matt 不好意思,我刚才删除了我的上一条评论。但是我建议尽可能使用本地JS类/函数。 - Madbreaks

6
如果您正在寻找时分秒格式的解决方案,这是我的贡献:

h:mm:ss

不要像我一样使用其他格式。
function msConversion(millis) {
  let sec = Math.floor(millis / 1000);
  let hrs = Math.floor(sec / 3600);
  sec -= hrs * 3600;
  let min = Math.floor(sec / 60);
  sec -= min * 60;

  sec = '' + sec;
  sec = ('00' + sec).substring(sec.length);

  if (hrs > 0) {
    min = '' + min;
    min = ('00' + min).substring(min.length);
    return hrs + ":" + min + ":" + sec;
  }
  else {
    return min + ":" + sec;
  }
}

3

即使moment.js没有提供这样的功能,如果您正在使用moment.js并且来到这里,请尝试以下方法:

function formatDuration(ms) {
  var duration = moment.duration(ms);
  return Math.floor(duration.asHours()) + moment.utc(duration.asMilliseconds()).format(":mm:ss");
}

你将会得到类似于 x:xx:xx 的东西。
当持续时间小于60分钟时,您可能希望跳过小时。
function formatDuration(ms) {
  var duration = moment.duration(ms);
  if (duration.asHours() > 1) {
    return Math.floor(duration.asHours()) + moment.utc(duration.asMilliseconds()).format(":mm:ss");
  } else {
    return moment.utc(duration.asMilliseconds()).format("mm:ss");
  }
}

这个moment中的解决方法在问题中被引入。


3
也许有更好的方法来解决这个问题,但这种方法能够完成任务:
var ms = 298999;
var min = ms / 1000 / 60;
var r = min % 1;
var sec = Math.floor(r * 60);
if (sec < 10) {
    sec = '0'+sec;
}
min = Math.floor(min);
console.log(min+':'+sec);

不确定为什么在分钟行中使用了 << 运算符,我认为它是不需要的,只需在显示之前对分钟进行取整。

使用 % 获取剩余分钟可以得到该分钟内已经过去的秒数的百分比,因此将其乘以 60 可以得到秒数,并将其取整使其更适合显示,尽管您也可以获取亚秒精度。

如果秒数小于 10,则需要在前面加上零。


3

最好的就是这个!

function msToTime(duration) {
var milliseconds = parseInt((duration%1000))
    , seconds = parseInt((duration/1000)%60)
    , minutes = parseInt((duration/(1000*60))%60)
    , hours = parseInt((duration/(1000*60*60))%24);

hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;

return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
}

它将返回 00:04:21.223。您可以根据需要格式化此字符串。

1
不需要重新发明轮子。看看Date类及其提供的方法。始终使用本地解决方案是最好的选择。 - Madbreaks
@Madbreaks 我不确定你如何处理日期的纯格式,因为你必须处理时区。你能提供一个你所说的例子吗? - ianstarz
1
@ianstarz,我添加了一个答案。 - Madbreaks
这个解决方案太糟糕了。为什么要将毫秒除以1000来得到秒数? - undefined

0

如果您不需要关注小时数,momentjs和dayjs有一种巧妙的方法可以实现。

dayjs(ms).format("mm:ss")

或者

moment(ms).format("mm:ss")

传递给MomentJS和DayJS的毫秒级时间戳将被解释为自Unix纪元以来的毫秒数,因此任何不受时区影响的时间段(即任何小于一小时的毫秒数)都将被正确解释。

0
function msToHMS( ms ) {
  // 1- Convert to seconds:
  var seconds = ms / 1000;

  // 2- Extract hours:
  var hours = parseInt( seconds / 3600 ); // 3,600 seconds in 1 hour
  seconds = seconds % 3600; // seconds remaining after extracting hours

  // 3- Extract minutes:
  var minutes = parseInt( seconds / 60 ); // 60 seconds in 1 minute

  // 4- Keep only seconds not extracted to minutes:
  seconds = seconds % 60;

  //alert( hours+":"+minutes+":"+seconds);
  hours = (hours < 10) ? "0" + hours : hours;
  minutes = (minutes < 10) ? "0" + minutes : minutes;
  seconds = (seconds < 10) ? "0" + seconds : seconds;
  var hms = hours+":"+minutes+":"+seconds;
  return hms;
}

0
// ✅ You can use a Quick one-liner hack
 const ms = 54000000;
console.log(new `enter code here`Date(ms).toISOString().slice(11, 19)); // ️ 15:00:00

// ------------------------------------------------

// ✅ Or create a reusable function
function padTo2Digits(num) {
  return num.toString().padStart(2, '0');
}

function convertMsToTime(milliseconds) {
  let seconds = Math.floor(milliseconds / 1000);
  let minutes = Math.floor(seconds / 60);
  let hours = Math.floor(minutes / 60);

  seconds = seconds % 60;
  minutes = minutes % 60;

  // ️ If you don't want to roll hours over, e.g. 24 to 00
  // ️ comment (or remove) the line below
  // commenting next line gets you `24:00:00` instead of `00:00:00`
  // or `36:15:31` instead of `12:15:31`, etc.
  hours = hours % 24;

  return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}:${padTo2Digits(
    seconds,
  )}`;
}

console.log(convertMsToTime(54000000)); // ️ 15:00:00 (15 hours)
console.log(convertMsToTime(86400000)); // ️ 00:00:00 (24 hours)
console.log(convertMsToTime(36900000)); // ️ 10:15:00 (10 hours, 15 minutes)
console.log(convertMsToTime(15305000)); // ️ 04:15:05 (4 hours, 15 minutes, 5 seconds)

1
根据目前的写法,你的回答不够清晰。请编辑以添加更多细节,帮助其他人理解这如何回答所提出的问题。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接