如何使用JavaScript将秒转换为HH-MM-SS字符串?
当前回答
试试这个:
function toTimeString(seconds) {
return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
}
其他回答
我认为最普遍(也是最神秘)的解决方案可能是这样的
function hms(seconds) {
return [3600, 60]
.reduceRight(
(pipeline, breakpoint) => remainder =>
[Math.floor(remainder / breakpoint)].concat(pipeline(remainder % breakpoint)),
r => [r]
)(seconds)
.map(amount => amount.toString().padStart(2, '0'))
.join('-');
}
或者复制粘贴最短的版本
function hms(seconds) {
return [3600, 60]
.reduceRight(
(p, b) => r => [Math.floor(r / b)].concat(p(r % b)),
r => [r]
)(seconds)
.map(a => a.toString().padStart(2, '0'))
.join('-');
}
一些示例输出:
> hms(0)
< "00-00-00"
> hms(5)
< "00-00-05"
> hms(60)
< "00-01-00"
> hms(3785)
< "01-03-05"
> hms(37850)
< "10-30-50"
> hms(378500)
< "105-08-20"
它是如何工作的
算法
要得到小时数,你需要用总秒数除以3600,然后取底。 要得到分钟数,你需要用余数除以60,然后取底。 要得到秒数,你只需用余数。
将单个金额保存在一个数组中也很好,以便于格式化。
例如,给定3785s的输入,输出应该是[1,3,5],即1小时3分5秒。
创建管道
将3600和60个常量命名为“断点”,您可以将此算法写成如下函数
function divideAndAppend(remainder, breakpoint, callback) {
return [Math.floor(remainder / breakpoint)].concat(callback(remainder % breakpoint));
}
它返回一个数组,其中第一项是给定断点的数量,数组的其余部分由回调函数给出。 重用回调函数中的divideAndAppend将为您提供一个组合的divideAndAppend函数的管道。每一个 计算每个给定断点的数量,并将其附加到生成所需输出的数组中。
然后,您还需要“final”回调来结束这个管道。换句话说,您使用了所有的断点,现在只剩下其余的。 既然你已经在3)处得到了答案,你应该使用某种恒等函数,在这种情况下,remainder =>[余数]。
现在可以像这样编写管道
let pipeline = r3 => divideAndAppend(
r3,
3600,
r2 => divideAndAppend(
r2,
60,
r1 => [r1]));
> pipeline(3785)
< [1, 3, 5]
酷吧?
使用for-loop泛化
现在,您可以使用可变数量的断点进行泛化,并创建一个for循环,将单独的divideAndAppend函数组合到其中 管道。 您从恒等函数r1 => [r1]开始,然后使用60断点,最后使用3600断点。
let breakpoints = [60, 3600];
let pipeline = r => [r];
for (const b of breakpoints) {
const previousPipeline = pipeline;
pipeline = r => divideAndAppend(r, b, previousPipeline);
}
> pipeline(3785)
< [1, 3, 5]
使用Array.prototype.reduce ()
现在您可以将for循环重写为reducer,以获得更短、更实用的代码。换句话说,重写函数组合成减速器。
let pipeline = [60, 3600].reduce(
(ppln, b) => r => divideAndAppend(r, b, ppln),
r => [r]
);
> pipeline(3785)
< [1, 3, 5]
累加器ppln是管道,您正在使用它的以前版本来组合它。初始管道为r => [r]。
你现在可以内联函数divideAndAppend,并使用Array.prototype.reduceRight(与[].reverse().reduce(…)相同)来设置断点 定义更自然。
let pipeline = [3600, 60]
.reduceRight(
(ppln, b) => r => [Math.floor(r / b)].concat(ppln(r % b)),
r => [r]
);
这是最终形式。然后你只需appy映射到字符串与填充0的左边和连接字符串:分隔符;
更多的推广
将减速器包装成功能
function decompose(total, breakpoints) {
return breakpoints.reduceRight(
(p, b) => r => [Math.floor(r / b)].concat(p(r % b)),
r => [r]
)(total);
}
> decompose(3785, [3600, 60])
< [1, 3, 5]
你现在有了一个非常通用的算法。例如:
容易转换(奇怪的)我们的长度标准
考虑到标准
Unit | Divisions |
---|---|
1 foot | 12 inches |
1 yard | 3 feet |
1 mile | 1760 yards |
> decompose(123_456, [1760 * 3 * 12, 3 * 12, 12])
< [1, 1669, 1, 0]
123456英寸= 1英里,1669码,1英尺和0英寸
或者你可以转换成十进制或二进制表示
> decompose(123_456, [100_000, 10_000, 1000, 100, 10])
< [1, 2, 3, 4, 5, 6]
> decompose(127, [128, 64, 32, 16, 8, 4, 2])
< [0, 1, 1, 1, 1, 1, 1, 1]
也适用于浮点断点
由于Javascript支持mod运算符带浮点数,你也可以这样做
> decompose(26.5, [20, 2.5])
< [1, 2, 1.5]
没有断点的边缘情况自然也被涵盖了
> decompose(123, [])
< [123]
对于HH:MM:SS的特殊情况。MS (eq: "00:04:33.637"), FFMPEG用来指定毫秒。
[-] [HH: MM: SS(打烊……) HH表示小时数,MM表示分钟数 最大值为2位,SS为最大值为2的秒数 位数。最后的m表示SS的十进制值。
/* HH:MM:SS.MS to (FLOAT)seconds ---------------*/ function timerToSec(timer){ let vtimer = timer.split(":") let vhours = +vtimer[0] let vminutes = +vtimer[1] let vseconds = parseFloat(vtimer[2]) return vhours * 3600 + vminutes * 60 + vseconds } /* Seconds to (STRING)HH:MM:SS.MS --------------*/ function secToTimer(sec){ let o = new Date(0) let p = new Date(sec*1000) return new Date(p.getTime()-o.getTime()) .toISOString() .split("T")[1] .split("Z")[0] } /* Example: 7hours, 4 minutes, 33 seconds and 637 milliseconds */ const t = "07:04:33.637" console.log( t + " => " + timerToSec(t) + "s" ) /* Test: 25473 seconds and 637 milliseconds */ const s = 25473.637 // "25473.637" console.log( s + "s => " + secToTimer(s) )
示例使用,毫秒传输计时器:
/* Seconds to (STRING)HH:MM:SS.MS --------------*/ function secToTimer(sec){ let o = new Date(0) let p = new Date(sec*1000) return new Date(p.getTime()-o.getTime()) .toISOString() .split("T")[1] .split("Z")[0] } let job, origin = new Date().getTime() const timer = () => { job = requestAnimationFrame(timer) OUT.textContent = secToTimer((new Date().getTime() - origin) / 1000) } requestAnimationFrame(timer) span {font-size:4rem} <span id="OUT"></span> <br> <button onclick="origin = new Date().getTime()">RESET</button> <button onclick="requestAnimationFrame(timer)">RESTART</button> <button onclick="cancelAnimationFrame(job)">STOP</button>
绑定到媒体元素的示例用法
/* Seconds to (STRING)HH:MM:SS.MS --------------*/ function secToTimer(sec){ let o = new Date(0) let p = new Date(sec*1000) return new Date(p.getTime()-o.getTime()) .toISOString() .split("T")[1] .split("Z")[0] } VIDEO.addEventListener("timeupdate", function(e){ OUT.textContent = secToTimer(e.target.currentTime) }, false) span {font-size:4rem} <span id="OUT"></span><br> <video id="VIDEO" width="400" controls autoplay> <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"> </video>
在问题之外,那些用php编写的函数:
<?php
/* HH:MM:SS to (FLOAT)seconds ------------------*/
function timerToSec($timer){
$vtimer = explode(":",$timer);
$vhours = (int)$vtimer[0];
$vminutes = (int)$vtimer[1];
$vseconds = (float)$vtimer[2];
return $vhours * 3600 + $vminutes * 60 + $vseconds;
}
/* Seconds to (STRING)HH:MM:SS -----------------*/
function secToTimer($sec){
return explode(" ", date("H:i:s", $sec))[0];
}
当我想象一个时钟或计时器时,我会这样做:
const secondsTo_HHMMSS = (seconds) => {
//format to a readable friendly timer
let hour = Math.floor(seconds / 3600);
let minute = Math.floor((seconds % 3600) / 60);
let second = seconds % 60;
if(hour.toString().length === 1) {
hour = `0${hour}`;
}
if(minute.toString().length === 1) {
minute = `0${minute}`;
}
if(second.toString().length === 1) {
second = `0${second}`;
};
let timer = `${hour}-${minute}-${second}`;
return timer;
}
export const secondsToHHMMSS = (seconds) => {
const HH = `${Math.floor(seconds / 3600)}`.padStart(2, '0');
const MM = `${Math.floor(seconds / 60) % 60}`.padStart(2, '0');
const SS = `${Math.floor(seconds % 60)}`.padStart(2, '0');
return [HH, MM, SS].join(':');
};
试试这个:
function toTimeString(seconds) {
return (new Date(seconds * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
}
推荐文章
- Node.js和CPU密集型请求
- val()和text()的区别
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- 添加javascript选项选择
- 在Node.js中克隆对象
- 如何计算两个时间串之间的时间间隔
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?