`起因:`最近同事在做定時打卡的東西,遇到一個詭異的問題,端只是傳了一個開始時間跟打卡周期,剩下的打卡時間都是由服務端自己生成的,顯示的截止時間有的變成==23:59:59==. 有時候又變成了 ==00:00:00==,沒有找到原因,讓幫忙找一下原因,之前沒有遇到過這種情況,一時來了興趣。 通過編 ...
起因:
最近同事在做定時打卡的東西,遇到一個詭異的問題,端只是傳了一個開始時間跟打卡周期,剩下的打卡時間都是由服務端自己生成的,顯示的截止時間有的變成==23:59:59==. 有時候又變成了 ==00:00:00==,沒有找到原因,讓幫忙找一下原因,之前沒有遇到過這種情況,一時來了興趣。
探究:
通過編寫單元測試,過程並沒有出錯,入庫的時候時間確實是23:59:59,入庫之後就變了,相關測試代碼如下
@Autowired
private JdbcTemplate jdbc;
@Test
public void timeTest(){
Date dateInDay = getDateInDay(new Date(), 23, 59, 59);
jdbc.update("INSERT INTO test(create_time) VALUES(?)", new Object[] {dateInDay});
}
/**
* 獲取某個日期的時刻點,如2017-02-01的18:00:00
* @param date 開始日期
* @param hour 時
* @param minute 分
* @param second 秒
* @return
*/
public static Date getDateInDay(Date date, int hour, int minute, int second){
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
return c.getTime();
}
資料庫結果:
1 2019-05-23 23:59:59
2 2019-05-24 00:00:00
3 2019-05-24 00:00:00
4 2019-05-24 00:00:00
5 2019-05-23 23:59:59
但是在開發庫沒有出現這種現象,部署到測試環境就出現這種現象了,其中開發庫mysql5.6
版本,測試庫使用的5.7
版本。初步推斷是由於資料庫版本不一樣,對時間處理的不一樣導致的,但是具體細節是什麼,最終決定去翻閱一下mysql官方的說明文檔,終於找到了答案。
從這篇Fractional Seconds in Time Values中我們看到5.6.4
之前的版本中是不保存毫秒數的,那麼高版本中是如何處理的?
從這篇Conversion Between Date and Time Types中我們看到毫秒數在低於500的時候會捨棄掉,大於等於500會進位,類似四捨五入
,既然找到問題的本質原因,那麼解決起來也比較方便了,只需要設置一下日期的毫秒數就能得到有效解決,修改如下:
public static Date getDateInDay(Date date, int hour, int minute, int second){
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
//設置毫秒數,避免產生進位
c.set(Calendar.MILLISECOND,0);
return c.getTime();
}
總結:
從這個小問題中,個人最大的感受就是官方api的重要性,對於開發用到的工具、技術要多多關註官方refrence,和release note,看看新加了哪些新特性,優化了哪些內容,修複了哪些bug。