mysql 时间绝对值_datetime和timestamp--时间戳是绝对值,日期是相对值
遇到的問題:系統(tǒng)時間與數(shù)據庫時間不一致,系統(tǒng)時間是8:20,存到數(shù)據庫里是0:20。
第一直覺是時區(qū)不同導致的。
先看一段代碼:
Java代碼
public?static?void?main(String[]?args)?{
//System.out.println(TimeZone.getDefault());
SimpleDateFormat?sdf?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");
Calendar?c?=?Calendar.getInstance();
//System.out.println(c.getTime());
System.out.println(sdf.format(c.getTime()));
System.out.println(c.getTimeInMillis());
TimeZone.setDefault(TimeZone.getTimeZone("GMT+5:00"));
sdf.setTimeZone(TimeZone.getDefault());
//System.out.println(c.getTime());
//System.out.println(c.getTime().getTimezoneOffset());
System.out.println(sdf.format(c.getTime()));
System.out.println(c.getTimeInMillis());
}
輸出結果:
2011-11-25 10:33:21
1322188401796
2011-11-25 07:33:21
1322188401796
這說明,時間的顯示是由時區(qū)決定的,時間所表示的距標準時間毫秒數(shù)是絕對的,不會隨時區(qū)不同而改變。理解這一點很重要。
那么數(shù)據庫里的時間也應該有個時區(qū)概念,那到底是如何處理的呢?一直這么認為的,時間在數(shù)據庫里實際存的是毫秒數(shù)。那我們在客戶端看到的時間一定是經過數(shù)據庫格式化以后的。
但結果不完全是這樣的,下面我們要討論數(shù)據庫中的兩個時間類型 datetime 和 timestamp 。
網上有文稱
datetime - 存儲日期和時間部分,精確到秒,沒有時區(qū)信息
timestamp - 時間戳,存儲日期、時間和時區(qū)信息,秒值精確到小數(shù)點后6位
注意這里的時間戳,在sqlserver中根本就不是時間,他只記錄相對時間的先后,不記錄具體時間。我認為應該叫做數(shù)據版本號。
首先在sqlserver中測試:
select getdate()
執(zhí)行結果跟想像的一樣,操作系統(tǒng)的時區(qū)如何修改,他都能隨之變化,他肯定獲得了系統(tǒng)的時區(qū)信息,然后對當前毫秒數(shù)格式化。
把系統(tǒng)時區(qū)恢復到GMT+8:00,創(chuàng)建一個測試表,并插入兩條數(shù)據
create table TEST_TIMEZONE(
tid int,
time1 datetime ,
time2 datetime
);
insert into TEST_TIMEZONE values(1,getdate(),getdate());
insert into TEST_TIMEZONE values(2,getdate(),getdate());
select * from TEST_TIMEZONE;
這時數(shù)據庫查詢結果為
1???? 2011-11-25 10:47:23.750?????? 2011-11-25 10:47:23.750
2???? 2011-11-25 10:47:27.513?????? 2011-11-25 10:47:27.513
現(xiàn)在修改系統(tǒng)時區(qū)為GMT+5:00,再插入兩條數(shù)據,并修改第一條數(shù)據
insert into TEST_TIMEZONE values(3,getdate(),getdate());
insert into TEST_TIMEZONE values(4,getdate(),getdate());
update TEST_TIMEZONE set time1=getdate() where tid=1;
select * from TEST_TIMEZONE;
這時數(shù)據庫查詢結果為
1???? 2011-11-25 07:50:20.373?????? 2011-11-25 10:47:23.750
2???? 2011-11-25 10:47:27.513?????? 2011-11-25 10:47:27.513
3???? 2011-11-25 07:50:15.920?????? 2011-11-25 07:50:15.920
4???? 2011-11-25 07:50:18.500?????? 2011-11-25 07:50:18.500
因為datetime沒有時區(qū)信息,只有年月日時分秒,所以保存的是幾點就是幾點,兩次操作差了3個小時。
select t.*,t.time2-t.time1 from TEST_TIMEZONE t where t.tid=1
我們再看時間戳類型,sqlserver一個表只能有一個時間戳列,而且時間戳列不用操作,在數(shù)據行插入或更新時自動更新。
新建測試表
create table TEST_TIMEZONE2(
tid int,
time1 timestamp
);
insert into TEST_TIMEZONE2(tid) values(1);
insert into TEST_TIMEZONE2(tid) values(2);
insert into TEST_TIMEZONE2(tid) values(3);
select * from TEST_TIMEZONE2;
查詢結果:
1???? 0x000000000000200A
2???? 0x000000000000200B
3???? 0x000000000000200C
update TEST_TIMEZONE2 set tid=4 where tid=3;
select * from TEST_TIMEZONE2;
查詢結果:
1???? 0x000000000000200A
2???? 0x000000000000200B
4???? 0x000000000000200E
這個時間戳主要用在處理并發(fā)問題上,做為數(shù)據是否已被修改的憑證,可以提高并發(fā)性能。 再次明確sqlserver的時間戳不是具體時間。
恢復一下時區(qū)到GMT+8:00,都不知道現(xiàn)在幾點了。
接下來,在mysql做個測試:
select now()
修改系統(tǒng)時區(qū)對查詢結果沒有影響,這與sqlserver不同。修改時區(qū)后,重啟mysql,再執(zhí)行有效果了。說明mysql在啟動時記錄了系統(tǒng)時區(qū),而不是實時的讀取系統(tǒng)時區(qū)。
恢復時區(qū)到GMT+8:00,新建 表
create table TEST_TIMEZONE(
tid int,
time1 datetime ,
time2 timestamp ,
time3 timestamp
);
插入數(shù)據
insert into TEST_TIMEZONE(tid) values(1);
insert into TEST_TIMEZONE(tid) values(2);
insert into TEST_TIMEZONE values(3,now(),now(),now());
insert into TEST_TIMEZONE values(4,now(),now(),now());
select * from TEST_TIMEZONE
查詢結果
Mysql允許多個timestamp列,但只有第一列會自動更新,默認值 為
CURRENT_TIMESTAMP。
恢復時區(qū)到GMT+5:00,重啟動mysql,執(zhí)行查詢
結果說明datetime的時間不隨系統(tǒng)時區(qū)而變化,timestamp會隨系統(tǒng)時區(qū)變化而變化,也sqlserver完全不同。Mysql在timestamp字段記錄的是毫秒數(shù),并且按初始的系統(tǒng)時區(qū)格式化后顯示。
另外對oracle現(xiàn)在沒有測試環(huán)境。
結論:
Datatime類型只保存年月日時分秒信息,不含時區(qū)。
Timestamp時間戳,不同數(shù)據庫有不同的實現(xiàn),不要用做業(yè)務列,更不能作為索引或鍵使用,他會自動被更新。
總結
以上是生活随笔為你收集整理的mysql 时间绝对值_datetime和timestamp--时间戳是绝对值,日期是相对值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广发银行信用卡申请被拒 几招补救信用卡申
- 下一篇: 计算机专业408题目结构,2019考研4