Spring时区转换问题
spring转json的默认实现jackson中会根据时区去转换时间,而jackson的默认时区跟国内是相差8小时的。
解决方法:
重新设置当前项目地所在时区。使用注解的方法。
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
Javascript时区转换问题
方法一:
/**
* 日期转换
* @param datetime
* @param fmt
* @returns {*}
* @constructor
*/
function Format(datetime,fmt) {
if (parseInt(datetime)==datetime) {
if (datetime.length==10) {
datetime=parseInt(datetime)*1000;
} else if(datetime.length==13) {
datetime=parseInt(datetime);
}
}
datetime=new Date(datetime);
var o = {
"M+" : datetime.getMonth()+1, //月份
"d+" : datetime.getDate(), //日
"h+" : datetime.getHours(), //小时
"m+" : datetime.getMinutes(), //分
"s+" : datetime.getSeconds(), //秒
"q+" : Math.floor((datetime.getMonth()+3)/3), //季度
"S" : datetime.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt))
fmt=fmt.replace(RegExp.$1, (datetime.getFullYear()+"").substr(4 - RegExp.$1.length));
for(var k in o)
if(new RegExp("("+ k +")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
return fmt;
}
方法二:
function setTime(datetime,i) {
//参数i为时区值数字,比如北京为东八区则输进8,西5输入-5
if (typeof i !== 'number') return;
var d = new Date(datetime);
console.log('d:'+ d);
//得到1970年一月一日到现在的秒数
var len = d.getTime();
//本地时间与GMT时间的时间偏移差
var offset = d.getTimezoneOffset() * 60000;
//得到现在的格林尼治时间
var utcTime = len + offset;
return new Date(utcTime + 3600000 * i);
}
方法三:
function dateToGMT(strDate){
var dateStr=strDate.split(" ");
var strGMT = dateStr[0]+" "+dateStr[1]+" "+dateStr[2]+" "+dateStr[5]+" "+dateStr[3]+" GMT+0800";
var date = new Date(Date.parse(strGMT));
return date;
}
docker部署完系统后,时区问题排查
1、首先排查Linux系统时间
利用date命令
[root@oracle-131 bytd]# date
Tue Apr 21 17:30:24 CST 2020
[root@oracle-131 bytd]#
2、docker容器的时区
进入宿主机查看容器 docker ps
进入容器 docker exec -it “容器名“ /bin/bash
查询时间 date -R 发现时区为0时区
Tue, 21 Apr 2020 07:23:05 +0000
解决办法:
(1)、复制相应的时区文件,替换系统时区文件;
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
有的容器基础镜像是有这个文件的,直接拷贝就可以,如果不能拷贝,则是因为创建镜像时依赖的基础镜像 运行的容器没有这两个文件,使用下面的办法
(2)、创建文件夹
mkdir -p /usr/share/zoneinfo/Asia
(3)、回到宿主机,复制宿主机里的文件到容器中
docker cp /usr/share/zoneinfo/Asia/Shanghai 容器ID或容器名:/usr/share/zoneinfo/Asia
(4)、进入容器
docker exec -it 容器Id或容器名 bash
执行命令 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
(5)、验证date
bash-5.0# date
Tue Sep 17 13:54:25 CST 2019
3、继续排查数据源时间
如果是MySQL:直接在链接后面加上 &useTimezone=true&serverTimezone=GMT%2B8
Oracle时间相关数据类型
序号 | 数据类型 | 说明 | 使用选择 |
---|---|---|---|
1 | DATE | 存储日期和时间信息,精确到秒 | 所占字节最少,最节省空间 |
2 | TIMSTAMP | DATE类型的扩展,保留小数级别的秒,默认为小数点后6位 | 所占字节比DATE要多,但比其他两个数据类型少 |
3 | TIMESTAMP WITH TIME ZONE | 存储带时区信息的TIMESTAMP | 需要保存时区/地区信息的时候使用 |
4 | TIMESTAMP WITH LOCAL TIME ZONE | 和TIMESTAMP WITH TIME ZONE类型的区别:不会保存原时间的时区信息,而是把时间转换为基于数据库时区(database timezone)的时间后存入数据库 | 谨慎使用,不关心操作发生的具体地点,而只关心操作是在当前时区的几点发生 |
如果是Oracle:
【DATE】
设置格式:
SQL> alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS';
查询系统时间:
SQL> select sysdate from dual;
【TIMESTAMP】
设置格式:
SQL> ALTER SESSION SET NLS_TIMESTAMP_FORMAT='DD-MON-YY HH:MI:SSXFF';
查询数据库所在系统时间:
SQL> select localtimestamp from dual;
【TIMESTAMP WITH TIME ZONE】
设置格式:
SQL> ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='DD-MON-RR HH:MI:SSXFF AM TZR';
查询数据库所在系统时间(带时区):
SQL> select systimestamp from dual;
【TIMESTAMP WITH LOCAL TIME ZONE】
设置数据库时区(东8区),需要重启数据库才会生效:
SQL> ALTER SESSION SET TIME_ZONE='+08:00';
查询数据库时区:
SQL> select dbtimezone from dual;
查看数据库时区和会话时区
SQL> select dbtimezone,systimestamp from dual;
修改数据时区
SQL> alter database set time_zone='+8:00';
可能会有以下报错:
ORA-30079: cannot alter database timezone when database has TIMESTAMP WITH LOCAL TIME ZONE columns
从错误提示可以看出数据库中某些字段的数据类型为:TIMESTAMP WITH LOCAL TIME ZONE,只有将这些列删除之后,才能更改。
更改完时区之后需要重启数据库
SQL> shutdown immediate;
SQL> startup;
更新之后,重新查询数据库时区
SQL> select dbtimezone from dual;
4、排查JDK1.8(Tomcat)时区
可通过查看tomcat日志。
(1)如果日志时间正确,故排除tomcat时区问题。
(2)如果日志时间不正确,则修改tomcat时区.
编辑tomcat/bin目录下的 catalina.sh 或 catalina.bat ,添加JAVA_OPTS参数
JAVA_OPTS="$JAVA_OPTS -Duser.timezone=GMT+08"
保存,重启Tomcat使配置生效,即可设置为东八区时区