背景
项目中遇到这样一个需求,从后台获取到一个时间戳,需要在页面上展示成比如”一个月前“的字样。
下面是百度搜到的实现方式以及我进行优化之后的代码。
百度结果
function getDateDiff(dateTimeStamp) {
var minute = 1000 * 60;
var hour = minute * 60;
var day = hour * 24;
var halfamonth = day * 15;
var month = day * 30;
var now = new Date().getTime();
var diffValue = now - dateTimeStamp;
if (diffValue < 0) {
return;
}
var monthC = diffValue / month;
var weekC = diffValue / (7 * day);
var dayC = diffValue / day;
var hourC = diffValue / hour;
var minC = diffValue / minute;
if (monthC >= 1) {
result = "" + parseInt(monthC) + "月前";
} else if (weekC >= 1) {
result = "" + parseInt(weekC) + "周前";
} else if (dayC >= 1) {
result = "" + parseInt(dayC) + "天前";
} else if (hourC >= 1) {
result = "" + parseInt(hourC) + "小时前";
} else if (minC >= 1) {
result = "" + parseInt(minC) + "分钟前";
} else {
result = "刚刚";
}
return result;
}
这里是代码执行的大致思路:
- 以秒为基本单位,首先计算出每个时间单位(分钟、小时、天、半月、一月)内包含多少秒
- 计算现在与需要对比的时间戳之间的差值,如果差值小于 0 ,证明出现异常,直接返回
- 分别将步骤 2 中计算出的时间差值除以每个时间单位(月、周、天、小时、分),得到商值(向下取整,如 10 除以 4 得到 2.5,则结果为 2)
- 对步骤 3 中的商值进行判断,具体判断逻辑如下:
- 先对最大的时间单位进行判断,这里是“月”,你也可以改成“年”;
- 如果
monthC
大于或者等于1
,假设是 2,则返回结果是2月前
; - 如果
monthC
小于1
,则说明时间差在一个月之内,那么就以“周”为单位进行判断; - 如果
weekC
大于或者等于1
,假设是 2,则返回结果是2周前
; - 如果
weekC
小于1
,则说明时间差在一周之内,那么就以“天”为单位进行判断; - 重复步骤 2 和 3,直至单位是分钟,如果小于一分钟,则直接返回“刚刚”。
优化
/*
* 将时间戳转化为 “几周前” 的形式
*/
function getAgoAt (stamptime) {
var current_time = Date.parse(new Date()) / 1000;
var diff = current_time - stamptime;
var agoAt = '刚刚';
var timePoints = [
{ value: 60 * 60 * 24 * 365, suffix: '年前', max: 2 },
{ value: 60 * 60 * 24 * 30, suffix: '月前', max: 11 },
{ value: 60 * 60 * 24 * 7, suffix: '周前', max: 4 },
{ value: 60 * 60 * 24, suffix: '天前', max: 6 },
{ value: 60 * 60, suffix: '小时前', max: 23 },
{ value: 60 * 10, suffix: '0分钟前', max: 5 }
];
for (var i = 0; i < timePoints.length; i++) {
var point = timePoints[i];
var mode = Math.floor(diff / point.value);
if (mode > 1) {
agoAt = Math.min(mode, point.max) + point.suffix;
break;
}
}
return agoAt;
}
代码思路:
- 计算现在与需要对比的时间戳之间的差值
- 以数组形式定义时间表
timePoints
,数组中的每项元素都是一个时间单位的对象,包含 3 个属性:-
value
: 时间单位包含的秒数,如“年”的value
值是365 * 24 * 60 * 60
-
suffix
: 后缀,用于最终结果中的文字部分,如1年前
中的文字部分年前
-
max
: 用于限制时间单位的个数,比如时间差最多只能是4 周前
,而不能是5 周前
。
-
- 遍历时间表
timePoints
:- 获得时间差与单位时间包含秒数的商,并向下取整,记为
mode
- 如果
mode
大于 1 ,则使用当前的时间单位当做最终结果,否则继续遍历,直至遍历结束。
- 获得时间差与单位时间包含秒数的商,并向下取整,记为