我们在做业务的时候,按天查询数据的时候可能要计算某天的起始时间和结束时间。
通常情况下,我们都是先获取这一天的年月日,然后时分秒用0填充构造一个新的时间对象,返回时间戳。
如下面的一个Java的示例:
import java.util.Calendar;
public class Test {
Long getDailyStartTime(Long timeStamp) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTimeInMillis();
}
}
不同的编程语言有不同的语法,但是基本思路是一致的。
但是仔细一想,发现这种方法太麻烦。
我们计算某天的开始时间戳,本质就是抹零。
所以我们可以这样思考,我们只需要计算某时间到零点时间戳的天数,再乘以每天的秒数即可。
这里的零点时间戳,即为1970年1月1日0点0分0秒。
那么这个公式可以表示为
floor((某时间戳-零点时间戳)/一天包含的秒数) * 一天包含的秒数
但这里需要注意的是,Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。
所以上述方法算出的是UTC+0
的0点时间戳,实际上我们是东八区(UTC+8),是有时差的,所以我们还得考虑时区因素。
我们location的1970年1月1日0点的实际时间戳是 0-8*3600
所以,我们最终的计算方式用C语言表示为:
int getDailyStartTime(int ts)
{
return ((ts + 8*3600)/(24*3600))*24*3600-8*3600;
}
用此思路,也可以计算某小时的起始时间戳,而且因为不涉及时区,更简单。
int getHourStartTime(int ts)
{
return (ts/3600)*3600;
}
注意了,此方法只能计算天,小时,分钟等单位固定的起始时间戳,不能计算年和月, 因为不同的年份和月份所包含的秒数是不同的。