mysql 时间绝对值_datetime和timestamp--时间戳是绝对值,日期是相对值
遇到的問題:系統時間與數據庫時間不一致,系統時間是8:20,存到數據庫里是0:20。
第一直覺是時區不同導致的。
先看一段代碼:
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
這說明,時間的顯示是由時區決定的,時間所表示的距標準時間毫秒數是絕對的,不會隨時區不同而改變。理解這一點很重要。
那么數據庫里的時間也應該有個時區概念,那到底是如何處理的呢?一直這么認為的,時間在數據庫里實際存的是毫秒數。那我們在客戶端看到的時間一定是經過數據庫格式化以后的。
但結果不完全是這樣的,下面我們要討論數據庫中的兩個時間類型 datetime 和 timestamp 。
網上有文稱
datetime - 存儲日期和時間部分,精確到秒,沒有時區信息
timestamp - 時間戳,存儲日期、時間和時區信息,秒值精確到小數點后6位
注意這里的時間戳,在sqlserver中根本就不是時間,他只記錄相對時間的先后,不記錄具體時間。我認為應該叫做數據版本號。
首先在sqlserver中測試:
select getdate()
執行結果跟想像的一樣,操作系統的時區如何修改,他都能隨之變化,他肯定獲得了系統的時區信息,然后對當前毫秒數格式化。
把系統時區恢復到GMT+8:00,創建一個測試表,并插入兩條數據
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;
這時數據庫查詢結果為
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
現在修改系統時區為GMT+5:00,再插入兩條數據,并修改第一條數據
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;
這時數據庫查詢結果為
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沒有時區信息,只有年月日時分秒,所以保存的是幾點就是幾點,兩次操作差了3個小時。
select t.*,t.time2-t.time1 from TEST_TIMEZONE t where t.tid=1
我們再看時間戳類型,sqlserver一個表只能有一個時間戳列,而且時間戳列不用操作,在數據行插入或更新時自動更新。
新建測試表
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
這個時間戳主要用在處理并發問題上,做為數據是否已被修改的憑證,可以提高并發性能。 再次明確sqlserver的時間戳不是具體時間。
恢復一下時區到GMT+8:00,都不知道現在幾點了。
接下來,在mysql做個測試:
select now()
修改系統時區對查詢結果沒有影響,這與sqlserver不同。修改時區后,重啟mysql,再執行有效果了。說明mysql在啟動時記錄了系統時區,而不是實時的讀取系統時區。
恢復時區到GMT+8:00,新建 表
create table TEST_TIMEZONE(
tid int,
time1 datetime ,
time2 timestamp ,
time3 timestamp
);
插入數據
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。
恢復時區到GMT+5:00,重啟動mysql,執行查詢
結果說明datetime的時間不隨系統時區而變化,timestamp會隨系統時區變化而變化,也sqlserver完全不同。Mysql在timestamp字段記錄的是毫秒數,并且按初始的系統時區格式化后顯示。
另外對oracle現在沒有測試環境。
結論:
Datatime類型只保存年月日時分秒信息,不含時區。
Timestamp時間戳,不同數據庫有不同的實現,不要用做業務列,更不能作為索引或鍵使用,他會自動被更新。
總結
以上是生活随笔為你收集整理的mysql 时间绝对值_datetime和timestamp--时间戳是绝对值,日期是相对值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广发银行信用卡申请被拒 几招补救信用卡申
- 下一篇: 如何释放mysql连接资源_CI框架出现