zoukankan      html  css  js  c++  java
  • 关于时间的梳理

    1. 明确几个概念

    • UTC: Universal Time Coordinated 协调世界时,又称世界标准时间,比GMT更精确
    • GMT: Greenwich Mean Time 格林尼治平均时
    • 时间戳 int类型,将GMT/UTC的1970年01月01日00时00分00秒作为起始值进行计算,得到的总秒数就是这个Unix时间戳,不分地区。

    UTC和GMT都与英国伦敦的本地时相同,所以程序中UTC与GMT没什么不同。但是实际上,GMT 是一个时区,而 UTC 是一个时间标准。

    2. ISO_8601日期格式标准

    ISO 8601的标准格式是:YYYY-MM-DDTHH:mm:ss.sssZ,分别表示:

    • YYYY:年份,0000 ~ 9999
    • MM:月份,01 ~ 12
    • DD:日,01 ~ 31
    • T:分隔日期和时间
    • HH:小时,00 ~ 24
    • mm:分钟,00 ~ 59
    • ss:秒,00 ~ 59
    • .sss:毫秒
    • Z:时区,可以是:Z(UFC)、+HH:mm、-HH:mm

    T

    T 也可以用空格表示,但是这两种表示有点不一样,T 其实表示 UTC,而空格会被认为是本地时区(前提是不通过 Z 指定时区)。

    Z

    Z 用来表示传入时间的时区(zone),不指定并且没有使用 T 分隔而是使用空格分隔时,就按本地时区处理,比如下面的例子:

    3. JavaScript中的时间

    Data()构造时间的方法有下面几种:

    • new Date(); // 当前时间
    • new Date(value); // 自 1970-01-01 00:00:00 UTC 经过的毫秒数
    • new Date(dateString); // 时间字符串
    • new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
    new Date();  
    new Date(1000 * 1)
    new Date('Thu Jan 01 1970 00:00:00 GMT+0800 (CST)')
    new Date(1970, 0, 1, 0, 0, 0)
    

    Javascript则精确到毫秒数。用dateObject.getTime()来获得当前时间戳,用Date.parse(datestring)来生成一个时间戳。

    使用谷歌浏览器的控台,探究一下

    在浏览器中直接new一个date对象,因为我们处于UTC+0800的时区,所以控制台给我们打印出来的时间是GMT+0800的时间

    new Date()
    Thu Feb 08 2018 17:25:13 GMT+0800 (中国标准时间)
    

    通过日期字符串new一个Date对象,输入的时间字符串是2018-02-08 00:00:00,没有带ISO标准的“T”字母,因此浏览器认为我们想输入的是当地时间

    new Date("2018-02-08 00:00:00")
    Thu Feb 08 2018 00:00:00 GMT+0800 (中国标准时间)
    

    2018-02-08T00:00:00+0800 代表UTC+0800时区2月8日0时0分,2018-02-08T00:00:00-0800 代表UTC-0800时区2月8日0时0分,在控制台中显示分别如下

    new Date("2018-02-08T00:00:00+0800")
    Thu Feb 08 2018 00:00:00 GMT+0800 (中国标准时间)
    new Date("2018-02-08T00:00:00-0800")
    Thu Feb 08 2018 16:00:00 GMT+0800 (中国标准时间)
    

    4. MySql中的时间

    MySQL 中和时间相关的数据类型主要包括:YEAR、TIME、DATE、DATETIME、TIMESTAMP。

    DATE、YEAR、TIME 比较简单,大概总结如下:

    名称 占用字节 取值
    DATE 3 字节 1000-01-01 ~ 9999-12-31
    YEAR 1 字节 1901 ~ 2155
    TIME 3 字节 -838:59:59 ~ 838:59:59

    注:TIME 的小时范围可以这么大(超过 24 小时),是因为它还可以用来表示两个时间点之差。

    DATEIME vs TIMESTAMP
    我们主要来说明下 DATETIME 和 TIMESTAMP,可以做下面的总结:

    名称 占用字节 取值 受 time_zone 设置影响
    DATETIME 8 字节 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
    TIMESTAMP 4 字节 1970-01-01 00:00:00 ~ 2038-01-19 03:14:07

    第一个区别是占用字节不同,导致能表示的时间范围也不一样。

    第二个区别是 DATETIME 是“常量”,保存时就是保存时的值,检索时是一样的值,不会改变;而 TIMESTAMP 则是“变量”,保存时数据库服务器将其从time_zone 时区转换为 UTC 时间后保存,检索时将其转换从 UTC 时间转换为 time_zone 时区时间后返回。

    创建数据表:

    CREATE TABLE `tests` (
        `id` INTEGER NOT NULL auto_increment , 
        `datetime` DATETIME, 
        `timestamp` TIMESTAMP, 
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    

    连接到数据库服务器后,可以执行 SHOW VARIABLES LIKE '%time_zone%' 查看当前时区设置。类似下面这样的结果:

    Variable_name Value
    system_time_zone CST
    time_zone SYSTEM

    说明我目前时区是 CST(China Standard Time),也就是东八区。

    INSERT INTO tests (id, datetime, timestamp) VALUES (DEFAULT, '2000-01-01 00:00:00', '2000-01-01 00:00:00');

    检索

    id datetime timestamp
    1 2000-01-01 00:00:00 2000-01-01 00:00:00

    如果我们先将 time_zone 设置为一个不同的值后再进行检索就会发现不同的结果:

    SET time_zone = '+00:00';
    

    再次检索

    id datetime timestamp
    1 2000-01-01 00:00:00 1999-12-31 16:00:00

    5. Vue(ElementUI) + Laravel 的前后端数据的处理

    ElementUI前端初始化数据的时候,

    参数 说明 类型 可选值 默认值
    default-value 可选,选择器打开时默认显示的时间 Date 可被new Date()解析
    default-time 范围选择时选中日期的默认具体时刻 string[] 数组,长度为 2,每项值为字符串,形如12:00:00,第一项指定开始日期的时刻,第二项指定结束日期的时刻,不指定会使用时刻 00:00:00
    value-format 可选,绑定值的格式。不指定则绑定值为 Date 对象 string 见日期格式

    采用默认格式,参照官方文档

    <script>
      export default {
        data() {
          return {
            pickerOptions2: {
              shortcuts: [{
                text: '最近一周',
                onClick(picker) {
                  const end = new Date();
                  const start = new Date();
                  start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                  picker.$emit('pick', [start, end]);
                }
              }]
            },
            value3: [new Date(2000, 10, 10, 10, 10), new Date(2000, 10, 11, 10, 10)],
            value4: ''
          };
        }
      };
    </script>
    

    传递给时间控件的值,可以通过new Date()初始化,
    通过time.getTime()获取时间戳,进行时间的计算,
    再通过time.setTime()转换成new Date()类型。

    这里需要注意的是,time.getTime()获取的是毫秒值。

    如果前端不加任何其它处理,我们后端获取的值是UTC时间格式。

     dd($request->input('t_s'),date('Y-m-d H:i:s', strtotime($request->input('t_s'))));
    
    "2018-02-08T02:30:32.743Z"
    "2018-02-08 10:30:32"
    

    通过转换可以得到mysql数据库中(DATEIME或TIMESTAMP格式),然后进行存储。

    6. php(Laravel)中时区问题

    1. 配置Laravel时区

    我们在config/app.php中配置好找到timezone, 修改成如下时区即可,如果时间正确,就可以不用管第二步

    'timezone' => 'PRC',
    
    1. 修改php.ini中的时区

    找到PHP配置文件(php.ini,根据自己情况查找)

    date.timezone = PRC
    
    1. 不使用框架,没有提供配置时区功能

    Laravel提供给我们设置时区的配置,如果你没有使用框架,我们可以在系统初始化的时候设置。

    ini_set('date.timezone','PRC');  
    //或
    date_default_timezone_set("PRC"); 
    

    这样就可以解决时区问题

    参考资料

    关于“时间”的一次探索

  • 相关阅读:
    Yii2 的 updateAll 方法参数详解
    Yii2 数据库查询汇总
    Git常见报错
    git rebase篇
    在 Yii 2.0 上,使用 updateAll() 更新表列值为同一表的另一列值的实现
    Git从其他分支merge个别文件
    Git cherry-pick 复制多个commit
    Git 删除某次提交(某个commit)的方法
    多进程记录
    python3安装Crypto过程
  • 原文地址:https://www.cnblogs.com/redirect/p/8658537.html
Copyright © 2011-2022 走看看