How to convert milliseconds into human readable form?

我需要将任意数量的毫秒转换为天,小时,分钟秒。

例如: 10天,5小时,13分钟,1秒。

160675 次浏览

我建议使用您的语言/框架所提供的日期/时间函数/库。还要检查字符串格式化函数,因为它们通常提供传递日期/时间戳和输出可读字符串格式的简单方法。

设 A 是毫秒的数量,然后得到:

seconds=(A/1000)%60
minutes=(A/(1000*60))%60
hours=(A/(1000*60*60))%24

等等(%是模运算符)。

希望这个能帮上忙。

好吧,既然没有其他人站出来,我将编写简单的代码来完成这项工作:

x = ms / 1000
seconds = x % 60
x /= 60
minutes = x % 60
x /= 60
hours = x % 24
x /= 24
days = x

我只是很高兴你停下来几天而不是几个月。 :)

注意,在上面的例子中,假设 /表示截断整数除法。如果在 /表示浮点除法的语言中使用此代码,则需要根据需要手动截断除法的结果。

你的选择很简单:

  1. 编写代码进行转换(例如,除以 milsecond/PerDay 得到天数,使用模数除以 milsecond/PerHour 得到小时,使用模数除以 milsecond/PerMinute 得到小时,使用模数除以1000除以秒。毫秒/每分钟 = 60000,毫秒/每小时 = 60 * 毫秒/每分钟,毫秒/每天 = 24 * 毫秒/每小时。
  2. 使用某种操作程序。UNIX 和 Windows 都有可以从 Ticks 或秒类型值获得的结构。

您应该使用所使用的任何语言的 datetime 函数,但是,只是为了好玩,下面是代码:

int milliseconds = someNumber;


int seconds = milliseconds / 1000;


int minutes = seconds / 60;


seconds %= 60;


int hours = minutes / 60;


minutes %= 60;


int days = hours / 24;


hours %= 24;
Long serverUptimeSeconds =
(System.currentTimeMillis() - SINCE_TIME_IN_MILLISECONDS) / 1000;




String serverUptimeText =
String.format("%d days %d hours %d minutes %d seconds",
serverUptimeSeconds / 86400,
( serverUptimeSeconds % 86400) / 3600 ,
((serverUptimeSeconds % 86400) % 3600 ) / 60,
((serverUptimeSeconds % 86400) % 3600 ) % 60
);

Apache Commons Lang has a 持续时间格式工具 that has very helpful methods like formatDurationWords.

这是我写的一个方法,它接受一个 integer milliseconds value并返回一个 human-readable String:

public String convertMS(int ms) {
int seconds = (int) ((ms / 1000) % 60);
int minutes = (int) (((ms / 1000) / 60) % 60);
int hours = (int) ((((ms / 1000) / 60) / 60) % 24);


String sec, min, hrs;
if(seconds<10)  sec="0"+seconds;
else            sec= ""+seconds;
if(minutes<10)  min="0"+minutes;
else            min= ""+minutes;
if(hours<10)    hrs="0"+hours;
else            hrs= ""+hours;


if(hours == 0)  return min+":"+sec;
else    return hrs+":"+min+":"+sec;


}

下面的两个解决方案都使用 Javascript(我不知道这个解决方案是语言不可知的!).如果捕获持续时间 > 1 month,这两种解决方案都需要扩展。

解决方案1: 使用 Date 对象

var date = new Date(536643021);
var str = '';
str += date.getUTCDate()-1 + " days, ";
str += date.getUTCHours() + " hours, ";
str += date.getUTCMinutes() + " minutes, ";
str += date.getUTCSeconds() + " seconds, ";
str += date.getUTCMilliseconds() + " millis";
console.log(str);

Gives:

"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"

图书馆是有用的,但如果你可以重新发明轮子,为什么还要使用图书馆呢! :)

解决方案2: 编写自己的解析器

var getDuration = function(millis){
var dur = {};
var units = [
{label:"millis",    mod:1000},
{label:"seconds",   mod:60},
{label:"minutes",   mod:60},
{label:"hours",     mod:24},
{label:"days",      mod:31}
];
// calculate the individual unit values...
units.forEach(function(u){
millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod;
});
// convert object to a string representation...
var nonZero = function(u){ return dur[u.label]; };
dur.toString = function(){
return units
.reverse()
.filter(nonZero)
.map(function(u){
return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label);
})
.join(', ');
};
return dur;
};

创建一个带有所需字段的持续时间对象。 然后格式化时间戳就变得简单了..。

console.log(getDuration(536643021).toString());

给予:

"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"

这里有一个更精确的 JAVA 方法,我已经实现了这个简单的逻辑,希望对你有所帮助:

    public String getDuration(String _currentTimemilliSecond)
{
long _currentTimeMiles = 1;
int x = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;
int month = 0;
int year = 0;


try
{
_currentTimeMiles = Long.parseLong(_currentTimemilliSecond);
/**  x in seconds **/
x = (int) (_currentTimeMiles / 1000) ;
seconds = x ;


if(seconds >59)
{
minutes = seconds/60 ;


if(minutes > 59)
{
hours = minutes/60;


if(hours > 23)
{
days = hours/24 ;


if(days > 30)
{
month = days/30;


if(month > 11)
{
year = month/12;


Log.d("Year", year);
Log.d("Month", month%12);
Log.d("Days", days % 30);
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds  ", seconds % 60);


return "Year "+year + " Month "+month%12 +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}
else
{
Log.d("Month", month);
Log.d("Days", days % 30);
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds  ", seconds % 60);


return "Month "+month +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}


}
else
{
Log.d("Days", days );
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds  ", seconds % 60);


return "Days " +days +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}


}
else
{
Log.d("hours ", hours);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds  ", seconds % 60);


return "hours "+hours+" Minutes "+minutes %60+" Seconds "+seconds%60;
}
}
else
{
Log.d("Minutes ", minutes);
Log.d("Seconds  ", seconds % 60);


return "Minutes "+minutes +" Seconds "+seconds%60;
}
}
else
{
Log.d("Seconds ", x);
return " Seconds "+seconds;
}
}
catch (Exception e)
{
Log.e(getClass().getName().toString(), e.toString());
}
return "";
}


private Class Log
{
public static void d(String tag , int value)
{
System.out.println("##### [ Debug ]  ## "+tag +" :: "+value);
}
}
function convertTime(time) {
var millis= time % 1000;
time = parseInt(time/1000);
var seconds = time % 60;
time = parseInt(time/60);
var minutes = time % 60;
time = parseInt(time/60);
var hours = time % 24;
var out = "";
if(hours && hours > 0) out += hours + " " + ((hours == 1)?"hr":"hrs") + " ";
if(minutes && minutes > 0) out += minutes + " " + ((minutes == 1)?"min":"mins") + " ";
if(seconds && seconds > 0) out += seconds + " " + ((seconds == 1)?"sec":"secs") + " ";
if(millis&& millis> 0) out += millis+ " " + ((millis== 1)?"msec":"msecs") + " ";
return out.trim();
}

我不能回答你的问题,但是有一个小小的错误。您应该使用 parseInt 或 Math.floor 将浮点数转换为整数,i

var days, hours, minutes, seconds, x;
x = ms / 1000;
seconds = Math.floor(x % 60);
x /= 60;
minutes = Math.floor(x % 60);
x /= 60;
hours = Math.floor(x % 24);
x /= 24;
days = Math.floor(x);

就个人而言,我在我的项目中使用 CoffeeScript,我的代码看起来是这样的:

getFormattedTime : (ms)->
x = ms / 1000
seconds = Math.floor x % 60
x /= 60
minutes = Math.floor x % 60
x /= 60
hours = Math.floor x % 24
x /= 24
days = Math.floor x
formattedTime = "#{seconds}s"
if minutes then formattedTime = "#{minutes}m " + formattedTime
if hours then formattedTime = "#{hours}h " + formattedTime
formattedTime

这是一个解决方案。稍后你可以用“ :”分割,并获取数组的值

/**
* Converts milliseconds to human readeable language separated by ":"
* Example: 190980000 --> 2:05:3 --> 2days 5hours 3min
*/
function dhm(t){
var cd = 24 * 60 * 60 * 1000,
ch = 60 * 60 * 1000,
d = Math.floor(t / cd),
h = '0' + Math.floor( (t - d * cd) / ch),
m = '0' + Math.round( (t - d * cd - h * ch) / 60000);
return [d, h.substr(-2), m.substr(-2)].join(':');
}


var delay = 190980000;
var fullTime = dhm(delay);
console.log(fullTime);
Long expireTime = 69l;
Long tempParam = 0l;


Long seconds = math.mod(expireTime, 60);
tempParam = expireTime - seconds;
expireTime = tempParam/60;
Long minutes = math.mod(expireTime, 60);
tempParam = expireTime - minutes;
expireTime = expireTime/60;
Long hours = math.mod(expireTime, 24);
tempParam = expireTime - hours;
expireTime = expireTime/24;
Long days = math.mod(expireTime, 30);


system.debug(days + '.' + hours + ':' + minutes + ':' + seconds);

这个应该能打印0.0:1:9

以下是我使用 TimeUnit 的解决方案。

更新: 我应该指出,这是用 groovy 编写的,但 Java 几乎是相同的。

def remainingStr = ""


/* Days */
int days = MILLISECONDS.toDays(remainingTime) as int
remainingStr += (days == 1) ? '1 Day : ' : "${days} Days : "
remainingTime -= DAYS.toMillis(days)


/* Hours */
int hours = MILLISECONDS.toHours(remainingTime) as int
remainingStr += (hours == 1) ? '1 Hour : ' : "${hours} Hours : "
remainingTime -= HOURS.toMillis(hours)


/* Minutes */
int minutes = MILLISECONDS.toMinutes(remainingTime) as int
remainingStr += (minutes == 1) ? '1 Minute : ' : "${minutes} Minutes : "
remainingTime -= MINUTES.toMillis(minutes)


/* Seconds */
int seconds = MILLISECONDS.toSeconds(remainingTime) as int
remainingStr += (seconds == 1) ? '1 Second' : "${seconds} Seconds"

一种灵活的方式:
(不适用于当前日期,但足以适用于持续时间)

/**
convert duration to a ms/sec/min/hour/day/week array
@param {int}        msTime              : time in milliseconds
@param {bool}       fillEmpty(optional) : fill array values even when they are 0.
@param {string[]}   suffixes(optional)  : add suffixes to returned values.
values are filled with missings '0'
@return {int[]/string[]} : time values from higher to lower(ms) range.
*/
var msToTimeList=function(msTime,fillEmpty,suffixes){
suffixes=(suffixes instanceof Array)?suffixes:[];   //suffixes is optional
var timeSteps=[1000,60,60,24,7];    // time ranges : ms/sec/min/hour/day/week
timeSteps.push(1000000);    //add very big time at the end to stop cutting
var result=[];
for(var i=0;(msTime>0||i<1||fillEmpty)&&i<timeSteps.length;i++){
var timerange = msTime%timeSteps[i];
if(typeof(suffixes[i])=="string"){
timerange+=suffixes[i]; // add suffix (converting )
// and fill zeros :
while(  i<timeSteps.length-1 &&
timerange.length<((timeSteps[i]-1)+suffixes[i]).length  )
timerange="0"+timerange;
}
result.unshift(timerange);  // stack time range from higher to lower
msTime = Math.floor(msTime/timeSteps[i]);
}
return result;
};

注意: 如果你想控制时间范围,你也可以设置 时间步骤作为参数。

how to use (copy an test):

var elsapsed = Math.floor(Math.random()*3000000000);


console.log(    "elsapsed (labels) = "+
msToTimeList(elsapsed,false,["ms","sec","min","h","days","weeks"]).join("/")    );


console.log(    "half hour : "+msToTimeList(elsapsed,true)[3]<30?"first":"second"   );


console.log(    "elsapsed (classic) = "+
msToTimeList(elsapsed,false,["","","","","",""]).join(" : ")    );

为什么不这样做:

Var ms = 86400;

Var 秒 = ms/1000;//86.4

Var 分钟 = 秒/60;//1.4400000000000002

Var hours = minutes/60;//0.0240000000000000004

Var days = hours/24;//0.00100000000000002

并处理浮点精度,例如 Number (minutes.toFixed(5))//1.44

I suggest to use http://www.ocpsoft.org/prettytime/ library..

以人类可读的形式获得时间间隔非常简单,比如

PrettyTime p = new PrettyTime () ; Println (p.format (new Date ())) ;

it will print like "moments from now"

另一个例子

PrettyTime p = new PrettyTime () ; Date d = new Date (System.currentTimeMillis ()) ; 设置时间(设置时间()-1) ; String ago = p.format (d) ;

那么 string ago = “1小时前”

在爪哇

public static String formatMs(long millis) {
long hours = TimeUnit.MILLISECONDS.toHours(millis);
long mins = TimeUnit.MILLISECONDS.toMinutes(millis);
long secs = TimeUnit.MILLISECONDS.toSeconds(millis);
return String.format("%dh %d min, %d sec",
hours,
mins - TimeUnit.HOURS.toMinutes(hours),
secs - TimeUnit.MINUTES.toSeconds(mins)
);
}

给出了这样的东西:

12h 1 min, 34 sec

使用 awk的解决方案:

$ ms=10000001; awk -v ms=$ms 'BEGIN {x=ms/1000;
s=x%60; x/=60;
m=x%60; x/=60;
h=x%60;
printf("%02d:%02d:%02d.%03d\n", h, m, s, ms%1000)}'
02:46:40.001

在 python 3中,您可以通过使用以下代码片段来实现您的目标:

from datetime import timedelta


ms = 536643021
td = timedelta(milliseconds=ms)


print(str(td))
# --> 6 days, 5:04:03.021000

时间三角洲文档: https://docs.python.org/3/library/datetime.html#datetime.timedelta

Timedelta str 的 _ _ str _ _ 方法的来源: https://github.com/python/cpython/blob/33922cb0aa0c81ebff91ab4e938a58dfec2acf19/Lib/datetime.py#L607

这里省略了0个值,用于测试。

const toTimeString = (value, singularName) =>
`${value} ${singularName}${value !== 1 ? 's' : ''}`;


const readableTime = (ms) => {
const days = Math.floor(ms / (24 * 60 * 60 * 1000));
const daysMs = ms % (24 * 60 * 60 * 1000);
const hours = Math.floor(daysMs / (60 * 60 * 1000));
const hoursMs = ms % (60 * 60 * 1000);
const minutes = Math.floor(hoursMs / (60 * 1000));
const minutesMs = ms % (60 * 1000);
const seconds = Math.round(minutesMs / 1000);


const data = [
[days, 'day'],
[hours, 'hour'],
[minutes, 'minute'],
[seconds, 'second'],
];


return data
.filter(([value]) => value > 0)
.map(([value, name]) => toTimeString(value, name))
.join(', ');
};


// Tests
const hundredDaysTwentyHoursFiftyMinutesThirtySeconds = 8715030000;
const oneDayTwoHoursEightMinutesTwelveSeconds = 94092000;
const twoHoursFiftyMinutes = 10200000;
const oneMinute = 60000;
const fortySeconds = 40000;
const oneSecond = 1000;
const oneDayTwelveSeconds = 86412000;


const test = (result, expected) => {
console.log(expected, '- ' + (result === expected));
};


test(readableTime(
hundredDaysTwentyHoursFiftyMinutesThirtySeconds
), '100 days, 20 hours, 50 minutes, 30 seconds');


test(readableTime(
oneDayTwoHoursEightMinutesTwelveSeconds
), '1 day, 2 hours, 8 minutes, 12 seconds');


test(readableTime(
twoHoursFiftyMinutes
), '2 hours, 50 minutes');


test(readableTime(
oneMinute
), '1 minute');


test(readableTime(
fortySeconds
), '40 seconds');


test(readableTime(
oneSecond
), '1 second');


test(readableTime(
oneDayTwelveSeconds
), '1 day, 12 seconds');