ssm java编程遇到从数据库中查询的时间与存储时间不一致

推荐先去看这篇文章: java编程中遇到的时区与时间问题总结
http://blog.csdn.net/yeahwell/article/details/8559996

这几天开发中遇到一个问题:ssm中使用mapper从数据库中查询datetime类型字段,查询结果与存储结果不一致,大约比存储时间多了8个小时左右。网上查了很久都没看见有类型问题的解决方案。
刚开始开始想的是将数据库的字段的类型datetime改为date类型,问题确实解决;但是后来发现虽然自己不读取时分秒,但是其他人可能需要读取,这样改了后可能会影响到别人。
后来看到了一篇博客文章,知道了是Java的date转换出现了问题。

    因为Java这边会默认获取当前时区,我这的时区北京时区,即:GMT+8;同时Java这边会认为获取到的时间是unix timestamp的,此时Java会自动将其转换为符合当前时区的时间。因此也就出现了比存储时间多了的情况。

所以解决办法是,在写的sql语句中先将器格式化好如下(mysql):

SELECT id, date_format(OPER_DATE, '%Y-%c-%e %T') OPER_DATE FROM tempWHERE `STATUS`=1 AND id=#{id}

这样好像解解决了问题。

关于Java编程中遇到的时区与时间问题总结

转自:http://blog.csdn.net/yeahwell/article/details/8559996

摘自http://www.cnblogs.com/flying5/archive/2011/12/05/2276578.html)(好像已经不能访问了)
最近在编程中遇到了时间与时区相关的问题,整理在这里
  我的程序是一个在Hadoop上运行的分布式程序,从MySQL数据库中取数据,经过处理之后输出
一. 基本概念
  时区 :time zone 1884年国际经线会议规定,全球按经度分为24个时区,每区各占经度15°。
      以本初子午线为中央经线的时区为零时区,由零时区向东、西各分12区,东、西12区都是半时区,共同使用180°经线的地方时。
  CST :China Standard Time UTC+8:00 中国标准时间(北京时间),在东八区
  UTC :Universal Time Coordinated,世界协调时间,又称世界标准时间、世界统一时间。UTC 提供了一种与时区无关(或非特定于时区)的时间。
      世界上的所有时区都可以表示为 UTC 加上或减去一个偏移量。
      因此,UTC是0时区的时间,如北京为早上八点(东八区),UTC时间就为零点,时间比北京时晚八小时
  GMT :Greenwich Mean Time格林威治标准时间,指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
  Unix timestamp :Unix时间戳,或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,
      定义为从格林威治时间(UTC/GMT的午夜)1970年01月01日00时00分00秒起至现在的总秒数。
  可以这么说:
  UTC和GMT几乎是同一概念,两者的区别是GMT是一个天文上的概念,UTC是基于原子钟。
  GMT=UTC
  GMT + 8 = UTC + 8 = CST
  UTC+时间差=本地时间 (时间差东为正,西为负,东八区记为 +0800)

二. 从数据库取数据的过程

mysql>select auction_id,startsfrom auctions where auction_id=88888;
+————-+———————+
| auction_id | starts |
+————-+———————+
| 88888 | 2011-10-24 20:32:58 |
+————-+———————+
1 rowin set (0.00 sec)

mysql> show columnsfrom auctions;
+——————————–+—————+——+—–+———+——-+
| Field | Type |Null | Key| Default | Extra |
+——————————–+—————+——+—–+———+——-+
|starts | datetime | YES | MUL |NULL | |
  可见:数据库的时间字段starts存的是datetime类型,它是一个和时区相关的string(显然:string都是和时区相关的)
  而且数据库是按照CST时区存的时间
程序中从数据库取数据用的sql语句:

mysql>select auction_id,DATE_FORMAT(starts,’%Y%m%d%H%i%S’)from auctions where auction_id=88888;
+————-+————————————+
| auction_id | DATE_FORMAT(starts,’%Y%m%d%H%i%S’) |
+————-+————————————+
| 88888 | 20111024203258 |
+————-+————————————+
1 rowin set (0.00 sec)
  这里只是简单的用DATE_FORMAT函数把datetime类型的starts字段转换为我们需要的格式 %Y%m%d%H%i%S 而已

三、Java代码
  看这样一段转换时间的java代码:

// 将字符串时间转化为秒数(yyyyMMddHHmmss)
staticpublic long getUnixTimestamp(String srcTime)
{
SimpleDateFormat sdf =new SimpleDateFormat(“yyyyMMddHHmmss”);
Date result_date;
longresult_time = 0;
try{
result_date = sdf.parse(srcTime);
//返回的是毫秒数故除以1000
result_time = result_date.getTime()/1000;
}catch (Exception e) {
//出现异常时间赋值为20000101000000
result_time =946684800;
}
returnresult_time;
}
  计算结果:

getUnixTimestamp(“20111204212224”) =1323004944
  说明:java.util.Date中的getTime函数定义如下:
     java.util.Date代表一个时间点,其值为距公元1970年1月1日 00:00:00的毫秒数。所以它是没有时区和Locale概念的。
     public long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
  java中通过如下形式取得当前时间点: 

Date now =new Date(); //这个时间点与本地系统的时区无关
  而正因为其与时区的无关性,才使得我们的存储数据(时间)是一致的(时区一致性)。
  一般的我们将now存储于数据库中,当我们需要展现数据时,将now格式化成想要的格式,如:2011-12-04 21:22:24
  而这个功能一般交由java.text.DateFormat来实现。例如:

SimpleDateFormat sdf =new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
String snow = sdf.format(now);
  我们发现snow是带时间(如2011-12-04 21:22:24)的字符串,那么 2011-12-04 21:22:24 这个时间是哪个时区的时间呢?
  默认情况下,SimpleDateFormat 取得本地系统的时区(我的时区为GMT+8北京),然后按照 pattern(”yyyy-MM-dd HH:mm:ss”)格式化now,
  此时输出的就是 GMT+8 区的时间了。如果想支持国际化时间,则先指定时区,然后再格式化date数据。例如:

SimpleDateFormat sdf =new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
sdf.setTimeZone(TimeZone.getTimeZone(“GMT+8”));
String snow = sdf.format(now);// snow = 2011-12-04 21:22:24
sdf.setTimeZone(TimeZone.getTimeZone(“GMT+7”));
String snow2 = sdf.format(now);// snow2 = 2011-12-04 20:22:24 (可见:东八区比东七区早一个小时)
  另外,你可以通过如下代码修改本地时区信息:

TimeZone.setDefault(TimeZone.getTimeZone(“GMT+8”));
  在windows操作系统中,是通过桌面右下角,也可以指定操作系统的时区。
  在Linux系统中,通过如下命令可以得到当前时区

[admin@localhost]$ date -R
Sun,04 Dec 201122:49:00+0800

四、结论:
  getTime()返回的已经是一个UTC的unix timestamp秒数了,与时区无关;而转换为字符串后,就和时区相关了
  对于这个秒数,不同时区的人,按照自己所在的时区去解析,就可以得到正确的时间了

[admin@localhost]date−d@13230049442011年12月04日星期日21:22:24CST[admin@localhost] date -d@1323004944 2011年12月 04日 星期日21:22:24CST [admin@localhost] date -d@1323004944 -u
2011年12月 04日 星期日13:22:24UTC
  对于涉及到时间转换的程序来说,如果代码里面没有强行指定时区,那就会依赖于操作系统的时区。
  特别是对于分布式程序,如果不同机器上系统时区不一样,那就会出现不一致的数据了!

五、对unix timestamp和时区概念的曲解和误用
  由于历史原因,发现程序中有这样一段代码:

// 将字符串时间转化为秒数(yyyyMMddHHmmss),有8个小时的时差
staticpublic long getLongTime(String srcTime)
{
SimpleDateFormat sdf =new SimpleDateFormat(“yyyyMMddHHmmss”);
Date result_date;
longresult_time = 0;
try{
result_date = sdf.parse(srcTime);
//返回的是毫秒数故除以1000
result_time = result_date.getTime()/1000+ 8 * 3600; // 这里加了八个小时
}catch (Exception e) {
//出现异常时间赋值为20000101000000
result_time =946684800;
}

        returnresult_time;

}
  计算结果:

getUnixTimestamp(“20111204212224”) =1323033744
  显然,这个时间比上面通过 getUnixTimestamp(“20111204212224”) = 1323004944 得到的时间多了8个小时
     1323033744 - 1323004944 = 28800 = 8 * 3600 = 8h
  如果用户将得到的 1323033744 按照自己所在的时区解析后得到的结果是:

[admin@localhost]$ date -d@1323033744
2011年12月 05日 星期一05:22:24CST
  得到了一个完全错误的结果!
  但如果用户将这个 1323033744 按照UTC时区来解析后得到的结果是:

[admin@localhost]$ date -d@1323033744 -u
2011年12月 04日 星期日21:22:24UTC
  为了方便对比,把 1323004944 的解析结果也拿来对比

[admin@localhost]date−d@13230049442011年12月04日星期日21:22:24CST[admin@localhost] date -d@1323004944 2011年12月 04日 星期日21:22:24CST [admin@localhost] date -d@1323004944 -u
2011年12月 04日 星期日13:22:24UTC
  可以看到,这个代码中得到的秒数时间是比UTC的unix timestamp秒数多了八个小时
    这个时间 1323033744 可以理解为北京时区得到的秒数,但是不是unix timstamp时间!
    unix timestamp秒数是与时区无关的,不管是在哪个时区得到的unix timestamp都是一样的
  我们可以验证一下,用北京时间“20111204212224”减去“19700000000000”得到的秒数,就是 1323033744

SimpleDateFormat df =new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
java.util.Date end = df.parse(“2011-12-04 21:22:24”);
java.util.Date start = df.parse(“1970-01-01 00:00:00”);
longdelta = (end.getTime() - start.getTime())/1000;
System.out.println(“delta=”+ delta); // delta=1323033744
  或者用shell命令来求时间差

[admin@localhost]date−d”2011−12−0421:22:24”+1323004944[admin@localhost] date -d”2011-12-04 21:22:24” +%s 1323004944 [admin@localhost] date -d”1970-01-01 0:0:0” +%s
-28800
[admin@localhost]date−d”2011−12−0421:22:24”+1323033744[admin@localhost] date -d”2011-12-04 21:22:24” +%s -u 1323033744 [admin@localhost] date -d”1970-01-01 0:0:0” +%s -u
0
    1323004944 + 28800 = 1323033744
  对于东八区的人来说,1323033744 这个时间按照UTC时间可以解析正确。不能按照自己所在的时区去解析,不然就是错的
  但是如果是东七区的人呢?需要按照UTC时间解析后,自己去减1个小时的时差,so ugly!
  所以,用户在解析1323033744 这个数据的时候:
    (1) 按照UTC时间来解析得到北京时间,然后根据时间差换算成自己所在时区的时间
     (当然,一般都是在北京时区了,所以不用换算,按UTC时间来解析就能得到正确的时间)
    (2) 将这个时间减去8小时得到unix timestamp,然后按照自己所在的时区去解析就可以了
  总结:这段代码是对unix timestamp和时区的曲解和误用。

六、从数据库获取unix timestamp时间
其实从数据库是可以直接获取到unix timestamp时间的

mysql> select auction_id,unix_timestamp(starts) from auctions where auction_id=88888;
+————-+————————+
| auction_id | unix_timestamp(starts) |
+————-+————————+
|88888 | 1319459578 |
+————-+————————+
1row in set (0.02 sec)

七、参考
  java.util.Date http://www.jar114.com/jdk6/zh_CN/api/java/util/Date.html
  关于Java Date和时区的问题 http://blog.163.com/haizai219@126/blog/static/444125552009101924912981/
八、unix时间戳转换工具
http://code.aosoo.com/unixtime

ssm java编程遇到从数据库中查询的时间与存储时间不一致相关推荐

  1. mysql查询转json数据库_json格式数据,将数据库中查询的结果转换为json, 然后调用接口的方式返回json(方式一)...

    调用接口,无非也就是打开链接 读取流 将结果以流的形式输出 将查询结果以json返回,无非就是将查询到的结果转换成jsonObject ================================ ...

  2. java向mysql写入数据慢_通过java代码往mysql数据库中写入日期相关数据少13个小时...

    通过show variables like '%time_zone%'; 查看时区: CST 时区 名为 CST 的时区是一个很混乱的时区,有四种含义: 美国中部时间 Central Standard ...

  3. 获取mysql可行方法_Mysql学习Java实现获得MySQL数据库中所有表的记录总数可行方法...

    <Mysql学习Java实现获得MySQL数据库中所有表的记录总数可行方法>要点: 本文介绍了Mysql学习Java实现获得MySQL数据库中所有表的记录总数可行方法,希望对您有用.如果有 ...

  4. 不同数据库中查询前几条记录的用法(SQL Server/Oracle/Postgresql)

    SQL在不同数据库中查询前几条记录的用法分类 1. orACLE Select * FROM TABLE1 Where ROWNUM<=N 2. INFORMIX Select FIRST N ...

  5. flask查询mysql数据展示_flask再学习-思考之怎么从数据库中查询数据在页面展示!...

    看别人视频觉得很简单,要自己做蒙蔽了!这样子.NO! 1. 流程: 首先要有和数据库连接的驱动!一般有PYMySQL mysqlclient 等 使用扩展Flask-SQLAlchemy 获得orm对 ...

  6. 基于Java线程池读取数据库中数据(学习+运用)

    基于Java线程池读取数据库中数据(学习+运用) 以下是学习内容 Main.java import java.util.concurrent.ArrayBlockingQueue; import ja ...

  7. Java程序向MySql数据库中插入的中文数据变成了问号

    找到mysql的安装目录,修改my.ini文件 (1)如何找到my.ini文件 如果my.ini文件不在MySQL的安装目录下,可能放在隐藏目录,要先去找到ProgramData,(这里要先打开显示隐 ...

  8. mysql查询计算机系信息_在学生管理数据库中查询通信系和计算机系的所有教师信息...

    在学生管理数据库中查询通信系和计算机系的所有教师信息 答:select * from 教师 where 系部代码 in(select 系部代码 from 系部 where 系部名称 in('通信系', ...

  9. oracle时间24小时格式转换,在oracle数据库中查询时间并转为24小时制--------------String转Date类型或者Date转String类型...

    1.在Oracle数据库中查询时间的时候,首先就是把日期从date类型的转化为String类型的. 2.将date类型的转成String类型的,直接调用传入date类型的参数,返回String类型的字 ...

最新文章

  1. 我要是长得和姚明一样高,是不是也能打进NBA?
  2. SAP RETAIL 基于分配表创建采购订单的时候按工厂拆分?
  3. ECMAScript 6中的let和const关键词
  4. [读书笔记]《Head First Servlets JSP》2nd
  5. Uncaught SyntaxError: Unexpected token in body onload
  6. Linux 中 VIM 的使用
  7. 使用meterpreter让没有安装python解释器的肉鸡设备执行任意python程序
  8. 2017.10.11 灾难 失败总结
  9. Python小屋在线练习与刷题软件重要升级
  10. 多位专家解读工业3D打印“叫好不叫座”
  11. 云服务器和虚拟主机的区别
  12. 使用typescript开发集成阿里云短信接口
  13. 如何玩Chrome的小恐龙游戏
  14. bzoj 2959: 长跑 lct+并查集
  15. 海马汽车经销商管理系统技术解析(四)保养管理
  16. 技术经理成长复盘-我是什么样的人
  17. linux图片编辑工具,如何在Ubuntu 18.04中安装Pinta图像编辑器
  18. opencv滤波函数简介
  19. ISP图像处理—紫边Purple Fringing
  20. 企业付款到零钱(微信)

热门文章

  1. Apache Calcite 实现方言转换
  2. 搜狗搜索曝光“搜狗商店” 人工智能概念产品可提升人类能力
  3. android金币动效_打造高逼格Android个人中心动效UI
  4. 阿里“中台”概念结合环保行业架构的思考
  5. i tell you 微软各种 操作系统 应用程序 开发工具 下载
  6. 常见问题汇总:FLUENT文件导出为CAS或MSH
  7. Android 之路30---UI基础控件
  8. 基于JAVA-英杰学堂网上教学平台-计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  9. apollo配置中心之--spring boot如何加载apollo
  10. 【转】STM32 定时器 输出比较模式和PWM输出模式的区别