[Linux/MYSQL/Java] 时间与时区(UTC/GMT/CST/Timestamp)

  • MYSQL JDBC 版本 : 8.0.28
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>${mysql.jdbc.version}</version>
</dependency>
  • MYSQL 版本:MYSQL 5.7.38-221001-log

基本概念

GMT(格林尼治标准时间、世界时间) 与 UTC(协调世界时间)

GMT(格林尼治标准时间、世界时间) 【不推荐】、UTC(协调世界时间) 【推荐】

  • ‌GMT(Greenwich Mean Time,格林威治标准时间)‌:GMT是基于地球自转对恒星的观测来定义的时间标准,将地球划分为24个时区。

它以英国伦敦郊区的格林尼治天文台为参考点,当太阳在每年的某一天通过格林尼治子午线的时刻为中午12点。
GMT曾经是国际上主要的时间标准,但由于地球自转速度会有微小的变化,GMT并不是一个非常精确的时间标准

  • ‌UTC‌(Coordinated Universal Time,协调的世界时间):UTC是在GMT的基础之上,基于原子时钟的测量,让世界各地的时差保持一致。

这些原子时钟的精度非常高,几乎不受环境因素影响。
UTC由国际时间标准组织(法国人发起)维护,并通过增加或减少闰秒来校正地球自转速度的微小变化,以保持与GMT的一致性。)维护,并通过增加或减少闰秒来校正地球自转速度的微小变化,以保持与GMT的一致性。
UTC是
当前国际上最广泛使用的时间标准**,被用于全球的时间服务、互联网、航空等领域。
UTC比GMT更为精确,误差值必须保持在0.9秒以内。

-- mysql 5.7
> set time_zone = 'UTC';
> select CURTIME()
CURTIME()|
---------+
 12:53:29|

> set time_zone = 'GMT';
> select CURTIME()
CURTIME()|
---------+
 12:53:29|
  • 时间偏移的对比

由于地球自转轴的倾斜和地球公转轨道的椭圆形状,地球上不同地区的太阳高度角和白昼时间会有所不同。
这导致了GMT在跨越经度较大的地区时,时间会出现较大的偏差。
UTC则能较好地反映地球的真实形状,因此在跨越经度较大的地区时,时间偏差较小。

  • 在实际应用中,UTC通常被认为是更现代和精确的时间标准,尤其是在需要高精度时间的情况下,UTC是首选的时间标准。

尽管GMT和UTC之间通常差异很小,但在需要高精度的时间应用中,UTC更为适用。
在互联网中,UTC时间系统被应用与许多互联网和万维网的标准中,网络时间协议就是协调世界时(UTC)的一种使用方式。
在军事中,UTC时区会使用Z来表示。又由于Z在无线电联络中使用Zulu作代称,协调世界时也会被称为Zulu time

yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
  • 推荐文献

可直观地了解GMT和UTC的区别

美国时间(American Time) : 东部EST/中部CST/山地MST/西部(太平洋)PST

一般被认为是美国本土及2个海外州的时间。
美国本土横跨西五区至西八区,共4个时区,每个时区对应一个标准时间。从东向西分别为:

  • 东部时间(EST)西五区时间
  • 中部时间(CST)西六区时间
  • 山地时间(MST)西七区时间
  • 太平洋时间(西部时间)(PST)(西八区时间)

2个海外州为阿拉斯加州夏威夷州,时间分别是:

  • 阿拉斯加时间(AKST)(西九区时间)
  • 夏威夷时间(HST)(西十区时间)

因此,美国时间包括6个时区,每个时区对应一个标准时间,按照“东早西晚”的规律,各递减一小时。
美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时,夏令时比正常时间快一小时。

UTC+10 夏莫罗标准时区
UTC-11 美属萨摩亚标准时区
UTC-10HST夏威夷-阿留申标准时区
UTC-9AKST阿拉斯加标准时区
UTC-8PST太平洋标准时区
UTC-7MST山地标准时区
UTC-6CST中部标准时区
UTC-5EST东部标准时区
UTC-4AST大西洋标准时区

CST(中国、美国、澳大利亚、古巴的标准时间)

  • CST时间(默认指,China Standard Time, 中国标准时间)

在时区划分上,属东八区,比协调世界时早8小时,记为UTC+8。
CST时间:China Standard Time,即中国标准时间。在时区划分上,属东八区,比协调世界时早8小时,记为UTC+8。

恶心的CST问题(4个同名CST时区/mysql/java/...)

  • 结论:重新配置MYSQLsystem_time_zone为非CST,或 修改time_zone改成非SYSTEM

  • CST同名的有4个时区

Central Standard Time (USA) UT-6:00 美国标准时间
Central Standard Time (Australia) UT+9:30 澳大利亚标准时间
China Standard Time UT+8:00 中国标准时间
Cuba Standard Time UT-4:00 古巴标准时间

  • 这个不仅仅是重名的问题,而且在某些情况下会造成bug,详细看另一篇博文。这里简单说一下:

CST 时区是个非常坑的概念,因为在 mysql 里被理解为 China Standard TimeGMT+8
但在Java里被理解为Central Standard Time (USA)(GMT-6),这就是造成坑的原因。

  • 解决办法:mysql就别用CST时区,改成 +08:00 以免造成误解。(肯定改mysql啦,你改得了jdk源码吗?)
  • 如果mysqltime_zone变量是SYSTEM,而system_time_zoneCST的值,system_time_zone的CST这个字符串会造成bug。
  • mysql jdbc

mysql的jdbc驱动的代码里会设置时区,这个时区是通过 TimeZone.getTimeZone(canonicalTimezone) 读取,其中 canonicalTimezone 是字符串, TimeZone.getTimeZone("CST") 返回-6时区,即美国的时区。

  • Java中的CST时区问题坑

java.util.TimeZone

TimeZone.getTimeZone("Asia/Shanghai").getRawOffset() : 28800000 (单位:毫秒,即 +8h,即 中国东八区)

TimeZone.getTimeZone("CST").getRawOffset() : -21600000 (单位:毫秒,即 -6h,即美国西六时区,代表城市芝加哥、新奥尔良与北京时间有15小时的时差)

java.text.SimpleDateFormat / java.util.TimeZone

@Test
public void test() {
	String str = "1989-05-29 00:00:00";
	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	// 不加时区有问题 :            date : Mon May 29 00:00:00 CDT 1989       | ts : 612370800000 (个人理解,等效于: 1989-05-29 00:00:00 UTC+8)
	// 加时区(GMT+08)后,修正结果 : date : Sun May 28 23:00:00 GMT+08:00 1989 | ts : 612370800000 (个人理解,等效于: 1989-05-29 00:00:00 UTC+8) | 不兼容中国夏令时
	// 加时区(UTC+08)后,修正结果 : date : Sun May 28 15:00:00 GMT 1989       | ts : 612370800000 (个人理解,等效于: 1989-05-29 00:00:00 UTC+8)
	// 加时区(UTC)后,修正结果 :    date : Sun May 28 15:00:00 UTC 1989       | ts : 612370800000 (个人理解,等效于: 1989-05-29 00:00:00 UTC+8)
	// 加时区(Asia/Shanghai)后,修正结果 :  date : Mon May 29 00:00:00 CDT 1989 | ts : 612370800000 (个人理解,等效于: 1989-05-29 00:00:00 UTC+8) | 兼容中国夏令时
	//TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));//"GMT+08" / "UTC+08" / "UTC" / "Asia/Shanghai"

	Date date = simpleDateFormat.parse(str);
	System.out.println("date : " + date.toString() + " | ts : "+ date.toInstant().toEpochMilli());
}

打印获取到日期,发现两个日期存在了时区的不同,一个为CDT,一个为CST

  • CDT:为夏令时时间(中华人民共和国在1986年~1991年实行了夏令时制度,每年夏令时实行时间如下:

1986年5月4日至9月14日(1986年因是实行夏令时的第一年,从5月4日开始到9月14日结束)
1987年4月12日至9月13日
1988年4月10日至9月11日
1989年4月16日至9月17日
1990年4月15日至9月16日
1991年4月14日至9月15日

  • CST:为美国、澳大利亚、古巴或中国的标准时间。

  • CST的时间和CDT的时间是相差了13个小时。

  • 解决方法:需根据实际情况,选择使用何时的时区

常用的GMT+8的时区设置,并不兼容夏令时。
使用TimeZone = Asia/Shanghai,则会兼容夏令时。
当mysql的url,修改为配置serverTimezone=Asia/Shanghai,可解决插入数据库时间错误问题
当java应用返回给前端的时候,设置JsonFormattimeZone的时候,也需要使用此配置:@JsonFormat(timezone = “Asia/Shanghai”, pattern = “yyyy/MM/dd”)这样才可以保证前端的数据展示正确。

(UNIX)时间戳

  • UNIX时间戳(timestamp):计算机中的UNIX时间戳,是以GMT/UTC时间1970-01-01T00:00:00为起点,到当前具体时间的秒数(不考虑闰秒)。

这样做的目的,主要是通过“整数计算”来简化计算机对时间操作的复杂度。

时间单位换算

  • 1分钟(min) = 60秒(s)
  • 1秒(s) = 1000 毫秒(ms)
  • 1毫秒(ms) = 1000微秒(μs)
  • 1000微秒(μs) = 1000 纳秒(ns)

Linux 的时间操作

获取时间

  • 获取本地时间
root@xxx:~# date
Wed Nov 27 09:12:59 PM CST 2024

root@xxx:~# date +'%Y-%m-%d %H:%M:%S.%s'
2024-11-27 21:13:20.1732713200
  • 获取UTC时间
root@xxx:~# date +'%Y-%m-%d %H:%M:%S.%s' -u
2024-11-27 13:14:04.1732713244

root@xxx:~# date; date -u
Wed Nov 27 09:14:46 PM CST 2024
Wed Nov 27 01:14:46 PM UTC 2024

可见,与本地时间(UTC+8)确实相差8小时

  • date命令的参数
  • %T 时间(24小时制)(hh:mm:ss)
  • %y 年的最后两个数字( 1999则是99)
  • %Y 年(例如:1970,1996等)
  • %m 月(01..12)
  • %d 日、一个月的第几天(01..31)
  • %D 日期(mm/dd/yy)
  • %j 一年的第几天(001..366)
  • %H 小时(00..23)
  • %M 分(00..59)
  • %S 秒(00..59)
  • %s 从1970年1月1日00:00:00到目前经历的秒数
  • %N 从1970年1月1日00:00:00到目前经历的纳秒
> date +%s.%N
1715409477.512093100

> DATE_STR=$(date +'%Y-%m-%d %H:%M:%S')
> DATE_STR=$(date +'%Y%m%d%H%M%S')
> echo $DATE_STR
2023-04-15 21:08:35

# 字符串拼接方式(秒级时间戳 + 毫秒级的3位)
> echo $(date +%s)$(( "$(echo  $(date +%N) | awk '{print $0+0}' )/1000000" ))
> echo $(date +%s)$( echo $(( "$(echo  $(date +%N) | awk '{print $0+0}' )/1000000" )) | awk '{printf("%03d\n",$0)}' )
1715409575298

# 字符串拼接方式(秒级时间戳 + 毫秒级的3位) + 字符串转为数值
> echo $( expr $((  $(date +%s)$( echo $(( "$(echo  $(date +%N) | awk '{print $0+0}' )/1000000" )) | awk '{printf("%03d\n",$0)}' ) )) \* 1 )
1715409575298

获取时间戳

获取时间戳,不管是UTC时间还是北京时间 时间戳都是一样
是以GMT/UTC时间1970-01-01T00:00:00为起点,到当前具体时间的秒数(不考虑闰秒)

root@xxx:~# date +%s;date +%s -u
1732713357
1732713357

将【时间戳】转为时间字符串

[root@chb1 ~]# date -d @1682137164
Sat Apr 22 12:19:24 CST 2023

[root@chb1 ~]# date -d @1682137164 +'%Y-%m-%d %H:%M:%S.%s'
2023-04-22 12:19:24.1682137164

[root@chb1 ~]# date -d @1682137164 +'%Y-%m-%d %H:%M:%S.%s' -u
2023-04-22 04:19:24.1682137164

获取当前系统时区

  • 可以通过 date +%Z 或者 timedatectl
root@xxx:~# date +%Z
CST

root@xxx:~# date +%z
+0800

root@xxx:~# timedatectl
               Local time: Wed 2024-11-27 21:11:04 CST
           Universal time: Wed 2024-11-27 13:11:04 UTC
                 RTC time: Wed 2024-11-27 13:11:04
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

查看时区配置文件:/etc/localtime

root@xxx:~# ls -l /etc/localtime
lrwxrwxrwx 1 root root 33 Jul  7 12:11 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai

Java 的时间操作

java.time.Instant : 时间戳常量

  • java.time.Instant

Java 8 新增 API
所谓的 Instant 类代表的是某个时间(有点像 java.util.Date),它是精确到纳秒的(而不是象旧版本的Date精确到毫秒)。
如果使用纳秒去表示一个时间则原来使用一位Long类型是不够的,需要占用更多一点的存储空间。
实际上,Instant的内部是由两个Long字段组成:

  • 第1个部分保存的是自标准Java计算时代(就是1970年1月1日开始)到现在的秒数
  • 第2部分保存的是纳秒数(永远不会超过999,999,999)。
  • API: long toEpochMilli()

用于将此Instant转换为自1970-01-01T00:00:00Z以来的Java时期标准格式的毫秒数

//获得当前时间 
Instant instant = Instant.now();
Long ms = instant.toEpochMilli(); //1732774113958
  • java.util.Date/Calendar转换为Instant
java.util.Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();

long ts = now.getTime();//13位、毫秒级时间戳
Instant instant = Instant.ofEpochMilli( ts ); 
  • 从时间字符串类型中创建Instant类型的时间
Instant instant = Instant.parse("1995-10-23T10:12:35Z"); // UTC+0 格式的时间字符串
instant.toEpochMilli();//8144 4315 5000 (单位: 毫秒) => 换算为 UTC+8时,则对应时间为: 1995-10-23 18:12:35

注意,在上面这个例子中,有一个时间字符串中创建 Instant 类型的时间,但 Instant 代表的是一个时间,并不包括时区的概念,所以必须传入的是符合 UTC 格式的时间字符串。

  • 允许使用 Instant 和其他包中的类进行一些运算
Instant instant = Instant.parse("1995-10-23T10:12:35Z");
Instant instant2 = instant.plus(Duration.ofHours(5).plusMinutes(4));
instant2.toEpochMilli();//8144 6139 5000 (毫秒级时间戳) => 相当于 1995-10-23 23:16:35 (UTC+8)

java.time.LocalDateTime : 本地时间

  • 定义

它是LocalDateLocalTime的组合体,表示的是不带时区的日期及时间。
包含了年、月、日、时、分、秒等信息,可以精确到纳秒级别。
与Date类不同,LocalDateTime 不受时区的影响,更适合处理应用程序中不涉及时区转换的日期和时间。

  • 最主要的特性:
    (1) 不可变性(Immutability): LocalDateTime 是不可变的,这意味着一旦创建了对象,就无法更改其内容。任何对日期和时间的修改都会返回一个新的LocalDateTime对象。
    (2) 线程安全性: 由于不可变性,LocalDateTime 是线程安全的。多个线程可以同时访问对象而无需担心并发问题。
    (3) 工厂方法: 除了使用of方法创建 LocalDateTime 对象外,还有一些静态工厂方法,如now、ofInstant、ofEpochSecond等,用于根据不同的情况创建实例。
    (4) 日期时间调整: LocalDateTime 提供了 plus、minus 等方法,用于执行日期和时间的调整操作。这些方法返回新的对象,而不是修改原始对象。
    (5) 格式化和解析: LocalDateTime 支持 DateTimeFormatter 用于格式化和解析日期时间。你可以创建自定义的格式化模式。

  • API: LocalDateTime : static now()

//获取当前日期时间:
LocalDateTime currentDateTime = LocalDateTime.now();
  • API: of(int var0, Month var1, int var2, int var3, int var4)

//创建指定日期时间:
LocalDateTime specificDateTime = LocalDateTime.of(2022, Month.JANUARY, 1, 12, 30);
  • API: Instant toInstant(ZoneOffset var1)

  • API: long toEpochSecond(ZoneOffset var1)

返回10位的秒级时间戳

LocalDateTime localDateTime = LocalDateTime.now(); 
localDateTime.toEpochSecond(ZoneOffset.of("+08")); //10位的秒级时间戳
  • API : ZonedDateTime atZone(ZoneId var1)

atZone() 方法用于通过将此 LocalDateTime(日期时间) 合并到给定区域来创建 ZonedDateTime

LocalDateTime localDateTime = LocalDateTime.parse("2024-01-01T00:00:00");

ZonedDateTime utc8ZonedDateTime = localDateTime.atZone(ZoneId.of("+08"));
utc8ZonedDateTime.toInstant().toEpochMilli();//1704038400000 => 相当于: 2024-01-01 00:00:00 (UTC+8)

ZonedDateTime utc0ZonedDateTime = localDateTime.atZone(ZoneId.of("+00"));
utc0ZonedDateTime.toInstant().toEpochMilli();//1704067200000 => 相当于: 2024-01-01 08:00:00 (UTC+8)

java.time.LocalDateTime#now()方法的源码分析

  • java.time.LocalDateTime
    //java.time.LocalDateTime#now()
    public static LocalDateTime now() { // 分析入口
        return now(Clock.systemDefaultZone());
    }

	//java.time.LocalDateTime#now(java.time.ZoneId)
    public static LocalDateTime now(ZoneId var0) {
        return now(Clock.system(var0));
    }

    //java.time.LocalDateTime#now(java.time.Clock)
    public static LocalDateTime now(Clock var0) {
        Objects.requireNonNull(var0, "clock");
        Instant var1 = var0.instant();
        ZoneOffset var2 = var0.getZone().getRules().getOffset(var1);
        return ofEpochSecond(var1.getEpochSecond(), var1.getNano(), var2);
    }


  • java.time.Clock
    //java.time.Clock#systemDefaultZone
    public static Clock systemDefaultZone() {
        return new SystemClock(ZoneId.systemDefault());
    }
  • java.time.ZoneId
    //java.time.ZoneId#systemDefault
    public static ZoneId systemDefault() {
	    // TimeZone.getDefault() 返回的对象 := java.util.TimeZone
		// 例如: TimeZone.getDefault().getID() = "Asia/Shanghai" | TimeZone.getDefault().getDisplayName() := "中国标准时间"
		// 例如: TimeZone.getDefault().getRawOffset() := 28800000 (单位: 毫秒)
		// 例如: 支持主动设置时区 | TimeZone.setDefaultZone(); or TimeZone.setDefault(TimeZone.getTimeZone("UTC")); // "UTC" or "+00" or ...
        return TimeZone.getDefault().toZoneId();
    }

ZonedDateTime : 时区时间

  • API: ChronoZonedDateTime withZoneSameInstant(ZoneId zone)

返回值: 该方法根据请求区域的日期时间返回一个时区数据。
异常:此方法抛出日期时间异常:如果结果超出支持的日期范围。

ChronoZonedDateTime zonedDT = ZonedDateTime.parse( "2018-12-06T19:21:12.123+05:30[Asia/Calcutta]");

ZoneOffset f = zonedDT.getOffset(); // id = "+05:30" / totalSeconds = 19800

获取系统默认时区 : ZoneId.systemDefault() / TimeZone#getDefault / TimeZone#setDefaultZone

  • java.time.ZoneId#systemDefault : 分析入口
    public static ZoneId systemDefault() {//获取系统默认时区
        return TimeZone
			.getDefault() // java.util.TimeZone#getDefault
			.toZoneId(); // java.util.TimeZone#toZoneId
    }
  • java.util.TimeZone#toZoneId
    public ZoneId toZoneId() {
        String var1 = this.getID();
        if (ZoneInfoFile.useOldMapping() && var1.length() == 3) {
            if ("EST".equals(var1)) {
                return ZoneId.of("America/New_York");
            }

            if ("MST".equals(var1)) {
                return ZoneId.of("America/Denver");
            }

            if ("HST".equals(var1)) {
                return ZoneId.of("America/Honolulu");
            }
        }

        return ZoneId.of(var1, ZoneId.SHORT_IDS);
    }
  • java.util.TimeZone#getDefault
    public static TimeZone getDefault() {
        return (TimeZone)getDefaultRef().clone();//java.util.TimeZone#getDefaultRef
    }
  • java.util.TimeZone#getDefaultRef
    static TimeZone getDefaultRef() {
        TimeZone var0 = defaultTimeZone;//defaultTimeZone : TimeZone 的 静态属性 : private static volatile TimeZone defaultTimeZone;
        if (var0 == null) {
            var0 = setDefaultZone();//java.util.TimeZone#setDefaultZone

            assert var0 != null;
        }

        return var0;
    }
  • java.util.TimeZone#setDefaultZone
    private static synchronized TimeZone setDefaultZone() {
        final String var1 = (String)AccessController.doPrivileged(new GetPropertyAction("user.timezone"));
        String var2;
        if (var1 == null || var1.isEmpty()) {
            var2 = (String)AccessController.doPrivileged(new GetPropertyAction("java.home"));

            try {
                var1 = getSystemTimeZoneID(var2);// java.util.TimeZone#getSystemTimeZoneID : private static native String getSystemTimeZoneID(String var0);
                if (var1 == null) {
                    var1 = "GMT";
                }
            } catch (NullPointerException var4) {
                var1 = "GMT";
            }
        }

        TimeZone var0 = getTimeZone(var1, false);
        if (var0 == null) {
            var2 = getSystemGMTOffsetID();
            if (var2 != null) {
                var1 = var2;
            }

            var0 = getTimeZone(var1, true);
        }

        assert var0 != null;

        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                System.setProperty("user.timezone", var1);
                return null;
            }
        });
        defaultTimeZone = var0;
        return var0;
    }
  • 补充:设置 java 默认时区的方式
  • 方式1
// 设置时区为 Asia/Shanghai
System.setProperty("user.timezone", "Asia/Shanghai");

这行代码用于设置系统的默认时区为 “Asia/Shanghai”。

或者 通过 JVM参数(VM Options)

java -Duser.timezone=Asia/Shanghai YourMainClass
  • 方式2
// 应用时区设置
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
  • 案例:使用系统默认时区
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
 
public class TimeExample {
    public static void main(String[] args) {
        Instant instant = Instant.now();
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = zonedDateTime.format(formatter);
        System.out.println("Current Date and Time: " + formattedDateTime);
    }
}

获取可用的时区

Java一共定义了 603个 时区,这些时区的名字是不需要你去背的,在 java.time.ZoneId 这个类中有一个方法可以获取到:getAvailableZoneIds()

这个方法是 static 静态方法,因此我们直接用类名直接调用就行了。

  • 获取所有可用的时区
static Set<string> getAvailableZoneIds()  // 获取Java中支持的所有时区名称

["Asia/Aden","America/Cuiaba","Etc/GMT+9","Etc/GMT+8","Africa/Nairobi","America/Marigot","Asia/Aqtau","Pacific/Kwajalein","America/El_Salvador","Asia/Pontianak","Africa/Cairo","Pacific/Pago_Pago","Africa/Mbabane","Asia/Kuching","Pacific/Honolulu","Pacific/Rarotonga","America/Guatemala","Australia/Hobart","Europe/London","America/Belize","America/Panama","Asia/Chungking","America/Managua","America/Indiana/Petersburg","Asia/Yerevan","Europe/Brussels","GMT","Europe/Warsaw","America/Chicago","Asia/Kashgar","Chile/Continental","Pacific/Yap","CET","Etc/GMT-1","Etc/GMT-0","Europe/Jersey","America/Tegucigalpa","Etc/GMT-5","Europe/Istanbul","America/Eirunepe","Etc/GMT-4","America/Miquelon","Etc/GMT-3","Europe/Luxembourg","Etc/GMT-2","Etc/GMT-9","America/Argentina/Catamarca","Etc/GMT-8","Etc/GMT-7","Etc/GMT-6","Europe/Zaporozhye","Canada/Yukon","Canada/Atlantic","Atlantic/St_Helena","Australia/Tasmania","Libya","Europe/Guernsey","America/Grand_Turk","US/Pacific-New","Asia/Samarkand","America/Argentina/Cordoba","Asia/Phnom_Penh","Africa/Kigali","Asia/Almaty","US/Alaska","Asia/Dubai","Europe/Isle_of_Man","America/Araguaina","Cuba","Asia/Novosibirsk","America/Argentina/Salta","Etc/GMT+3","Africa/Tunis","Etc/GMT+2","Etc/GMT+1","Pacific/Fakaofo","Africa/Tripoli","Etc/GMT+0","Israel","Africa/Banjul","Etc/GMT+7","Indian/Comoro","Etc/GMT+6","Etc/GMT+5","Etc/GMT+4","Pacific/Port_Moresby","US/Arizona","Antarctica/Syowa","Indian/Reunion","Pacific/Palau","Europe/Kaliningrad","America/Montevideo","Africa/Windhoek","Asia/Karachi","Africa/Mogadishu","Australia/Perth","Brazil/East","Etc/GMT","Asia/Chita","Pacific/Easter","Antarctica/Davis","Antarctica/McMurdo","Asia/Macao","America/Manaus","Africa/Freetown","Europe/Bucharest","Asia/Tomsk","America/Argentina/Mendoza","Asia/Macau","Europe/Malta","Mexico/BajaSur","Pacific/Tahiti","Africa/Asmera","Europe/Busingen","America/Argentina/Rio_Gallegos","Africa/Malabo","Europe/Skopje","America/Catamarca","America/Godthab","Europe/Sarajevo","Australia/ACT","GB-Eire","Africa/Lagos","America/Cordoba","Europe/Rome","Asia/Dacca","Indian/Mauritius","Pacific/Samoa","America/Regina","America/Fort_Wayne","America/Dawson_Creek","Africa/Algiers","Europe/Mariehamn","America/St_Johns","America/St_Thomas","Europe/Zurich","America/Anguilla","Asia/Dili","America/Denver","Africa/Bamako","Europe/Saratov","GB","Mexico/General","Pacific/Wallis","Europe/Gibraltar","Africa/Conakry","Africa/Lubumbashi","Asia/Istanbul","America/Havana","NZ-CHAT","Asia/Choibalsan","America/Porto_Acre","Asia/Omsk","Europe/Vaduz","US/Michigan","Asia/Dhaka","America/Barbados","Europe/Tiraspol","Atlantic/Cape_Verde","Asia/Yekaterinburg","America/Louisville","Pacific/Johnston","Pacific/Chatham","Europe/Ljubljana","America/Sao_Paulo","Asia/Jayapura","America/Curacao","Asia/Dushanbe","America/Guyana","America/Guayaquil","America/Martinique","Portugal","Europe/Berlin","Europe/Moscow","Europe/Chisinau","America/Puerto_Rico","America/Rankin_Inlet","Pacific/Ponape","Europe/Stockholm","Europe/Budapest","America/Argentina/Jujuy","Australia/Eucla","Asia/Shanghai","Universal","Europe/Zagreb","America/Port_of_Spain","Europe/Helsinki","Asia/Beirut","Asia/Tel_Aviv","Pacific/Bougainville","US/Central","Africa/Sao_Tome","Indian/Chagos","America/Cayenne","Asia/Yakutsk","Pacific/Galapagos","Australia/North","Europe/Paris","Africa/Ndjamena","Pacific/Fiji","America/Rainy_River","Indian/Maldives","Australia/Yancowinna","SystemV/AST4","Asia/Oral","America/Yellowknife","Pacific/Enderbury","America/Juneau","Australia/Victoria","America/Indiana/Vevay","Asia/Tashkent","Asia/Jakarta","Africa/Ceuta","Asia/Barnaul","America/Recife","America/Buenos_Aires","America/Noronha","America/Swift_Current","Australia/Adelaide","America/Metlakatla","Africa/Djibouti","America/Paramaribo","Asia/Qostanay","Europe/Simferopol","Europe/Sofia","Africa/Nouakchott","Europe/Prague","America/Indiana/Vincennes","Antarctica/Mawson","America/Kralendijk","Antarctica/Troll","Europe/Samara","Indian/Christmas","America/Antigua","Pacific/Gambier","America/Indianapolis","America/Inuvik","America/Iqaluit","Pacific/Funafuti","UTC","Antarctica/Macquarie","Canada/Pacific","America/Moncton","Africa/Gaborone","Pacific/Chuuk","Asia/Pyongyang","America/St_Vincent","Asia/Gaza","Etc/Universal","PST8PDT","Atlantic/Faeroe","Asia/Qyzylorda","Canada/Newfoundland","America/Kentucky/Louisville","America/Yakutat","Asia/Ho_Chi_Minh","Antarctica/Casey","Europe/Copenhagen","Africa/Asmara","Atlantic/Azores","Europe/Vienna","ROK","Pacific/Pitcairn","America/Mazatlan","Australia/Queensland","Pacific/Nauru","Europe/Tirane","Asia/Kolkata","SystemV/MST7","Australia/Canberra","MET","Australia/Broken_Hill","Europe/Riga","America/Dominica","Africa/Abidjan","America/Mendoza","America/Santarem","Kwajalein","America/Asuncion","Asia/Ulan_Bator","NZ","America/Boise","Australia/Currie","EST5EDT","Pacific/Guam","Pacific/Wake","Atlantic/Bermuda","America/Costa_Rica","America/Dawson","Asia/Chongqing","Eire","Europe/Amsterdam","America/Indiana/Knox","America/North_Dakota/Beulah","Africa/Accra","Atlantic/Faroe","Mexico/BajaNorte","America/Maceio","Etc/UCT","Pacific/Apia","GMT0","America/Atka","Pacific/Niue","Australia/Lord_Howe","Europe/Dublin","Pacific/Truk","MST7MDT","America/Monterrey","America/Nassau","America/Jamaica","Asia/Bishkek","America/Atikokan","Atlantic/Stanley","Australia/NSW","US/Hawaii","SystemV/CST6","Indian/Mahe","Asia/Aqtobe","America/Sitka","Asia/Vladivostok","Africa/Libreville","Africa/Maputo","Zulu","America/Kentucky/Monticello","Africa/El_Aaiun","Africa/Ouagadougou","America/Coral_Harbour","Pacific/Marquesas","Brazil/West","America/Aruba","America/North_Dakota/Center","America/Cayman","Asia/Ulaanbaatar","Asia/Baghdad","Europe/San_Marino","America/Indiana/Tell_City","America/Tijuana","Pacific/Saipan","SystemV/YST9","Africa/Douala","America/Chihuahua","America/Ojinaga","Asia/Hovd","America/Anchorage","Chile/EasterIsland","America/Halifax","Antarctica/Rothera","America/Indiana/Indianapolis","US/Mountain","Asia/Damascus","America/Argentina/San_Luis","America/Santiago","Asia/Baku","America/Argentina/Ushuaia","Atlantic/Reykjavik","Africa/Brazzaville","Africa/Porto-Novo","America/La_Paz","Antarctica/DumontDUrville","Asia/Taipei","Antarctica/South_Pole","Asia/Manila","Asia/Bangkok","Africa/Dar_es_Salaam","Poland","Atlantic/Madeira","Antarctica/Palmer","America/Thunder_Bay","Africa/Addis_Ababa","Asia/Yangon","Europe/Uzhgorod","Brazil/DeNoronha","Asia/Ashkhabad","Etc/Zulu","America/Indiana/Marengo","America/Creston","America/Punta_Arenas","America/Mexico_City","Antarctica/Vostok","Asia/Jerusalem","Europe/Andorra","US/Samoa","PRC","Asia/Vientiane","Pacific/Kiritimati","America/Matamoros","America/Blanc-Sablon","Asia/Riyadh","Iceland","Pacific/Pohnpei","Asia/Ujung_Pandang","Atlantic/South_Georgia","Europe/Lisbon","Asia/Harbin","Europe/Oslo","Asia/Novokuznetsk","CST6CDT","Atlantic/Canary","America/Knox_IN","Asia/Kuwait","SystemV/HST10","Pacific/Efate","Africa/Lome","America/Bogota","America/Menominee","America/Adak","Pacific/Norfolk","Europe/Kirov","America/Resolute","Pacific/Tarawa","Africa/Kampala","Asia/Krasnoyarsk","Greenwich","SystemV/EST5","America/Edmonton","Europe/Podgorica","Australia/South","Canada/Central","Africa/Bujumbura","America/Santo_Domingo","US/Eastern","Europe/Minsk","Pacific/Auckland","Africa/Casablanca","America/Glace_Bay","Canada/Eastern","Asia/Qatar","Europe/Kiev","Singapore","Asia/Magadan","SystemV/PST8","America/Port-au-Prince","Europe/Belfast","America/St_Barthelemy","Asia/Ashgabat","Africa/Luanda","America/Nipigon","Atlantic/Jan_Mayen","Brazil/Acre","Asia/Muscat","Asia/Bahrain","Europe/Vilnius","America/Fortaleza","Etc/GMT0","US/East-Indiana","America/Hermosillo","America/Cancun","Africa/Maseru","Pacific/Kosrae","Africa/Kinshasa","Asia/Kathmandu","Asia/Seoul","Australia/Sydney","America/Lima","Australia/LHI","America/St_Lucia","Europe/Madrid","America/Bahia_Banderas","America/Montserrat","Asia/Brunei","America/Santa_Isabel","Canada/Mountain","America/Cambridge_Bay","Asia/Colombo","Australia/West","Indian/Antananarivo","Australia/Brisbane","Indian/Mayotte","US/Indiana-Starke","Asia/Urumqi","US/Aleutian","Europe/Volgograd","America/Lower_Princes","America/Vancouver","Africa/Blantyre","America/Rio_Branco","America/Danmarkshavn","America/Detroit","America/Thule","Africa/Lusaka","Asia/Hong_Kong","Iran","America/Argentina/La_Rioja","Africa/Dakar","SystemV/CST6CDT","America/Tortola","America/Porto_Velho","Asia/Sakhalin","Etc/GMT+10","America/Scoresbysund","Asia/Kamchatka","Asia/Thimbu","Africa/Harare","Etc/GMT+12","Etc/GMT+11","Navajo","America/Nome","Europe/Tallinn","Turkey","Africa/Khartoum","Africa/Johannesburg","Africa/Bangui","Europe/Belgrade","Jamaica","Africa/Bissau","Asia/Tehran","WET","Europe/Astrakhan","Africa/Juba","America/Campo_Grande","America/Belem","Etc/Greenwich","Asia/Saigon","America/Ensenada","Pacific/Midway","America/Jujuy","Africa/Timbuktu","America/Bahia","America/Goose_Bay","America/Virgin","America/Pangnirtung","Asia/Katmandu","America/Phoenix","Africa/Niamey","America/Whitehorse","Pacific/Noumea","Asia/Tbilisi","America/Montreal","Asia/Makassar","America/Argentina/San_Juan","Hongkong","UCT","Asia/Nicosia","America/Indiana/Winamac","SystemV/MST7MDT","America/Argentina/ComodRivadavia","America/Boa_Vista","America/Grenada","Asia/Atyrau","Australia/Darwin","Asia/Khandyga","Asia/Kuala_Lumpur","Asia/Famagusta","Asia/Thimphu","Asia/Rangoon","Europe/Bratislava","Asia/Calcutta","America/Argentina/Tucuman","Asia/Kabul","Indian/Cocos","Japan","Pacific/Tongatapu","America/New_York","Etc/GMT-12","Etc/GMT-11","America/Nuuk","Etc/GMT-10","SystemV/YST9YDT","Europe/Ulyanovsk","Etc/GMT-14","Etc/GMT-13","W-SU","America/Merida","EET","America/Rosario","Canada/Saskatchewan","America/St_Kitts","Arctic/Longyearbyen","America/Fort_Nelson","America/Caracas","America/Guadeloupe","Asia/Hebron","Indian/Kerguelen","SystemV/PST8PDT","Africa/Monrovia","Asia/Ust-Nera","Egypt","Asia/Srednekolymsk","America/North_Dakota/New_Salem","Asia/Anadyr","Australia/Melbourne","Asia/Irkutsk","America/Shiprock","America/Winnipeg","Europe/Vatican","Asia/Amman","Etc/UTC","SystemV/AST4ADT","Asia/Tokyo","America/Toronto","Asia/Singapore","Australia/Lindeman","America/Los_Angeles","SystemV/EST5EDT","Pacific/Majuro","America/Argentina/Buenos_Aires","Europe/Nicosia","Pacific/Guadalcanal","Europe/Athens","US/Pacific","Europe/Monaco"]
  • 获取系统默认时区
static ZoneId systemDefault()	// 获取当前系统默认时区
  • 指定时区
static Zoneld of(string zoneld)  // 指定一个时区

如:
ZoneId.of("Asia/Shanghai")
ZoneId.of("Asia/Tokyo")
ZoneId.of("UTC+08")
ZoneId.of("UTC")
ZoneId.of("GMT")

获取当前UTC时间

import java.time.ZonedDateTime;
import java.time.ZoneOffset;
 
public class TimeExample {
    public static void main(String[] args) {
        // 获取当前UTC时间
        ZonedDateTime utcNow = ZonedDateTime.now(ZoneOffset.UTC);// ZoneOffset.UTC or ZoneOffset.of("Asia/Shanghai") or ...
        System.out.println("Current UTC Time: " + utcNow);//Current UTC Time: 2024-11-27T13:29:36.840Z
    }
}

将本地时间转换为UTC时间

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
 
public class LocalToUTCTimeExample {
    public static void main(String[] args) {
        // 获取当前本地时间
        LocalDateTime localNow = LocalDateTime.now();
        // 将本地时间转换为UTC时间
        ZonedDateTime utcTime = localNow.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC);
        System.out.println("Local Time to UTC: " + utcTime);
    }
}

时间字符串的解析(转为时间对象、转时间戳)

public static datetimeStrParse(){
	final ZoneId ZONE_CST = ZoneId.of("Asia/Shanghai");
	final DateTimeFormatter CST_PARSER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZONE_CST);

	String dateTimeString = "2024-11-24 08:40:00";
	ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString, CST_PARSER);
	Long ts = dateTime.toInstant().toEpochMilli();//获取时间戳
	System.out.println("ts: "+ ts + " dateTime: " + dateTime);//ts: 1732408800000 dateTime: 2024-11-24T08:40+08:00[Asia/Shanghai]
}
  • DateTimeFormatter#Pattern的参数
  • y:年份,例如"2022"
  • M:月份,例如"01"
  • d:天数,例如"01"
  • H:小时(24小时制),例如"10"
  • h:小时(12小时制),例如"10"或"10 PM"
  • m:分钟数,例如"00"
  • s:秒数,例如"00"
  • S:毫秒数,例如"000"
  • a:上午/下午标记,例如"AM"或"PM"
  • E:星期几
  • Z:时区

获取时间戳(毫秒级、纳秒级)

  • 获取毫秒级时间戳
Long ts = System.currentTimeMillis();
//1733923968525
  • 获取纳秒级时间戳 【不推荐使用】
  • nanoTime返回的可能是任意时间,甚至可能是负数
Long ts = System.nanoTime();
//25793292985600

long startTime = System.nanoTime();
// 某个算法,例如:线性查找算法
long endTime = System.nanoTime();
double timeConsuming = (endTime - startTime) / 1000000000.0  // 将纳秒转换为秒
System.out.println(timeConsuming + "s");
  • 扩展应用场景:纳秒数转毫秒级时间戳
    /**
     * 纳秒数转毫秒级时间戳
     * @param targetNanoTime
     *   eg: long targetNanoTime = System.nanoTime(); // 获取当前时间的 nano time,例如 : 87277522042200
     * @return
     */
    public static long nanoTimeToMillisTimestamp(long targetNanoTime){
        //待转换的纳秒时间(targetNanoTime)
        //long targetNanoTime = System.nanoTime(); // 获取当前时间的 nano time,例如 : 87277522042200

        //获取当前的毫秒数(currentTimeMillis) 和 纳秒数(currentNanoTime)
        long currentTimeMillis = System.currentTimeMillis();//例如: 1733985453227
        long currentNanoTime = System.nanoTime();//例如 : 87277522044200

        //计算 currentNanoTime 与 targetNanoTime 的差值(nanoTimeDiff)
        long nanoTimeDiff = currentNanoTime - targetNanoTime;//例如: 2000
        // 利用 currentNanoTime 和 nanoTimeDiff ,向前推算出 targetNanoTime当时对应的毫秒级时间戳
        long targetMillisTime = currentTimeMillis - ( nanoTimeDiff / 1000000L);//13位的毫秒级时间戳,例如: 1733985453227

        //Date date = new Date(targetMillisTime); // 创建日期对象
        //System.out.println("date : " + date.toString());//例如: date : Thu Dec 12 14:37:33 CST 2024
        return targetMillisTime;
    }

MYSQL 时间与时区概述

MYSQL 支持的时区

方式1:查看操作系统

在mysql文档中发现可用的时区都在/usr/share/zoneinfo目录下

lewis@lewis-dzwww:/usr/share/zoneinfo$ ll
总用量 308
drwxr-xr-x  21 root root  4096 5月  27 12:54 ./
drwxr-xr-x 334 root root 12288 6月  21 15:11 ../
drwxr-xr-x   2 root root  4096 5月  27 12:56 Africa/
drwxr-xr-x   6 root root  4096 5月  27 12:56 America/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Antarctica/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Arctic/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Asia/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Atlantic/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Australia/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Brazil/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Canada/
-rw-r--r--   1 root root  2102 4月  21 02:09 CET
drwxr-xr-x   2 root root  4096 5月  27 12:56 Chile/
-rw-r--r--   1 root root  2294 4月  21 02:09 CST6CDT
-rw-r--r--   1 root root  2437 4月  21 02:09 Cuba
-rw-r--r--   1 root root  1876 4月  21 02:09 EET
-rw-r--r--   1 root root  1972 4月  21 02:09 Egypt
-rw-r--r--   1 root root  3559 4月  21 02:09 Eire
-rw-r--r--   1 root root   127 4月  21 02:09 EST
-rw-r--r--   1 root root  2294 4月  21 02:09 EST5EDT
drwxr-xr-x   2 root root  4096 5月  27 12:56 Etc/
drwxr-xr-x   2 root root  4096 5月  27 12:56 Europe/
-rw-r--r--   1 root root   264 4月  21 02:09 Factory
-rw-r--r--   1 root root  3687 4月  21 02:09 GB
lrwxrwxrwx   1 root root     2 5月  27 09:07 GB-Eire -> GB
-rw-r--r--   1 root root   127 4月  21 02:09 GMT
lrwxrwxrwx   1 root root     3 5月  27 09:07 GMT0 -> GMT
lrwxrwxrwx   1 root root     3 5月  27 09:07 GMT-0 -> GMT
lrwxrwxrwx   1 root root     3 5月  27 09:07 GMT+0 -> GMT
lrwxrwxrwx   1 root root     3 5月  27 09:07 Greenwich -> GMT
-rw-r--r--   1 root root  1189 4月  21 02:09 Hongkong
-rw-r--r--   1 root root   128 4月  21 02:09 HST
-rw-r--r--   1 root root  1190 4月  21 02:09 Iceland
drwxr-xr-x   2 root root  4096 5月  27 12:56 Indian/
-rw-r--r--   1 root root  1678 4月  21 02:09 Iran
-rw-r--r--   1 root root  4475 2月  24 17:01 iso3166.tab
-rw-r--r--   1 root root  2265 4月  21 02:09 Israel
-rw-r--r--   1 root root   507 4月  21 02:09 Jamaica
-rw-r--r--   1 root root   355 4月  21 02:09 Japan
-rw-r--r--   1 root root   237 4月  21 02:09 Kwajalein
-rw-r--r--   1 root root 10384 2月  22 23:58 leap-seconds.list
-rw-r--r--   1 root root   655 4月  21 02:09 Libya
lrwxrwxrwx   1 root root    14 5月  27 09:07 localtime -> /etc/localtime
-rw-r--r--   1 root root  2102 4月  21 02:09 MET
drwxr-xr-x   2 root root  4096 5月  27 12:56 Mexico/
-rw-r--r--   1 root root   127 4月  21 02:09 MST
-rw-r--r--   1 root root  2294 4月  21 02:09 MST7MDT
-rw-r--r--   1 root root  2453 4月  21 02:09 Navajo
-rw-r--r--   1 root root  2460 4月  21 02:09 NZ
-rw-r--r--   1 root root  2057 4月  21 02:09 NZ-CHAT
drwxr-xr-x   2 root root  4096 5月  27 12:56 Pacific/
-rw-r--r--   1 root root  2705 4月  21 02:09 Poland
-rw-r--r--   1 root root  3453 4月  21 02:09 Portugal
drwxr-xr-x  19 root root  4096 5月  27 12:56 posix/
-rw-r--r--   1 root root  3545 4月  21 02:09 posixrules
-rw-r--r--   1 root root   414 4月  21 02:09 PRC
-rw-r--r--   1 root root  2294 4月  21 02:09 PST8PDT
drwxr-xr-x  19 root root  4096 5月  27 12:56 right/
-rw-r--r--   1 root root   800 4月  21 02:09 ROC
-rw-r--r--   1 root root   571 4月  21 02:09 ROK
-rw-r--r--   1 root root   428 4月  21 02:09 Singapore
drwxr-xr-x   2 root root  4096 5月  27 12:56 SystemV/
-rw-r--r--   1 root root  2747 4月  21 02:09 Turkey
-rw-r--r--   1 root root   127 4月  21 02:09 UCT
lrwxrwxrwx   1 root root     4 5月  27 09:07 Universal -> Zulu
drwxr-xr-x   2 root root  4096 5月  27 12:56 US/
lrwxrwxrwx   1 root root     4 5月  27 09:07 UTC -> Zulu
-rw-r--r--   1 root root  1873 4月  21 02:09 WET
-rw-r--r--   1 root root  1528 4月  21 02:09 W-SU
-rw-r--r--   1 root root 17533 4月  13 16:01 zone1970.tab
-rw-r--r--   1 root root 19014 4月  13 16:01 zone.tab
-rw-r--r--   1 root root   127 4月  21 02:09 Zulu

方式2: mysql.time_zone_name

> SELECT * FROM mysql.time_zone_name;
Name                            |Time_zone_id|
--------------------------------+------------+
Africa/Abidjan	37
Africa/Accra	159
Africa/Addis_Ababa	499
Africa/Algiers	230
Africa/Asmara	191
Africa/Asmera	590
Africa/Bamako	150
Africa/Bangui	256
Africa/Banjul	154
Africa/Bissau	26
Africa/Blantyre	329
Africa/Brazzaville	567
Africa/Bujumbura	94
Africa/Cairo	359
Africa/Casablanca	474
Africa/Ceuta	479
Africa/Conakry	216
Africa/Dakar	489
Africa/Dar_es_Salaam	353
Africa/Djibouti	449
Africa/Douala	368
Africa/Freetown	24
Africa/Gaborone	533
Africa/Harare	148
Africa/Johannesburg	455
Africa/Juba	49
Africa/Kampala	346
Africa/Khartoum	358
Africa/Kigali	564
Africa/Kinshasa	180
Africa/Lagos	574
Africa/Libreville	22
Africa/Lome	559
Africa/Luanda	356
Africa/Lubumbashi	269
Africa/Lusaka	204
Africa/Malabo	162
Africa/Maputo	524
Africa/Maseru	9
Africa/Mbabane	174
Africa/Mogadishu	492
Africa/Monrovia	480
Africa/Nairobi	145
Africa/Ndjamena	232
Africa/Niamey	471
Africa/Nouakchott	476
Africa/Ouagadougou	295
Africa/Porto-Novo	286
Africa/Sao_Tome	90
Africa/Timbuktu	363
Africa/Tripoli	304
Africa/Tunis	534
Africa/Windhoek	226
America/Adak	257
America/Anchorage	587
America/Anguilla	539
America/Antigua	258
America/Araguaina	32
America/Argentina/Buenos_Aires	52
America/Argentina/Catamarca	552
America/Argentina/ComodRivadavia	170
America/Argentina/Cordoba	225
America/Argentina/Jujuy	313
America/Argentina/La_Rioja	260
America/Argentina/Mendoza	578
America/Argentina/Rio_Gallegos	141
America/Argentina/Salta	320
America/Argentina/San_Juan	372
America/Argentina/San_Luis	58
America/Argentina/Tucuman	219
America/Argentina/Ushuaia	186
America/Aruba	67
America/Asuncion	429
America/Atikokan	11
America/Atka	21
America/Bahia	293
America/Bahia_Banderas	374
America/Barbados	547
America/Belem	89
America/Belize	160
America/Blanc-Sablon	405
America/Boa_Vista	385
America/Bogota	190
America/Boise	116
America/Buenos_Aires	6
America/Cambridge_Bay	355
America/Campo_Grande	462
America/Cancun	500
America/Caracas	195
America/Catamarca	137
America/Cayenne	488
America/Cayman	350
America/Chicago	194
America/Chihuahua	139
America/Coral_Harbour	23
America/Cordoba	365
America/Costa_Rica	239
America/Creston	319
America/Cuiaba	203
America/Curacao	354
America/Danmarkshavn	125
America/Dawson	498
America/Dawson_Creek	463
America/Denver	529
America/Detroit	332
America/Dominica	285
America/Edmonton	161
America/Eirunepe	127
America/El_Salvador	45
America/Ensenada	79
America/Fortaleza	491
America/Fort_Nelson	20
America/Fort_Wayne	123
America/Glace_Bay	531
America/Godthab	522
America/Goose_Bay	420
America/Grand_Turk	568
America/Grenada	336
America/Guadeloupe	117
America/Guatemala	88
America/Guayaquil	235
America/Guyana	439
America/Halifax	5
America/Havana	504
America/Hermosillo	233
America/Indiana/Indianapolis	259
America/Indiana/Knox	553
America/Indiana/Marengo	478
America/Indiana/Petersburg	338
America/Indiana/Tell_City	310
America/Indiana/Vevay	545
America/Indiana/Vincennes	337
America/Indiana/Winamac	361
America/Indianapolis	70
America/Inuvik	503
America/Iqaluit	523
America/Jamaica	411
America/Jujuy	364
America/Juneau	283
America/Kentucky/Louisville	290
America/Kentucky/Monticello	496
America/Knox_IN	484
America/Kralendijk	375
America/La_Paz	199
America/Lima	390
America/Los_Angeles	418
America/Louisville	106
America/Lower_Princes	446
America/Maceio	421
America/Managua	247
America/Manaus	131
America/Marigot	445
America/Martinique	40
America/Matamoros	217
America/Mazatlan	399
America/Mendoza	165
America/Menominee	238
America/Merida	86
America/Metlakatla	525
America/Mexico_City	78
America/Miquelon	15
America/Moncton	107
America/Monterrey	589
America/Montevideo	333
America/Montreal	289
America/Montserrat	322
America/Nassau	119
America/New_York	276
America/Nipigon	12
America/Nome	571
America/Noronha	228
America/North_Dakota/Beulah	138
America/North_Dakota/Center	542
America/North_Dakota/New_Salem	518
America/Nuuk	234
America/Ojinaga	520
America/Panama	231
America/Pangnirtung	250
America/Paramaribo	266
America/Phoenix	202
America/Port-au-Prince	348
America/Porto_Acre	113
America/Porto_Velho	475
America/Port_of_Spain	301
America/Puerto_Rico	80
America/Punta_Arenas	423
America/Rainy_River	344
America/Rankin_Inlet	132
America/Recife	193
America/Regina	71
America/Resolute	543
America/Rio_Branco	129
America/Rosario	464
America/Santarem	114
America/Santa_Isabel	18
America/Santiago	51
America/Santo_Domingo	408
America/Sao_Paulo	441
America/Scoresbysund	126
America/Shiprock	334
America/Sitka	431
America/St_Barthelemy	108
America/St_Johns	585
America/St_Kitts	227
America/St_Lucia	28
America/St_Thomas	394
America/St_Vincent	210
America/Swift_Current	318
America/Tegucigalpa	112
America/Thule	105
America/Thunder_Bay	413
America/Tijuana	556
America/Toronto	291
America/Tortola	582
America/Vancouver	144
America/Virgin	299
America/Whitehorse	314
America/Winnipeg	483
America/Yakutat	573
America/Yellowknife	209
Antarctica/Casey	102
Antarctica/Davis	93
Antarctica/DumontDUrville	551
Antarctica/Macquarie	509
Antarctica/Mawson	2
Antarctica/McMurdo	109
Antarctica/Palmer	452
Antarctica/Rothera	60
Antarctica/South_Pole	297
Antarctica/Syowa	409
Antarctica/Troll	461
Antarctica/Vostok	468
Arctic/Longyearbyen	56
Asia/Aden	176
Asia/Almaty	554
Asia/Amman	422
Asia/Anadyr	275
Asia/Aqtau	155
Asia/Aqtobe	486
Asia/Ashgabat	527
Asia/Ashkhabad	481
Asia/Atyrau	64
Asia/Baghdad	218
Asia/Bahrain	526
Asia/Baku	437
Asia/Bangkok	465
Asia/Barnaul	442
Asia/Beijing	31
Asia/Beirut	140
Asia/Bishkek	316
Asia/Brunei	550
Asia/Calcutta	309
Asia/Chita	220
Asia/Choibalsan	404
Asia/Chongqing	224
Asia/Chungking	187
Asia/Colombo	347
Asia/Dacca	448
Asia/Damascus	540
Asia/Dhaka	27
Asia/Dili	173
Asia/Dubai	341
Asia/Dushanbe	252
Asia/Famagusta	163
Asia/Gaza	548
Asia/Harbin	370
Asia/Hebron	223
Asia/Hong_Kong	55
Asia/Hovd	124
Asia/Ho_Chi_Minh	146
Asia/Irkutsk	466
Asia/Istanbul	398
Asia/Jakarta	450
Asia/Jayapura	243
Asia/Jerusalem	516
Asia/Kabul	264
Asia/Kamchatka	240
Asia/Karachi	157
Asia/Kashgar	39
Asia/Kathmandu	340
Asia/Katmandu	433
Asia/Khandyga	74
Asia/Kolkata	8
Asia/Krasnoyarsk	41
Asia/Kuala_Lumpur	236
Asia/Kuching	43
Asia/Kuwait	214
Asia/Macao	560
Asia/Magadan	97
Asia/Makassar	430
Asia/Manila	362
Asia/Muscat	298
Asia/Nicosia	253
Asia/Novokuznetsk	151
Asia/Novosibirsk	561
Asia/Omsk	254
Asia/Oral	175
Asia/Phnom_Penh	246
Asia/Pontianak	328
Asia/Pyongyang	339
Asia/Qatar	248
Asia/Qostanay	415
Asia/Qyzylorda	513
Asia/Rangoon	360
Asia/Riyadh	75
Asia/Saigon	103
Asia/Sakhalin	424
Asia/Samarkand	287
Asia/Seoul	570
Asia/Shanghai	130
Asia/Singapore	321
Asia/Srednekolymsk	395
Asia/Taipei	490
Asia/Tashkent	323
Asia/Tbilisi	366
Asia/Tehran	565
Asia/Tel_Aviv	460
Asia/Thimbu	327
Asia/Thimphu	158
Asia/Tokyo	400
Asia/Tomsk	91
Asia/Ujung_Pandang	100
Asia/Ulaanbaatar	343
Asia/Ulan_Bator	249
Asia/Urumqi	335
Asia/Ust-Nera	537
Asia/Vientiane	212
Asia/Vladivostok	538
Asia/Yakutsk	427
Asia/Yangon	82
Asia/Yekaterinburg	98
Asia/Yerevan	198
Atlantic/Azores	515
Atlantic/Bermuda	99
Atlantic/Canary	1
Atlantic/Cape_Verde	111
Atlantic/Faeroe	237
Atlantic/Faroe	485
Atlantic/Jan_Mayen	192
Atlantic/Madeira	172
Atlantic/Reykjavik	432
Atlantic/South_Georgia	456
Atlantic/Stanley	393
Atlantic/St_Helena	546
Australia/ACT	470
Australia/Adelaide	351
Australia/Brisbane	506
Australia/Broken_Hill	200
Australia/Canberra	566
Australia/Currie	101
Australia/Darwin	312
Australia/Eucla	519
Australia/Hobart	281
Australia/LHI	211
Australia/Lindeman	184
Australia/Lord_Howe	371
Australia/Melbourne	7
Australia/North	473
Australia/NSW	121
Australia/Perth	447
Australia/Queensland	555
Australia/South	311
Australia/Sydney	169
Australia/Tasmania	378
Australia/Victoria	153
Australia/West	406
Australia/Yancowinna	444
Brazil/Acre	296
Brazil/DeNoronha	245
Brazil/East	376
Brazil/West	407
Canada/Atlantic	511
Canada/Central	572
Canada/Eastern	417
Canada/Mountain	349
Canada/Newfoundland	17
Canada/Pacific	128
Canada/Saskatchewan	135
Canada/Yukon	507
CET	396
Chile/Continental	458
Chile/EasterIsland	68
CST6CDT	279
Cuba	389
EET	369
Egypt	580
Eire	386
EST	562
EST5EDT	453
Etc/GMT	280
Etc/GMT+0	50
Etc/GMT+1	10
Etc/GMT+10	435
Etc/GMT+11	434
Etc/GMT+12	401
Etc/GMT+2	44
Etc/GMT+3	38
Etc/GMT+4	65
Etc/GMT+5	14
Etc/GMT+6	13
Etc/GMT+7	54
Etc/GMT+8	4
Etc/GMT+9	3
Etc/GMT-0	535
Etc/GMT-1	377
Etc/GMT-10	268
Etc/GMT-11	267
Etc/GMT-12	270
Etc/GMT-13	403
Etc/GMT-14	271
Etc/GMT-2	380
Etc/GMT-3	379
Etc/GMT-4	382
Etc/GMT-5	381
Etc/GMT-6	384
Etc/GMT-7	383
Etc/GMT-8	373
Etc/GMT-9	505
Etc/GMT0	262
Etc/Greenwich	136
Etc/UCT	133
Etc/Universal	352
Etc/UTC	583
Etc/Zulu	528
Europe/Amsterdam	29
Europe/Andorra	387
Europe/Astrakhan	288
Europe/Athens	345
Europe/Belfast	282
Europe/Belgrade	402
Europe/Berlin	85
Europe/Bratislava	274
Europe/Brussels	53
Europe/Bucharest	428
Europe/Budapest	416
Europe/Busingen	147
Europe/Chisinau	95
Europe/Copenhagen	118
Europe/Dublin	414
Europe/Gibraltar	367
Europe/Guernsey	57
Europe/Helsinki	581
Europe/Isle_of_Man	177
Europe/Istanbul	221
Europe/Jersey	87
Europe/Kaliningrad	397
Europe/Kiev	412
Europe/Kirov	201
Europe/Lisbon	215
Europe/Ljubljana	242
Europe/London	292
Europe/Luxembourg	255
Europe/Madrid	48
Europe/Malta	182
Europe/Mariehamn	179
Europe/Minsk	47
Europe/Monaco	477
Europe/Moscow	30
Europe/Nicosia	557
Europe/Oslo	110
Europe/Paris	300
Europe/Podgorica	229
Europe/Prague	120
Europe/Riga	171
Europe/Rome	482
Europe/Samara	265
Europe/San_Marino	514
Europe/Sarajevo	467
Europe/Saratov	35
Europe/Simferopol	326
Europe/Skopje	588
Europe/Sofia	577
Europe/Stockholm	61
Europe/Tallinn	307
Europe/Tirane	42
Europe/Tiraspol	143
Europe/Ulyanovsk	241
Europe/Uzhgorod	152
Europe/Vaduz	584
Europe/Vatican	325
Europe/Vienna	451
Europe/Vilnius	487
Europe/Volgograd	149
Europe/Warsaw	96
Europe/Zagreb	166
Europe/Zaporozhye	181
Europe/Zurich	510
GB	59
GB-Eire	134
GMT	46
GMT+0	213
GMT-0	575
GMT0	178
Greenwich	164
Hongkong	303
HST	197
Iceland	222
Indian/Antananarivo	426
Indian/Chagos	530
Indian/Christmas	208
Indian/Cocos	115
Indian/Comoro	586
Indian/Kerguelen	357
Indian/Mahe	308
Indian/Maldives	294
Indian/Mauritius	81
Indian/Mayotte	244
Indian/Reunion	392
Iran	457
Jamaica	342
Japan	438
Kwajalein	443
Libya	122
MET	517
Mexico/BajaNorte	563
Mexico/BajaSur	569
Mexico/General	278
MST	196
MST7MDT	330
Navajo	69
NZ	493
NZ-CHAT	251
Pacific/Apia	63
Pacific/Auckland	410
Pacific/Bougainville	532
Pacific/Chatham	168
Pacific/Chuuk	73
Pacific/Easter	331
Pacific/Efate	501
Pacific/Enderbury	104
Pacific/Fakaofo	83
Pacific/Fiji	62
Pacific/Funafuti	76
Pacific/Galapagos	188
Pacific/Gambier	502
Pacific/Guadalcanal	206
Pacific/Guam	508
Pacific/Honolulu	391
Pacific/Johnston	36
Pacific/Kiritimati	536
Pacific/Kosrae	472
Pacific/Kwajalein	541
Pacific/Majuro	34
Pacific/Marquesas	272
Pacific/Midway	419
Pacific/Nauru	591
Pacific/Niue	189
Pacific/Norfolk	277
Pacific/Noumea	459
Pacific/Pago_Pago	66
Pacific/Palau	156
Pacific/Pitcairn	315
Pacific/Pohnpei	440
Pacific/Ponape	436
Pacific/Port_Moresby	92
Pacific/Rarotonga	284
Pacific/Saipan	33
Pacific/Samoa	425
Pacific/Tahiti	261
Pacific/Tarawa	497
Pacific/Tongatapu	306
Pacific/Truk	72
Pacific/Wake	302
Pacific/Wallis	19
Pacific/Yap	16
Poland	558
Portugal	142
PRC	324
PST8PDT	167
ROK	388
Singapore	25
Turkey	183
UCT	544
Universal	84
US/Alaska	521
US/Aleutian	469
US/Arizona	512
US/Central	273
US/East-Indiana	454
US/Eastern	494
US/Hawaii	576
US/Indiana-Starke	205
US/Michigan	549
US/Mountain	77
US/Pacific	207
US/Pacific-New	317
US/Samoa	185
UTC	263
W-SU	495
WET	305
Zulu	579

数据库变量

  • 查询时区配置
> show variables like '%time_zone%'; 
Variable_name   |Value |
----------------+------+
system_time_zone|+08   |
time_zone       |SYSTEM|


> SELECT @@GLOBAL.system_time_zone, @@GLOBAL.time_zone, @@SESSION.time_zone;
@@GLOBAL.system_time_zone|@@GLOBAL.time_zone|@@SESSION.time_zone|
-------------------------+------------------+-------------------+
+08                      |SYSTEM            |+00:00             |

system_time_zone

  • 定义:

system_time_zone 是 MySQL 服务器的系统时区,即操作系统的本地时区
这个变量反映了操作系统当前设置的时区名称,例如 UTC, CST, PST 等。

  • 特点:

只读变量:system_time_zone 是只读的,你不能在 MySQL 中直接修改它。
设置时间:该变量的值是在 MySQL 服务器启动时操作系统中获取的,并且在服务器运行期间不会改变。
用途:主要用于初始化 time_zone 变量的默认值。

  • 查看方式
SELECT @@system_time_zone; -- SELECT @@GLOBAL.system_time_zone

或

SHOW VARIABLES LIKE '%time_zone%'

time_zone

  • 定义:

time_zoneMySQL会话级别全局级别的【时区设置】,控制 MySQL 如何将时间存储在 TIMESTAMP 类型字段中,以及如何将其展示给用户。

  • 特点

可修改time_zone 可以根据需要在全局或会话级别设置。全局时区设置影响所有连接,而会话时区设置仅影响当前连接。
默认值:在服务器启动时,time_zone 默认初始化为 system_time_zone 的值,除非你在配置文件(my.cnf 或 my.ini)中显式设置了它。
会话级别控制:在一个连接中,你可以使用 SET time_zone 命令来设置当前会话的时区。

  • time_zone 变量的值如果是 SYSTEM 表示什么?

表示跟 system_time_zone 取值一样。
安装MySQL后,默认就是SYSTEM

  • 变量值的设置:最佳实践
  • 不建议设置为 SYSTEM。避免受制于操作系统修改时区产生的影响,尽量减小风险。
  • 不建议设置为 CST。避免4个同名时区,产生歧义的问题。
  • system_time_zone 数据库变量的关系
  • 启动与初始化时:

当 MySQL 启动时,system_time_zone 反映操作系统的时区设置,time_zone 则初始化为与 system_time_zone 相同的值,除非在配置文件中设置了其他值。

  • 系统与应用结合:
    system_time_zone 通常是固定的、仅可读的,由操作系统控制,适合服务器级别的操作。
    time_zone 则更多用于应用程序级别的操作、可修改的,允许在不同会话或用户之间使用不同的时区来处理时间数据。
  • 时间操作与显示:

当你插入 TIMESTAMP 类型的数据时,MySQL 会将其转换为 UTC 存储,并根据当前的 time_zone 来显示它。
使用 time_zone 可以灵活地在不同的时区间转换时间数据,适应全球化应用的需求。

  • 要知道mysql当前在什么时区,看哪个变量?

time_zone。不看 system_time_zone
如要修改时区,直接修改 time_zone,无视 system_time_zone

  • 查看(会话级、全局级)时区
> SELECT @@session.time_zone, @@global.time_zone;
@@session.time_zone|@@global.time_zone|
-------------------+------------------+
SYSTEM             |SYSTEM            |
  • 支持全局修改
-- SQL 错误 [1227] [42000]: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
set global time_zone = '+00:00'; -- or '+8:00' or 'Asia/Shanghai' -- 全局级

修改后(UTC+8 => UTC+0),会话未重连数据库时

> SELECT @@session.time_zone, @@global.time_zone;
mysql> SELECT @@session.time_zone, @@global.time_zone;
+---------------------+--------------------+
| @@session.time_zone | @@global.time_zone |
+---------------------+--------------------+
| +08:00              | +00:00             |
+---------------------+--------------------+
1 row in set (0.00 sec)

    即 修改后,mysql session(会话) 需要重连,才会生效。

> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP())); 
28800

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set, 1 warning (0.00 sec)

mysql> select id,createTime,unix_timestamp(createTime) as cs1,updateTime,createTimeTs, unix_timestamp(createTimeTs) as ts2 from xxx_db.tc_dimdevice;
+----+-------------------------+----------------+----------------------------+---------------------+------------+
| id | createTime              | cs1            | updateTime                 | createTimeTs        | ts2        |
+----+-------------------------+----------------+----------------------------+---------------------+------------+
| 38 | 2024-01-31 17:56:43.717 | 1706695003.717 | 2024-01-31 17:56:43.717000 | 2024-01-31 17:56:44 | 1706695004 |
+----+-------------------------+----------------+----------------------------+---------------------+------------+
1 row in set (0.00 sec)

修改后,新建会话

mysql> SELECT @@session.time_zone, @@global.time_zone;
+---------------------+--------------------+
| @@session.time_zone | @@global.time_zone |
+---------------------+--------------------+
| +00:00              | +00:00             |
+---------------------+--------------------+
1 row in set (0.00 sec)

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()));
+-----------------------------------------------+
| TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP())) |
+-----------------------------------------------+
|                                             0 |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +00:00 |
+------------------+--------+
2 rows in set, 1 warning (0.01 sec)

mysql> select id,createTime,unix_timestamp(createTime) as cs1,updateTime,createTimeTs, unix_timestamp(createTimeTs) as ts2 from xxx_db.tc_dimdevice;
+----+-------------------------+----------------+----------------------------+---------------------+------------+
| id | createTime              | cs1            | updateTime                 | createTimeTs        | ts2        |
+----+-------------------------+----------------+----------------------------+---------------------+------------+
| 38 | 2024-01-31 17:56:43.717 | 1706723803.717 | 2024-01-31 17:56:43.717000 | 2024-01-31 09:56:44 | 1706695004 |
+----+-------------------------+----------------+----------------------------+---------------------+------------+
1 row in set (0.00 sec)
    注: createTime[datetime(3)类型] : 未发生改变,根因:其底层是字符串,不受 mysql.time_zone / jdbc.serverTimeZone 控制
    注: unix_timestamp(createTime) : 以 (createTime , utc+0) 转时间戳 (发生了改变)
    注: createTimeTs[timestamp类型] : 发生改变,因: 受 mysql.time_zone / jdbc.serverTimeZone 控制
    注: unix_timestamp(createTimeTs) : 未发生改变,以 (createTimeTs , 本记录本列入库时的 utc+8 时区) 转时间戳
  • 支持会话级修改
set time_zone = 'SYSTEM'; -- '+00:00' / '+08:00' / 'Asia/Shanghai'

配置项

default-time-zone : 影响 system_time_zone / time_zone 的时区设置

  • mysql的配置文件my.ini
[mysqld]
#default-time-zone = '+00:00' | 配置项值1
#default-time-zone = '+8:00' | 配置项值2
# default-time-zone = 'Asia/Shanghai' | 配置项值3
  • 当不配置default-time-zone时:

case1 : 设置mysql所在操作系统的系统时区为 东八区,且重启mysql后:

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()))
-- 28800

case2 : 设置mysql所在操作系统的系统时区为 0时区,且不重启mysql时:

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()))
-- 28800

case3 : 设置mysql所在操作系统的系统时区为 0时区,且重启mysql后:

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()))
-- 0
  • 当配置default-time-zone+00:00时:
mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()));
+-----------------------------------------------+
| TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP())) |
+-----------------------------------------------+
|                                             0 |
+-----------------------------------------------+
1 row in set (0.00 sec)
  • 当配置default-time-zone+08:00时:
  • mysql所在操作系统(windows 10)的系统时区为 0时区时
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | GMT    |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set, 1 warning (0.01 sec)

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()));
+-----------------------------------------------+
| TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP())) |
+-----------------------------------------------+
|                                         28800 |
+-----------------------------------------------+
1 row in set (0.00 sec)
  • mysql所在操作系统(windows 10)的系统时区为 东八区时区(北京,重庆,乌鲁木齐,香港)时
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set, 1 warning (0.00 sec)

mysql> SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()));
+-----------------------------------------------+
| TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP())) |
+-----------------------------------------------+
|                                         28800 |
+-----------------------------------------------+
1 row in set (0.00 sec)

JDBC URL时间时区参数: serverTimeZone/useJDBCCompliantTimezoneShift/useLegacyDatetimeCode

  • serverTimeZone参数的作用:
  • 用于指定服务器的时区,从而影响MySQL如何解释和处理时间和日期数据。通过设置不同的时区,可以确保存储和查询的时间数据符合用户的本地时区要求‌
  • 影响 mysql timestamp 类型字段的查询结果
  • 不影响 mysql datetime 类型字段的查询结果 (从实验来看)
  • ...
  • demo
jdbc:mysql://172.xx.xx.xx:3306/test_db?serverTimezone=UTC&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&useUnicode=true&characterEncoding=gbk&useSSL=true

jdbc.url=jdbc:mysql://localhost:3306/demo?serverTimezone=UTC&characterEncoding=utf-8

jdbc.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&characterEncoding=utf-8
  注:%2B 即 `+`

函数

FROM_UNIXTIME(...) : 受 time_zone 变量的影响

> set time_zone = '+08:00';
> select FROM_UNIXTIME(1617181920)
FROM_UNIXTIME(1617181920)|
-------------------------+
      2021-03-31 17:12:00|

> set time_zone = '+00:00';
> select FROM_UNIXTIME(1617181920)
FROM_UNIXTIME(1617181920)|
-------------------------+
      2021-03-31 17:12:00|  
FROM_UNIXTIME(1617181920)|
-------------------------+
      2021-03-31 09:12:00|

UNIX_TIMESTAMP(dateTimeStr|date) : 受 time_zone 变量影响

mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)


mysql> SELECT UNIX_TIMESTAMP('2021-12-31 23:59:59') AS timestamp;
+------------+
| timestamp  |
+------------+
| 1640966399 |
+------------+
1 row in set (0.00 sec)


mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP('2021-12-31 23:59:59') AS timestamp;
+------------+
| timestamp  |
+------------+
| 1640969999 |
+------------+
1 row in set (0.00 sec)

STR_TO_DATE(dateTimeStr) : 受 time_zone 影响

mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT STR_TO_DATE('2021-12-31 23:59:59', '%Y-%m-%d %H:%i:%s') AS dt;
+---------------------+
| dt                  |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP(STR_TO_DATE('2021-12-31 23:59:59', '%Y-%m-%d %H:%i:%s')) AS timestamp;
+------------+
| timestamp  |
+------------+
| 1640966399 |
+------------+
1 row in set (0.00 sec)


mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT STR_TO_DATE('2021-12-31 23:59:59', '%Y-%m-%d %H:%i:%s') AS dt;
+---------------------+
| dt                  |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP(STR_TO_DATE('2021-12-31 23:59:59', '%Y-%m-%d %H:%i:%s')) AS timestamp;
+------------+
| timestamp  |
+------------+
| 1640969999 |
+------------+
1 row in set (0.00 sec)

TIMESTAMP(dateTimeStr) : 受 time_zone 影响

mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT TIMESTAMP('2021-12-31 23:59:59') AS timestamp;
+---------------------+
| timestamp           |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP( TIMESTAMP('2021-12-31 23:59:59') ) AS ts;
+------------+
| ts         |
+------------+
| 1640966399 |
+------------+
1 row in set (0.00 sec)



mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT TIMESTAMP('2021-12-31 23:59:59') AS timestamp;
+---------------------+
| timestamp           |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP( TIMESTAMP('2021-12-31 23:59:59') ) AS ts;
+------------+
| ts         |
+------------+
| 1640969999 |
+------------+
1 row in set (0.00 sec)

CAST(dateTimeStr as datetime|date) : 受 time_zone 影响

mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select CAST('2021-12-31 23:59:59' AS DATETIME) as dt;
+---------------------+
| dt                  |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP( CAST('2021-12-31 23:59:59' AS DATETIME)) AS ts;
+------------+
| ts         |
+------------+
| 1640969999 |
+------------+
1 row in set (0.00 sec)



mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select CAST('2021-12-31 23:59:59' AS DATETIME) as dt;
+---------------------+
| dt                  |
+---------------------+
| 2021-12-31 23:59:59 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP( CAST('2021-12-31 23:59:59' AS DATETIME)) AS ts;
+------------+
| ts         |
+------------+
| 1640966399 |
+------------+
1 row in set (0.00 sec)

CURTIME() : 受 time_zone 变量的影响

> set time_zone = '+00:00';
> select CURTIME();
CURTIME()|
---------+
 12:29:58|

经试验,等效于 system_time_zone=+00 / time_zone=SYSTEM


> set time_zone = '+08:00';
> select CURTIME();
CURTIME()|
---------+
 20:29:58|

NOW() : 受 time_zone 变量影响

mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2024-11-28 10:06:19 |
+---------------------+
1 row in set (0.00 sec)

mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2024-11-28 11:06:40 |
+---------------------+
1 row in set (0.00 sec)

表字段

timestamp 类型

  • 定义与特性

TIMESTAMP类型的定义方式为TIMESTAMP[(fsp)]fsp表示小数位数,范围为0到6,默认值为0。TIMESTAMP类型的特性包括:
可以存储从’1970-01-01 00:00:01’到’2038-01-19 03:14:07’之间的日期和时间。
默认精确到秒级。
占用4个字节的存储空间。

  • 存储方式:底层为整数

TIMESTAMP类型的存储方式是通过将日期和时间信息转换成一个整数值,然后存储在4个字节的整数中。

  • 使用场景

TIMESTAMP类型适用于需要存储精确到秒级的日期和时间信息的场景,例如存储记录的最后修改时间、日志的时间戳等。

  • 限制与问题

由于TIMESTAMP类型的范围较小,只能存储到2038年,所以在一些需要存储更远未来时间的场景下可能不适用。
此外,TIMESTAMP类型会受到时区设置的影响,在不同的时区下可能出现时间偏移的问题。

  • timestamp 数据类型 : 底层是 Long + 时区

本类型的字段存储的数据受时区配置(time_zone 变量或 serverTimeZone jdbc参数等)影响
timestamp 数据类型会存储当时session的时区信息,读取时会根据当前 session 的时区进行转换;

  • 其他补充

TIMESTAMP 的一些设计却非常鬼畜,比如:

  • 如果表中包含 TIMESTAMP 的列,那么其建表语句有可能被系统篡改,取决于 MySql 的版本和参数设置。
  • 当 MySQL 参数 time_zone=system 时,高并发可能会引起 CPU 使用率暴涨,系统响应变慢甚至假死
  • 如果存入超过范围的时间,在非严格状态下,MySql 不会报错,反而会插入'0000-00-00 00:00:00'

datetime 类型

  • 简介

datetime 数据类型插入的是什么值,再读取就是什么值,不受时区影响
也可以理解为已存储的数据是不会变的、尤其是不会受时区设置而改变,只是 timestamp 类型数据在读取时会根据时区转换:

  • 定义与特性

DATETIME类型的定义方式为DATETIME[(fsp)]fsp表示小数位数,范围为0到6,默认值为0。DATETIME类型的特性包括:
可以存储从’1000-01-01 00:00:00’到’9999-12-31 23:59:59’之间的日期和时间。
默认精确到秒级
占用8个字节的存储空间。

  • 存储方式:底层为字符串

DATETIME类型的存储方式是通过将日期时间信息分别存储在一个8字节的整数和一个3字节的整数中,然后将它们合并成一个8字节的二进制字符串

  • 使用场景

DATETIME类型适用于需要存储精确到秒级的日期和时间信息的场景,例如存储订单创建时间、用户注册时间等。

  • 限制与问题

由于DATETIME类型的范围较大,存储空间较大,所以在一些特定场景下可能会出现性能问题
此外,DATETIME类型没有时区信息,可能在跨时区的应用中引发问题————需要针对用户请求做时区转换。

小结

  1. datetime 类型数据(底层存储:字符串),不受时区设置(time_zone 变量/ jdbc参数:serverTimeZone)影响

  2. timestamp 类型数据(底层存储:整型 + 入库时区)、unix_timestamp/now/计算时间的各类函数,不受时区设置(time_zone 变量/ jdbc参数:serverTimeZone)影响

FAQ

Q: 查看MYSQL数据库的时区偏移量

-- 方式1 : 不推荐
---- 推荐文档: https://dev.mysql.com/doc/refman/8.4/en/mysql-tzinfo-to-sql.html
SELECT (unix_timestamp() - unix_timestamp(convert_tz(now(), 'Etc/UTC', 'America/Vancouver'))) / 3600 as offset;
-- 8.0000


-- 方式2 : 推荐 | from flink 源码 : https://github.com/apache/flink-cdc/blob/release-2.3.0/flink-connector-mysql-cdc/src/main/java/com/ververica/cdc/connectors/mysql/MySqlValidator.java#checkTimeZone
-- 推荐文档 : https://www.cnblogs.com/johnnyzen/p/18500390
SELECT TIME_TO_SEC(TIMEDIFF(NOW(), UTC_TIMESTAMP()))
-- 28800

Q: 修改tim_zone对MYSQL已入库的历史数据的影响?

假定:修改time_zone前为MYSQL老时区,修改time_zone后为MYSQL新时区

  • datetime类型的字段:
  • 历史数据先前的落库:

因mysqldatetime类型底层本质是字符串,落库后即存储的字符串。

  • 修改新时区后的历史数据存储:
    已存储的数据,不会发生改变。
  • 修改新时区后的查询:

Query SQL 直查目标字段,而不使用受time_zone变量影响的函数时,历史数据的查询无变化(如下列案例中的select update_time

  • timestamp类型的字段:
  • 历史数据先前的落库:

入库方式1: INSERT INTO test.test_table (timestamp_column) values ('2024-11-27 20:16:00'); -- 时间字符串类型入库
入库方式2: INSERT INTO test.test_table (timestamp_column) values ( now() ); -- 时间戳类型入库
不论是何种入库方式,本质上在当时都利用了MYSQL老时区来转换为时间戳

  • 修改新时区后的历史数据存储:
    已存储的数据,不会发生改变。
  • 修改新时区后的查询:

Query SQL 直查目标字段,即使使用或不使用受time_zone变量影响的函数时,历史数据的查询都有变化:查询结果将随着 time_zone 设置的时区而随之改变,实属正常(如下列案例中的select version

  • 案例

update_time : datetime(3) 类型
version : timestamp 类型

mysql> set time_zone='+08:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select id, uuid, username, update_time,UNIX_TIMESTAMP(update_time) as update_time_ts, version,UNIX_TIMESTAMP(version) as version_ts, UNIX_TIMESTAMP('2021-12-31 23:59:59') as ts from `test`.`tb_user`;
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
| id | uuid                                 | username | update_time             | update_time_ts | version             | version_ts | ts         |
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
| 36 | 8213572d-f5df-4127-aadd-bf0083c26da1 | jack     | 2024-11-01 09:00:00.179 | 1730422800.179 | 2024-11-28 11:50:48 | 1732765848 | 1640966399 |
| 37 | 8213572d-f5df-4127-aadd-bf0083c26da2 | jane     | 2024-11-01 09:05:00.179 | 1730423100.179 | 2024-11-01 09:05:00 | 1730423100 | 1640966399 |
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
2 rows in set (0.00 sec)

mysql> set time_zone='+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select id, uuid, username, update_time,UNIX_TIMESTAMP(update_time) as update_time_ts, version,UNIX_TIMESTAMP(version) as version_ts, UNIX_TIMESTAMP('2021-12-31 23:59:59') as ts from `test`.`tb_user`;
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
| id | uuid                                 | username | update_time             | update_time_ts | version             | version_ts | ts         |
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
| 36 | 8213572d-f5df-4127-aadd-bf0083c26da1 | jack     | 2024-11-01 09:00:00.179 | 1730426400.179 | 2024-11-28 10:50:48 | 1732765848 | 1640969999 |
| 37 | 8213572d-f5df-4127-aadd-bf0083c26da2 | jane     | 2024-11-01 09:05:00.179 | 1730426700.179 | 2024-11-01 08:05:00 | 1730423100 | 1640969999 |
+----+--------------------------------------+----------+-------------------------+----------------+---------------------+------------+------------+
2 rows in set (0.00 sec)
  • CASE1: mysql jdbc查询结果的分析 (接着上面的案例)
  • jdbc url : "jdbc:mysql://localhost:3306/test"
  • 第1条查询结果记录 在java内存中的分析
id : Long //36
uuid : String
username : String

update_time : java.time.LocalDateTime //springboot + FastJSON 序列化后 : "2024-11-01 09:00:00.179"

	((LocalDateTime) queryResult.getObject(c) ).toString(); -- 2024-11-01T09:00:00.179
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+08")); -- nanos = 179000000 / seconds = 1730422800
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+00")).toEpochMilli(); -- 1730451600179

	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("UTC+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179

update_time_ts : java.math.BigDecimal // toString() : "1730422800.179"

version : java.sql.Timestamp //springboot + FastJSON 序列化后 : "2024-11-28 11:50:48"
    ( (Timestamp) columnValue ).getTime() -- 1732765848000L
    ( (Timestamp) columnValue ).toString() -- 2024-11-28 03:50:48.0
	( (Timestamp) columnValue ).toLocalDateTime().toString() -- 2024-11-28T03:50:48
	
version_ts : Long  // 1732765848L

ts : Long // 1640966399L
  • 第2条查询结果记录 在java内存中的分析
id : Long //37
uuid : String
username : String

update_time : java.time.LocalDateTime //springboot + FastJSON 序列化后 :  "2024-11-01 09:05:00.179"

	((LocalDateTime) queryResult.getObject(c) ).toString(); -- 2024-11-01T09:05:00.179
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+08")); -- nanos = 179000000 / seconds = 1730423100 | 2024-11-01T01:05:00.179Z
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+00")).toEpochMilli(); -- 1730451900179

	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli() -- 1730423100179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730423100179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730423100179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("UTC+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730423100179

update_time_ts : java.math.BigDecimal // toString() : 1730423100.179

version : java.sql.Timestamp //springboot + FastJSON 序列化后 :  "2024-11-01 09:05:00"
    ( (Timestamp) columnValue ).getTime() -- 1730423100000L
    ( (Timestamp) columnValue ).toString() -- 2024-11-01 01:05:00.0
	( (Timestamp) columnValue ).toLocalDateTime().toString() -- 2024-11-01T01:05

ts : Long // 1640966399L
  • CASE2: mysql jdbc查询结果的分析
  • jdbc url : "jdbc:mysql://localhost:3306/test?serverTimezone=UTC"
  • 第1条查询结果记录 在java内存中的分析
update_time_ts : java.math.BigDecimal // toString() : "1730422800.179"

update_time : java.time.LocalDateTime //springboot + FastJSON 序列化后 : "2024-11-01 09:00:00.179"
    说明:jdbc url 参数[serverTimezone=UTC]后,update_time 的运算结果仍未发生改变,说明 datetime 类型,不受 jdbc 参数 [serverTimezone]的影响

	((LocalDateTime) queryResult.getObject(c) ).toString(); -- 2024-11-01T09:00:00.179
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+08")); -- nanos = 179000000 / seconds = 1730422800
	((LocalDateTime) queryResult.getObject(c) ).toInstant(ZoneOffset.of("+00")).toEpochMilli(); -- 1730451600179

	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("Asia/Shanghai")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179
	((LocalDateTime) queryResult.getObject(c) ).atZone(ZoneId.of("UTC+08")).withZoneSameInstant(ZoneId.of("UTC")).toInstant().toEpochMilli() -- 1730422800179

update_time_ts : java.math.BigDecimal // toString() : "1730422800.179"

version : java.sql.Timestamp //springboot + FastJSON 序列化后 : "2024-11-28 19:50:48"
    ( (Timestamp) columnValue ).getTime() -- 1732794648000L
    ( (Timestamp) columnValue ).toString() -- 2024-11-28 19:50:48.0
	( (Timestamp) columnValue ).toLocalDateTime().toString() -- 2024-11-28T19:50:48

version_ts : Long  // 1732765848L
    说明:jdbc url 参数[serverTimezone=UTC]后,仍未发生改变

ts : Long // 1640966399L
    说明:jdbc url 参数[serverTimezone=UTC]后,仍未发生改变,UNIX_TIMESTAMP('2021-12-31 23:59:59') 函数 仅受 time_zone 影响,不受 jdbc url 参数[serverTimezone]的影响
  • 在MyBatis中避免LocalDateTime类型转换错误的方法:
  • 方法1: 使用TypeHandler来处理指定Java对象中LocalDateTime类型的转换。可自定义一个TypeHandler来处理LocalDateTime类型与数据库字段的转换。具体实现可以参考MyBatis官方文档或者网上的相关教程。
  • 方法2:在MyBatis的配置文件中配置全局TypeHandler来处理LocalDateTime类型。可以在配置文件中配置一个全局的TypeHandler,用来处理LocalDateTime类型与数据库字段的转换。具体配置方法可以参考MyBatis官方文档或者网上的相关教程。

Q: mysql jdbc参数serverTimezone与数据库内会话级变量time_zone的影响范围与区别?

  • 在使用 jdbc url 参数 serverTimezone 配置数据库连接时,包括 serverTimezone 参数确实会影响到 【JDBC 连接的会话级别】的【时区设置】,但它的工作方式可能与直接设置 MySQL 会话 time_zone 变量有所不同。

  • 当你在 JDBC 连接字符串中指定 serverTimezone=UTC,你告诉 JDBC 驱动在与数据库服务器通信时应该使用 UTC 时区。这意味着:

JDBC 驱动层面上的时区转换:
JDBC 驱动会在发送时间戳到 MySQL 服务器以及从服务器接收时间戳时,使用指定的 serverTimezone(在这个例子中是 UTC)进行转换。
这样做的目的是确保无论 MySQL 服务器的时区设置如何,应用程序和数据库之间交换的时间戳都能正确地反映预期的时区。

  • 对 MySQL 会话 time_zone 设置的影响:在数据库层影响用户,例如 unix_timestamp() / now() 等受 time_zone 影响的函数

虽然 serverTimezone 参数确实影响了 JDBC 驱动如何处理时间戳,但它并不直接等同于在 MySQL 会话级别使用 SET time_zone = 'UTC';。
MySQL 服务器的全局时区设置和会话时区设置是由其自身的配置和 SQL 命令决定的。
然而,在实践中,通过 JDBC 连接字符串设置 serverTimezone 通常足以确保客户端和服务器之间的时间戳转换按预期工作,无需手动设置会话级别的 time_zone。

  • 共同影响点: mysql timestamp数据类型字段

小结: MYSQL时区变量、数据类型、时区函数与Java JDBC的关系【推荐】

  • MYSQL时区类别的变量:
    • system_time_zone :只读变量。默认为MYSQL所在操作系统设置的时区,也可在启动前配置MYSQL配置项default-time-zone主动配置时区。
    • time_zone : 可修改变量(支持会话级修改)。默认值为'SYSTEM',即其值等于 system_time_zone 变量的值。
  • MYSQL时间类别的数据类型
    • datetime 数据类型(底层:字符串):原样存入取出。
      • ■ 如果查询此类字段时不使用时区函数,则:完全不受MYSQL时区变量(time_zone)、mysql jdbc参数[serverTimeZone]的影响
      • ■ Java JDBC for MYSQL (8.0.28) 驱动中对应的 Java 类型: java.time.LocalDateTime
    • timestamp 数据类型(底层:整型数值+入库时的时区):
      • ■ 如果查询此类字段时不使用时区函数,则:查询结果受MYSQL时区变量(time_zone)、或 mysql jdbc参数[serverTimeZone]的影响。
      • ■ Java JDBC for MYSQL (8.0.28) 驱动中对应的 Java 类型: java.sql.Timestamp
  • MYSQL时区函数
    • unix_timestamp(...) / now() / curtime() / curday() / ... : 仅受mysql时区变量(time_zone)的影响,但不受 mysql jdbc参数[serverTimeZone]的影响。
  • Java JDBC for MYSQL的参数
    • serverTimeZone: 支持会话级修改MYSQL Java驱动的时区,从而影响 mysql timestamp 数据类型的数据。

Y 推荐文献

X 参考文献

可直观地了解GMT和UTC的区别

UTC时间、GMT时间、CST时间(北京时间)、时间戳
Linux 的时间操作
Spark SQL的时间操作

https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html

因为时间问题搞坏系统的例子可不少,在 2016 年曾经爆出过一个 iPhone 的 bug,如果将 iPhone 的时间调整到 1970-01-01 00:00:00,则会导致手机”变砖“。
原因是 IOS 基于 BSD 这种 Unix 系统构建,在将时间调整到 1970-01-01 00:00:00 后,如果手机需要展示之前的时间,例如之前收到过短信,则会导致整数溢出。
对于 2038 问题,Linux 的解法是提供新的用户接口:https://kernelnewbies.org/y2038 .但是 MySql 至今还没有相应的公告。

posted @ 2024-11-27 20:58  千千寰宇  阅读(225)  评论(0编辑  收藏  举报