日期时间存入数据库会差一天?

Date型的数据插入数据库时间被改变的一些问题记录。

一、插入数据库总是早一天

Date型的数据插入数据库,发现总是早一天。

  • 问题原因:是由于JDBC的时区和当前不一致导致的。
    mysql默认的是美国的时区,而我们中国大陆要比他们迟8小时,应该采用+8:00格式

  • 查看数据库时区
    show variables like "%time_zone";
    在这里插入图片描述

  • 解决方式:在JSBC连接的时候与数据库时区保持一致,java默认的应该是系统时区或者是世界时
    如果数据库时区是 CST 或者 世界时(GMT/UT)+8,那么JDBC连接参数中要加入serverTimezone=GMT%2B8,如下

dbc:mysql://localhost:3306/boo?useUnicode=ture&characterEncoding=UTF-8&serverTimezone=GMT%2B8

二、回显到前端会早一天

问题原因:依旧是时区问题,导致数据库跟java虚拟机读出来的时间不一致
应针对字段进行时区处理,例如 @JsonFormat注解中就有设置时区的属性 – timezone

/** 创建时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date createTime;

三、夏令时问题

这个问题就是就算是你时区保持一致了,但是在某些时间还是会出现时间不一致的情况

  • 问题原因:
    根据夏令时规定,在规定的时间段内,时针会自动回拨一小时(详见下方扩展)。
    那么当你用Date格式记录日期的时候,例如出生日期“1991-06-16”(此日期在夏令时内),Date中记做‘‘1991-06-16 00:00:00’’,那么插入数据库时日期就会被最终记录成 “1991-06-15 23:00:00”,再次读出来的话就是“1991-06-15”,提前了一天…

解决:
这个问题由于人们认知与实际规定的差异,所以基本无解。好在夏令时实行时间是1986 - 1992年之间,一般项目中涉及这个时间段的只有生日,而生日一般记做 yyyy-MM-dd , 根据夏令时的特性,将生日字段特殊处理 ---- 默认给时间+1小时,即 1996-10-13 在后台处理为 1996-10-13 01,这样在存入数据库时就算因为夏令时时针回拨1小时,那生日依旧是 1996-10-13 00 ,这样就不会出现生日提前一天的情况了。注意这种情况,生日在取得时候取到dd,存的时候+1h,否则累加hh会出错。

扩展:

夏令时

夏令时,(Daylight Saving Time:DST),也叫夏时制,又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。全世界有近110个国家每年要实行夏令时。
1986年4月,中国中央有关部门发出“在全国范围内实行夏时制的通知”,具体做法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。

  • 关键内容
    • 夏令时实行年份: 1986 - 1992 之间,不包括1992
    • 时间为:每年从四月中旬第一个星期日的凌晨2时到九月中旬第一个星期日的凌晨2时整
    • 调整:时针往前回拨一小时,即 1986-05-04 00:00:00 回拨一小时 为 1986-05-03 23:00:00、
      1986-05-04 01:00:00 回拨一小时 为 1986-05-04 00:00:00
    • 其时间分别是:
      1986年:05-04 02 ~ 09-14 02
      1987年:04 -12 02 ~ 09-13 02
      1988年:04 -10 02 ~ 09-11 02
      1989年:04 -17 02 ~ 09-17 02
      1990年:04 -15 02 ~ 09-16 02
      1991年:04 -14 02 ~ 09-15 02
在Go语言中,我们可以利用`net/http`库进行网页抓取,`time`库处理日期范围,`os`库操作文件,以及`database/sql`和相关的ORM库(如`sqlx`、`gorm`等)来存储数据到数据库。以下是简单的步骤: 1. **设置HTTP客户端**: 使用`http.Client`来发送请求并获取HTML内容。 ```go package main import ( "io/ioutil" "net/http" "time" ) ``` 2. **解析日期范围**: 定义起始日期和结束日期,通常会从URL或者其他来源获取。 ```go start := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC) // 示例 end := time.Now().UTC() ``` 3. **创建日期范围的循环**: 使用`time.Time`类型的切片来生成指定日期范围内的每一天。 ```go dateRange := make([]time.Time, 0, int((end.Sub(start))/24)) // 一天24小时 for start.Before(end) { dateRange = append(dateRange, start) start.AddDate(0, 0, 1) // 向后加一天 } ``` 4. **爬取文件**: 遍历日期范围,构造URL,然后用`http.Get`请求每个URL。如果响应码是200,说明文件可用,再读取其内容。 ```go fileURLs := []string{} for _, day := range dateRange { url := "https://example.com/files/" + day.Format("2006_01_02") // 根据实际网站结构调整URL resp, err := http.Get(url) if err == nil && resp.StatusCode == http.StatusOK { body, _ := ioutil.ReadAll(resp.Body) fileURLs = append(fileURLs, url) } resp.Body.Close() } // 确保处理错误 if err != nil { // 错误处理 } ``` 5. **保存文件到数据库**: 使用ORM库将文件URL插入到数据库表中。 ```go db, err := sql.Open("your_database", "your_connection_string") if err != nil { // 数据库连接错误 } defer db.Close() for _, fileURL := range fileURLs { _, err = db.Exec("INSERT INTO files (url, created_at) VALUES (?, ?)", fileURL, day) if err != nil { // 数据插入错误 } } ``` 注意这只是一个基本示例,实际应用中可能需要处理更多的细节,比如处理下载失败、分页请求、异常处理以及数据库事务等。同,为了遵守网站的robots.txt规则和法律法规,确保在合法范围内进行网络爬虫。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值