应用开发-对时间的关注

应用开发-对时间的关注

​ 时间,在应用软件开发中是一个至关重要的因素。良好的时间一致不仅关乎项目的进度,还直接影响着软件的稳定性和用户体验。

《时间的来龙去脉 & GMT、UTC、CST、时间戳、NTP》这篇文章中介绍了时间、UTC、GMT、CST、时间戳、时区等概念。

对于服务器系统时间的关注

Linux 系统中的时间主要有以下几种:

  1. 系统时间(System Time):
    • 定义: 系统时间是指计算机内部的时钟,表示当前操作系统内核维护的时间。它通常是从硬件时钟获取的,可以是协调世界时(UTC)或本地时间的形式。
    • 特点: 系统时间是动态变化的,会随着操作系统的运行而不断更新。
  2. 本地时间(Local Time):
    • 定义: 本地时间是当前所在时区内的时间,是以系统时间为基础进行时区转换得到的。它是用户通常所看到的时间,考虑了时区的影响。
    • 关系: 本地时间的显示和处理通常基于系统时间,通过时区转换来适应用户所在的地理位置。
  3. UTC 时间(Coordinated Universal Time):
    • 定义: UTC 是协调世界时,表示世界标准时间。它是全球通用的时间标准,不考虑时区的影响,通常用于在不同地区和系统之间进行统一的时间表示。
    • 关系: 本地时间和 UTC 时间之间的差值通常由系统时钟和时区设置确定。
  4. 硬件时钟(Hardware Clock / RTC):
    • 定义: 硬件时钟是计算机硬件上的一个时钟,通常是一个芯片上的实时时钟。它可以是设置为UTC或本地时间,且通常不受操作系统影响,即使系统关机,硬件时钟仍能持续运行。
    • 配置: 硬件时钟的设置可以通过计算机的BIOS或UEFI进行配置,决定其是使用UTC还是本地时间。
  5. 文件时间(File Time):
    • 定义: 文件时间是指文件和目录的创建时间、修改时间等时间戳。在Linux系统中,你可以通过 ls -l 命令查看文件的时间戳信息。
    • 应用: 文件时间对于文件的管理和跟踪修改非常有用,可以用于确定文件的版本、修改历史等。

截止到本文编写时间结点,中国境内是不使用夏令时这个制度的。

服务器时间的初始设置(思考/建议)

​ 对于服务器的时间上,一般开发默认使用UTC(世界标准时间)为硬件时间,再加上自身所处的时区为本地时间,在国内一般服务器以Asia/Shanghai为时区。

​ 简单来说,初始化服务器时间的步骤如下:

  1. 将硬件时间设置为UTC格式。
  2. 设置服务器时区为本地时区(例如,Asia/Shanghai)。
  3. 使用网络时间协议(NTP)进行同步,或手动进行时间调整。
  4. 确保本地时间与系统时间保持同步。

这样的设置可以有效避免时区混淆,确保服务器时间的正确性。

查看当前时间和时区设置

timedatectl

设置硬件时钟为 UTC

sudo timedatectl set-local-rtc 0

设置时区为中国东八区

sudo timedatectl set-timezone Asia/Shanghai

这将设置系统时区为中国标准时间(CST,UTC+8)。

查看设置是否生效

timedatectl

###############################
      Local time: 二 2024-01-02 13:51:57 CST   当前本地时间,即时区为 Asia/Shanghai(中国标准时间 CST,UTC+8)的时间。
  Universal time: 二 2024-01-02 05:51:57 UTC   协调世界时(UTC)时间,表示全球标准时间,与时区无关。
        RTC time: 二 2024-01-02 05:48:45       RTC 时间,即硬件时钟(Real-Time Clock)的时间。
       Time zone: Asia/Shanghai (CST, +0800)   时区设置,这里是 Asia/Shanghai(中国标准时间 CST,UTC+8)。
     NTP enabled: no         是否启用网络时间协议(NTP),这里显示为 "no",表示没有启用 NTP。
NTP synchronized: no        是否与 NTP 服务器同步,这里显示为 "no",表示当前没有与 NTP 服务器同步。
 RTC in local TZ: no        是否硬件时钟在本地时区,这里显示为 "no",表示硬件时钟不受本地时区影响,可能是设置为 UTC 时间。
      DST active: n/a      夏令时是否激活,这里显示为 "n/a",表示不适用于当前设置。夏令时(Daylight Saving Time)通常在一些地区会在夏季时激活,以调整时钟向前或向后一小时。

确保 “RTC in local TZ” 为 “no”,而 “Time zone” 为 “Asia/Shanghai”。

将系统时间同步到硬件时钟

sudo hwclock --systohc

这个命令将当前系统时间写入硬件时钟。

最后查看时间设置

date
#2024年 01月 02日 星期二 14:00:50 CST
hwclock --show
#2024年01月02日 星期二 14时01分12秒  -0.460377 秒

数据库时间的关注

启动参数&系统变量

在MySQL中,可以通过启动参数和系统变量来配置时区。

  • 启动参数: 使用default-time-zone参数在MySQL启动时指定时区。

    # 方法1:在启动命令中添加
    mysqld --default-time-zone='+08:00' &
    
    # 方法2:在配置文件中添加
    [mysqld]
    default-time-zone='+08:00'
    
  • 系统变量: 通过time_zone系统变量控制时区。

    -- 查看时区配置
    mysql> show global variables like '%time%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | CST    |
    | time_zone        | +08:00 |
    +------------------+--------+
    2 rows in set (0.00 sec)
    
    -- 修改全局时区,所有已经创建的、新创建的session都会被修改
    set global time_zone='+00:00';
    
    -- 修改当前session时区
    set session time_zone='+00:00';
    

可用的时区值包括’SYSTEM’、相对于UTC的偏移(如’+08:00’或’-6:00’)、时区名字(如’Asia/Shanghai’),需要先导入时区信息到mysql库中。

时区影响

时区的设置会影响以下两个方面:

  1. NOW()和CURTIME()函数的返回值: 受当前session的时区影响,包括INSERT语句和字段的DEFAULT CURRENT_TIMESTAMP属性。

    sqlCopy codemysql> set time_zone='+08:00';
    mysql> select now(), CURTIME();
    
    mysql> set time_zone='+00:00';
    mysql> select now(), CURTIME();
    
  2. timestamp数据类型字段的存储: timestamp会存储当前session的时区信息,读取时根据当前session的时区进行转换,而datetime则不受时区影响。

    sqlCopy codemysql> set time_zone='+08:00';
    mysql> create table t(ts timestamp, dt datetime);
    mysql> insert into t values('2021-12-02 16:45:39','2021-12-02 16:45:39');
    
    mysql> set time_zone='+00:00';
    mysql> select * from t;
    

关于时区的建议

  1. MySQL安装规范: 在my.cnf中写入default-time-zone='+08:00'(8.0版),对于其他地区,确认并设置对应的时区。
  2. 解决Java应用时间差问题: JDBC参数中设置serverTimezone属性,确保MySQL全局时区设置为’+08:00’。
  3. 修改MySQL时区不影响已存储数据: 仅对timestamp数据类型读取有影响,建议在开发规范中使用datetime类型。
  4. 迁移数据时防止时区错误: 使用mysqldump导出时,确保设置--skip-tz-utc参数,或者保持导出和导入时使用相同的时区。

JAVA时间的关注

JAVA应用时间来源

​ 在Java应用程序中,通过JAR文件启动后获取的时间通常是依赖于JVM(Java虚拟机)的时间设置,而不是直接使用Linux的本地时间或硬件时间。(tomcat也是一样,因为该应用在Tomcat中作为一个独立的Java虚拟机进程运行。)

​ JVM(Java Virtual Machine)的时间通常是从底层操作系统获取的系统时间。JVM利用系统调用获取操作系统的当前时间,这通常涵盖了硬件时钟和操作系统时钟的信息。

JVM时间的设置

​ Java 虚拟机(JVM)通常会默认使用系统的时区设置。它会通过查找底层操作系统的时区设置来确定默认时区。

1.服务器的时区设置一致,则默认启动

2.在启动参数中携带-Duser.timezone,该系统属性用于设置用户的时区。

java -Duser.timezone=Asia/Shanghai -jar your-application.jar

常见的做法是将JVM的时区设置在启动脚本或配置文件中进行统一配置。

3.sun.util.calendar.ZoneInfoFile

这个系统属性指定了时区信息的文件路径,影响JVM如何加载时区数据。一般情况下,你无需手动设置这个属性,因为JVM会自动查找时区信息。

4.user.country, user.language

这两个系统属性也可能影响某些时间和日期的处理,尽管它们与时区设置关系较小。

总结:

  1. 服务器系统时间的关注:
    • Linux系统中有多种时间概念,包括系统时间、本地时间、UTC时间、硬件时钟、文件时间等。
    • 初始设置时,建议将硬件时间设置为UTC格式,时区设置为本地时区(例如,Asia/Shanghai),并使用NTP进行同步。
  2. 数据库时间的关注:
    • MySQL中可以通过启动参数和系统变量配置时区,影响NOW()、CURTIME()函数和timestamp字段的行为。
    • 建议在MySQL安装规范中设置默认时区,处理Java应用时间差问题,并在开发规范中使用datetime类型以减少时区影响。
  3. Java应用时间的关注:
    • JVM的时间通常从底层操作系统获取,可以通过启动参数(-Duser.timezone)统一设置时区。
    • 常见做法是在启动脚本或配置文件中配置JVM的时区,确保与服务器一致。
  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的小庄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值