时间导致的时差以及日期时间格式

最后更新:2023-10-20 14:08:34 | 状态:未完成
如果数据库中存储的时间与Java中查出来的时间不一致,一般是由于时区不同造成的。
先确认服务器时间和数据库时间是否一致。
再看服务器时区、数据库时区、Java连接数据库的时区
如果时区一致,有可能是显示的格式化的问题,格式化时注意大小写

Linux时区
date -R
Fri, 20 Oct 2020 09:13:32 +0800
后面的 +8就是东八区

JVM设置时区
启动添加参数:
# 去掉TZ环境变量影响
unset TZ
# TestTimeZone为java类
java -Duser.timezone=Asia/Shanghai TestTimeZone
环境变量设置:
export TZ=Asia/Shanghai
JVM时区参数:
user.timezone 没值则代表取操作系统的默认时区
代码中设置JVM时区
System.setProperty("user.timezone","Asia/Shanghai"); 


MySQL时区

SELECT @@global.system_time_zone;
SELECT @@session.time_zone;
如果返回的SYSTEM表示与系统时区一致

配置文件时区/etc/my.cnf
[mysqld]
default-time-zone = '+8:00'

JDBC连接mysql时南要加时区参数serverTimezone=Asia/Shanghai


如果时区都一致,可能是显示格式的问题
关于LocalTime中如果秒位置是0 则toString()会忽略秒如 12:00:00会显示成12:00(分位置会保留)
在查出数据后给前端显示前应该格式化日期时间格式,而不应该通过toString()显示

DataRow/DataSet都提交了格式化方法
new DataRow().format.date("yyyy-MM-dd HH:mm:ss", "JOIN_TIME","CREATE_TIME")
jackson也提供了相关的格式化方法,可以参考BeanUtil源码开头部分
类似这样
JSON_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(TIME_FORMATTER));

如果在sql中格式化注意每个库的标识符不一样,背是背不过的,尽量在java中统一处理
pg:to_char(now(), 'YYYY-MM-DD HH24:MI:SS.US')
HH 一天的小时数(01-12)
HH12 一天的小时数(01-12)
HH24 一天的小时数(00-23)
MI 分钟(00-59)
SS 秒(00-59)
MS 毫秒(000-999)
US 微秒(000000-999999)
AM 正午标识(大写)
Y,YYY 带逗号的年(4和更多位)
YYYY 年(4和更多位)
YYY 年的后三位
YY 年的后两位
Y 年的最后一位
MONTH 全长大写月份名(空白填充为9字符)
Month 全长混合大小写月份名(空白填充为9字符)
month 全长小写月份名(空白填充为9字符)
MON 大写缩写月份名(3字符)
Mon 缩写混合大小写月份名(3字符)
mon 小写缩写月份名(3字符)
MM 月份号(01-12)
DAY 全长大写日期名(空白填充为9字符)
Day 全长混合大小写日期名(空白填充为9字符)
day 全长小写日期名(空白填充为9字符)
DY 缩写大写日期名(3字符)
Dy 缩写混合大小写日期名(3字符)
dy 缩写小写日期名(3字符)
DDD 一年里的日子(001-366)
DD 一个月里的日子(01-31)
D 一周里的日子(1-7;周日是1)
W 一个月里的周数(1-5)(第一周从该月第一天开始)
WW 一年里的周数(1-53)(第一周从该年的第一天开始)

mysql:SELECT DATE_FORMAT(now(), '%Y-%m-%d %H:%i:%s');
%a 缩写星期名
%b 缩写月名
%c 月,数值
%D 带有英文前缀的月中的天
%d 月的天,数值(00-31)
%e 月的天,数值(0-31)
%f 微秒
%H 小时 (00-23)
%h 小时 (01-12)
%I 小时 (01-12)
%i 分钟,数值(00-59)
%j 年的天 (001-366)
%k 小时 (0-23)
%l 小时 (1-12)
%M 月名
%m 月,数值(00-12)
%p AM 或 PM
%r 时间,12-小时(hh:mm:ss AM 或 PM)
%S 秒(00-59)
%s 秒(00-59)
%T 时间, 24-小时 (hh:mm:ss)
%U 周 (00-53) 星期日是一周的第一天
%u 周 (00-53) 星期一是一周的第一天
%V 周 (01-53) 星期日是一周的第一天,与 %X 使用
%v 周 (01-53) 星期一是一周的第一天,与 %x 使用
%W 星期名
%w 周的天 (0=星期日, 6=星期六)
%X 年,其中的星期日是周的第一天,4 位,与 %V 使用
%x 年,其中的星期一是周的第一天,4 位,与 %v 使用
%Y 年,4 位
%y 年,2 位

oracle:SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual;
YYYY  四位数年份
YY  两位数年份
MM  月份(01-12)
MON  月份(JAN-DEC)
DD | 日期(01-31)
HH24  24小时制的小时数(00-23)
HH12  12小时制的小时数(01-12)
MI  分钟数(00-59)
SS  秒数(00-59)
FF  毫秒数(1-9)

SQL Server:SELECT CONVERT(varchar(20), GETDATE(), 'yyyy年MM月dd日 HH:mm:ss')
SELECT FORMAT(GETDATE(), 'yyyy-MM-dd')
yyyy四位数年份
yy 两位数年份
y 年份
Q 季度
MM 月份(两位数)
M 月份
dd 日期(两位数)
d 日期
hh 小时(两位数,12小时制)
h 小时(12小时制)
HH 小时(两位数,24小时制)
H 小时(24小时制)
mm 分钟(两位数)
m 分钟
ss 秒钟(两位数)
s 秒钟
ttAM或PM
另外SQL Server还给整了几个枚举

SELECT CONVERT(varchar(100), GETDATE(), 1) 返回01/03/17
2 17.01.03
3 03/01/17
4 03.01.17
5 03-01-17
6 03 01 17
7 01 03, 17
8 09:09:10
9 01 3 2017 9:09:10:037AM
10 01-03-17
11 17/01/03
12 170103
13 03 01 2017 09:09:10:037
14 09:09:10:037
20 2017-01-03 09:09:10
21 2017-01-03 09:09:10.037
22 01/03/17 9:09:10 AM
23 2017-01-03
24 09:09:10
25 2017-01-03 09:09:10.037
100 01 3 2017 9:09AM
101 01/03/2017
102 2017.01.03
103 03/01/2017
104 03.01.2017
105 03-01-2017
106 03 01 2017
107 01 03, 2017
108 09:09:10
109 01 3 2017 9:09:10:037AM
110 01-03-2017
111 2017/01/03
112 20170103
113 03 01 2017 09:09:10:037
114 09:09:10:037
120 2017-01-03 09:09:10
121 2017-01-03 09:09:10.037
126 2017-01-03T09:09:10.037 
1315/04/1438 9:09:10:037AM

最近更新 搜索 提交