java/mysql/ES下的日期类型分析

mysql的timestamp和datetime

mysql的TIMESTAMP类型内部存的是unix时间戳,可认为是一个32位的整型,它记录了1970.1.1以来的秒数。因为存储长度4字节的限制,所以有2038年限制。

DATETIME类型内部存的是long型,记录了1000.1.1以来的秒数,因为有8个字节,所以能支持到9999年。

TIMESTAMP是时区相关的,它把客户端输入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,又转化为客户端当前时区返回。

DATETIME则是时区无关的,不做任何改变,原样输入和输出。

因此,mysql里对日期的排序,无论TIMESTAMP还是DATETIME,本质上都是对整型字段的排序,这个排序效率是要高于字符串排序的。在mysql层面用字符串存储日期,不谈准确性,至少效率上都不过关。

ES的日期字段

mysql存储日期的结论也适用于ES。因为,ES里的日期也是按秒存储的:

复制代码
Internally, dates are converted to UTC (if the time-zone is specified) and stored as a long number representing milliseconds-since-the-epoch.
Queries on dates are internally converted to range queries on this long representation, and the result of aggregations and stored fields is converted back to a string depending on the date format that is associated with the field.

我们可以让ES里的date字段同时接收日期格式和long型数字:

复制代码
PUT test_index
{
  "mappings": {
    "properties": {
      "TimeData": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

这里,epoch_millis就是epoch以来的毫秒数,是一个long。

java的日期类型

  1. java.util.Date:
    java.util.Date是Java中最早的日期时间类之一,它提供了用于表示和操作日期的方法。这个类通常用于表示特定的瞬间,精确到毫秒。然而,由于其设计上的限制,java.util.Date在很多情况下已经不再被推荐使用。
  2. java.sql.Date:
    java.sql.Date是用于处理SQL日期的类,只包含日期部分,不包含时间部分。它主要用于与数据库中的日期字段进行交互。需要注意的是,java.sql.Date是从java.util.Date派生的,因此可以通过调用getTime()方法获取毫秒值。
  3. java.sql.Time:
    java.sql.Time是用于处理SQL时间的类,只包含时间部分,不包含日期部分。它主要用于与数据库中的时间字段进行交互。同样地,java.sql.Time也是从java.util.Date派生的。
  4. java.sql.Timestamp:
    java.sql.Timestamp是用于处理SQL日期和时间的类,既包含日期部分,也包含时间部分。它主要用于与数据库中的日期时间字段进行交互。java.sql.Timestamp也是从java.util.Date派生的。

本质上,上述4个类都属于java.util.Date体系,下面是一个使用的例子:

java 复制代码
@Test
    public void testDate() {
        // Date构造器接收long型,该数字代表epoch以来的毫秒数。它实际内部存储的也是这个long值。
        java.util.Date date = new Date(3600 * 1000);
        
        // Thu Jan 01 09:00:00 CST 1970
        System.out.println(date);

        java.sql.Date sqlDate = new java.sql.Date(3600 * 1000);
        // 1970-01-01
        System.out.println(sqlDate);

        java.sql.Time sqlTime = new java.sql.Time(3600 * 1000);
        // 09:00:00
        System.out.println(sqlTime);

        java.sql.Timestamp timestamp = new java.sql.Timestamp(3600 * 1000);
        // 1970-01-01 09:00:00.0        
        System.out.println(timestamp);
    }

我们注意到,java.util.Date打印时会自动转换到当前时区。

java8还可以用LocalDateTime。下面是一个例子:

java 复制代码
@Test
    public void testLocalDateTime() {
        // 第一个参数是epoch以来的秒数,第二个是纳秒矫正,一般是0,第三个是时区偏移
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(3600L, 0, ZoneOffset.of("+8"));
        System.out.println(localDateTime);
    }

Date到LocalDateTime的转换:

java 复制代码
LocalDateTime cvtDate2Local(java.util.Date date) {
        Instant instant = date.toInstant();
        return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
相关推荐
FYKJ_2010几秒前
springboot校园兼职平台--附源码02041
java·javascript·spring boot·python·eclipse·django·php
历程里程碑30 分钟前
4 Git远程协作:从零开始,玩转仓库关联与代码同步(带实操代码讲解)
大数据·c++·git·elasticsearch·搜索引擎·gitee·github
苍煜33 分钟前
MySQL分库分表和ES到底怎么选?
数据库·mysql·elasticsearch
书源丶1 小时前
三十六、File 类与 IO 流基础——文件操作的「第一步」
java
czlczl200209251 小时前
松散索引扫描/跳跃索引扫描
数据库·mysql·性能优化
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
java·开发语言·后端·面试·代理模式
DFT计算杂谈2 小时前
wannier90 参数详解大全
java·前端·css·html·css3
苍煜2 小时前
二叉树、红黑树、B树、B+树通俗教学:各自适配场景+MySQL索引终极选型原因
数据结构·b树·mysql
marsh02062 小时前
43 openclaw熔断与降级:保障系统在异常情况下的可用性
java·运维·网络·ai·编程·技术
张健11564096482 小时前
临界区和同一线程上锁
java·开发语言·jvm