Lab3开发应用的过程中,与用户交互使用的格式大多是日期和周工作日的形式。
比如日期:2021-07-04;周工作日形式:1(Monday)…7(Sunday)。而应用底层ADT的处理过程都是基于绝对时间戳的。在ADT将结果计算出来之后,同样要以日期或周工作日的形式打印信息反馈给用户。因此在这个过程中反复用到了日期与绝对时间戳的互相转化。
自己造轮子写转化算法是比较麻烦的,难度不大,但细节很多(腊月、2月、闰年、平年),调试也需要花一番功夫。上网查了查,大概知道了java自带的日期类Date、日历类Calendar,以及日期格式化类SimpleDateFormat。借助这几个类的接口可以直接实现转化。
但需要注意的是,这几个类的时间可以精确到毫秒级,也就是说转化后的时间戳1个单位表示1毫秒。而我们的应用中完全不需要如此高的精度,应用一精确到日,应用三精确到小时即可。虽然实验指导书上非常有先见之明的建议将ADT内部有关时间戳的类型全部定义为long,但调试的时候看一堆十几位的整数也是够累眼睛的,不如手动调整一下精度。
原来想的是:一天24小时、一小时60分钟、一分钟60秒、一秒1000毫秒,那么只需要将精度为毫秒的时间戳/24/60/60/1000即可,这样得到的结果1个单位就表示1天,同理如果要精确到小时只需/60/60/1000。但测试了一下发现并不对,这么直接除是除不尽的。急中生智我打印了一下时间戳1对应的日期,是1970-01-01 …。总之是位于这个日期中午的某个时间段而不是00:00。那么显然事件戳的起始点并不是1。但几乎可以肯定1970应该是万年历的起点(Windows系统时间起点就是1970)。那么顺势打印一下1970-01-01 00:00的时间戳,发现为-28800000,看来起点是这个数(至于为甚么要设这么个奇怪的数当起点我也很迷惑)。那么我们只需要在上面的计算公式中引入28800000这个偏移量就行了。
日期转时间戳的时候,要先将java自带类的转化结果+28800000,再依次除掉那些常数,最后2021-07-02这个日期顺利的除成了18335(具体多少忘了)左右一个数,大概算一下从1970年到现在差不多就是这么多天,那么我们的转换应该没有大问题了。
日期转时间戳(精确到日)代码如下:
/**
* 将日期转化为抽象的时间戳
*
* @return 转化后的时间戳
*/
public long Date2Time(String date) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date d = format.parse(date);
return (d.getTime() + 28800000L) / 1000L / 60L / 60L / 24L;
}
相应的反过来时间戳转日期需要-28800000这个偏移量(逆运算嘛),代码如下:
/**
* 将时间戳转化为人可以看懂的格式化日期
*
* @return 格式化日期字符串
*/
public String Time2Date(long time) {
time = time * 60L * 60L * 24L * 1000L - 28800000L;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.format(new Date(time));
}
有了这两个函数,在与用户交互时表示问题就非常方便了。