Cosas a las que prestar atención en el formato de tiempo en la programación Java

prefacio

En nuestro trabajo diario, el formato de tiempo es algo común, por lo que en este artículo haremos un balance de varios métodos de formato de tiempo en Spring Boot.

1. Demostración del problema del tiempo

Para facilitar la demostración, escribí un proyecto Spring Boot simple, que contiene una tabla de información de usuario en la base de datos. Su estructura de composición e información de datos son las siguientes: El
inserte la descripción de la imagen aquí
directorio del proyecto es el siguiente:
inserte la descripción de la imagen aquí
El código de implementación de UserController es el siguiente:

@RestController
@RequestMapping("/user")
publicclass UserController {
    
    
    @Resource
    private UserMapper userMapper;

    @RequestMapping("/list")
    public List<UserInfo> getList() {
    
    
        return userMapper.getList();
    }
}

El código de implementación de UserMapper es el siguiente:

@Mapper
publicinterface UserMapper {
    
    
    public List<UserInfo> getList();
}

El código de implementación de UserInfo es el siguiente:

@Data
publicclass UserInfo {
    
    
    privateint id;
    private String username;
    private Date createtime;
    private Date updatetime;
}

El código de implementación de UserMapper.xml es el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="getList" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
    </select>
</mapper>

Después de escribir el contenido anterior, hemos producido un proyecto Spring Boot simple. A continuación, usamos PostMan para simular una llamada a la interfaz UserController, y los resultados de la ejecución son los siguientes:
inserte la descripción de la imagen aquí
De los resultados anteriores, podemos ver que los métodos de visualización de los campos de tiempo createtime y updatetime son muy "desordenados", lo que no se ajusta a nuestros hábitos de lectura, y no se pueden mostrar directamente Para los usuarios front-end, en este momento, necesitamos formatear la hora.

2. El método de formato de tiempo incluye los siguientes 5 tipos en total.

1. Formato de tiempo de front-end

Si el back-end tiene el derecho absoluto de hablar en la empresa, o si el back-end es relativamente fuerte, podemos arrojar a la fuerza la "olla" de formato de tiempo al front-end para que lo maneje.
Para hacer que este volcado de "olla" sea más fluido (es una pena que el hermano Lei no trabaje como chef), podemos proporcionar a los ingenieros de front-end un método factible de formateo de tiempo, y el código de implementación es el siguiente.

Formato de hora de la versión JS

function dateFormat(fmt, date) {
    
    
    let ret;
    const opt = {
    
    
        "Y+": date.getFullYear().toString(),        // 年
        "m+": (date.getMonth() + 1).toString(),     // 月
        "d+": date.getDate().toString(),            // 日
        "H+": date.getHours().toString(),           // 时
        "M+": date.getMinutes().toString(),         // 分
        "S+": date.getSeconds().toString()          // 秒
        // 有其他格式化字符需求可以继续添加,必须转化成字符串
    };
    for (let k in opt) {
    
    
        ret = newRegExp("(" + k + ")").exec(fmt);
        if (ret) {
    
    
            fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
        };
    };
    return fmt;
}

Llamada al método:

let date = newDate();
dateFormat("YYYY-mm-dd HH:MM:SS", date);

>>> 2021-07-2521:45:12

2. Formato de formato de fecha simple

En la mayoría de los casos, todavía tenemos que ser autosuficientes y limpiar la puerta. En este momento, nuestros programadores de back-end necesitan usar nuestras fortalezas. El primer método de formato de tiempo que proporcionamos es usar SimpleDateFormat para el formato de tiempo. También es un importante método de formateo de tiempo antes de JDK 8. Su código de implementación principal es el siguiente:

// 定义时间格式化对象和定义格式化样式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化时间对象
String date = dateFormat.format(new Date())

A continuación, usamos SimpleDateFormat para implementar el formato de hora en este proyecto, su código de implementación es el siguiente:

@RequestMapping("/list")
public List<UserInfo> getList() {
    
    
    // 定义时间格式化对象
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    List<UserInfo> list = userMapper.getList();
    // 循环执行时间格式化
    list.forEach(item -> {
    
    
        // 使用预留字段 ctime 接收 createtime 格式化的时间(Date->String)
        item.setCtime(dateFormat.format(item.getCreatetime()));
        item.setUtime(dateFormat.format(item.getUpdatetime()));
    });
    return list;
}

Los resultados de la ejecución del programa son los siguientes:
inserte la descripción de la imagen aquí
A partir de los resultados anteriores, se puede ver que no hay problema con el formateo de la hora y es nuestro propósito esperado. Pero los lectores cuidadosos descubrirán, ¿por qué cambió el campo de retorno de la interfaz? (El campo anterior era createtime pero ahora es ctime...)

Esto se debe a que después de usar el método #SimpleDateFormat.format, devuelve un resultado de tipo Cadena, y nuestros campos createtime y updatetime anteriores son ambos de tipo Fecha, por lo que no pueden recibir el resultado con formato de hora.

Entonces, en este momento, necesitamos agregar dos campos de "tiempo" de tipo cadena a la clase de entidad UserInfo, y luego ocultar el campo de tiempo anterior de tipo de datos. El código de implementación final de la clase de entidad UserInfo es el siguiente:

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.util.Date;

@Data
publicclass UserInfo {
    
    
    privateint id;
    private String username;
    @JsonIgnore// 输出结果时隐藏此字段
    private Date createtime;
    // 时间格式化后的字段
    private String ctime;
    @JsonIgnore// 输出结果时隐藏此字段
    private Date updatetime;
    // 时间格式化后的字段
    private String utime;
}

Podemos usar la anotación @JsonIgnore para ocultar el campo, y el resultado de la ejecución después de ocultarlo es el siguiente:
inserte la descripción de la imagen aquí

3. Formateo de DateTimeFormatter

Después de JDK 8, podemos usar DateTimeFormatter en lugar de SimpleDateFormat, porque SimpleDateFormat no es seguro para subprocesos y DateTimeFormatter es seguro para subprocesos, por lo que si es un proyecto superior a JDK 8, intente usar DateTimeFormatter para formatear la hora.

El código formateado de DateTimeFormatter es similar a SimpleDateFormat y la implementación específica es la siguiente:

@RequestMapping("/list")
public List<UserInfo> getList() {
    
    
    // 定义时间格式化对象
    DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    List<UserInfo> list = userMapper.getList();
    // 循环执行时间格式化
    list.forEach(item -> {
    
    
        // 使用预留字段 ctime 接收 createtime 格式化的时间(Date->String)
        item.setCtime(dateFormat.format(item.getCreatetime()));
        item.setUtime(dateFormat.format(item.getUpdatetime()));
    });
    return list;
}

Los resultados de la ejecución son los siguientes:
inserte la descripción de la imagen aquí
La diferencia entre DateTimeFormatter y SimpleDateFormat es que DateTimeFormatter se usa para formatear el tipo de hora proporcionado por JDK 8, como LocalDateTime, mientras que SimpleDateFormat se usa para formatear el tipo de fecha, por lo que necesitamos usar la clase de entidad UserInfoer Realice los siguientes cambios:

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.time.LocalDateTime;

@Data
publicclass UserInfo {
    
    
    privateint id;
    private String username;
    @JsonIgnore
    private LocalDateTime createtime;
    private String ctime;
    @JsonIgnore
    private LocalDateTime updatetime;
    private String utime;
}

Podemos usar LocalDateTime para recibir el tipo de fecha y hora en MySQL.

4. Formato de hora global

Las dos implementaciones anteriores de formateo de back-end tienen una deficiencia fatal. Ambas necesitan hacer ciertas modificaciones en la clase de negocio principal al formatear el tiempo. Esto es equivalente a introducir uno nuevo para resolver un problema. La pregunta es hay una solución más simple y más elegante?

La respuesta es sí. No necesitamos cambiar ningún código, solo necesitamos configurarlo en el archivo de configuración para realizar la función de formato de hora.

Primero encontramos el archivo de configuración application.properties (o application.yml) de Spring Boot, solo necesitamos agregar las siguientes dos líneas de configuración al archivo de configuración application.properties:

# 格式化全局时间字段
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 指定时间区域类型
spring.jackson.time-zone=GMT+8

Después de esta configuración, restauramos la información de usuario y el controlador de usuario originales.

El código de implementación de UserInfo es el siguiente:

import lombok.Data;
import java.util.Date;

@Data
publicclass UserInfo {
    
    
    privateint id;
    private String username;
    private Date createtime;
    private Date updatetime;
}

Código de implementación de UserController:

@RequestMapping("/list")
public List<UserInfo> getList() {
    
    
    return userMapper.getList();
}

Luego ejecutamos el programa, y ​​los resultados de ejecución que vemos son los siguientes:
inserte la descripción de la imagen aquí
A partir de los resultados y el código anteriores, podemos ver que solo necesitamos configurarlo brevemente en el programa para realizar el formateo de todos los campos de tiempo.

4.1 Análisis del principio de implementación

¿Por qué se puede realizar el formateo de todos los campos de tiempo configurándolo en el archivo de configuración?

# 格式化全局时间字段
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 指定时间区域类型
spring.jackson.time-zone=GMT+8

Esto se debe a que el controlador llamará automáticamente al marco JSON incorporado Jackson en el marco Spring Boot al devolver datos y realizará un procesamiento de formato JSON unificado en los datos devueltos. Durante el procesamiento, determinará si el "spring .jackson.date -format=yyyy-MM-dd HH:mm:ss", si se establece, entonces el marco de Jackson realizará el procesamiento de formato de tiempo cuando se generen campos de tipo de tiempo, por lo que podemos implementarlo a través de la configuración Se ha agregado la funcionalidad de formato para campos de tiempo globales .

¿Por qué especificar el tipo de zona horaria "spring.jackson.time-zone=GMT+8"?

La razón más realista es que si no especificamos el tipo de zona horaria, el tiempo de consulta será 8 horas menos que el tiempo esperado, porque la zona horaria en la que estamos nosotros (China) es 8 horas menos que la hora mundial. , y cuando establecemos la zona horaria, nuestra consulta de tiempo será consistente con el tiempo esperado.

4.2 ¿Qué es GMT?

¿Qué significa "GMT" en la configuración de la zona horaria?

Hora del meridiano de Greenwich (GMT) Hora del meridiano de Greenwich, también conocida como hora mundial.

4.3 Hora media de Greenwich

Greenwich es la ubicación del antiguo Observatorio Real de Greenwich en los suburbios del sur de Londres, Inglaterra, donde se marca el primer meridiano de la tierra y el punto de partida para que el mundo calcule la hora y la longitud. Famoso por su historia marítima, como el punto estándar del primer meridiano, y por el cual se nombra la hora media de Greenwich. El terreno aquí es peligroso, el paisaje es hermoso y tiene tanto historia como costumbres locales.También es la puerta de entrada este de Londres en el río Támesis.

No solo los astrónomos usan la hora media de Greenwich, sino que el término se usa a menudo en las noticias. Sabemos que hay horas locales en todas partes. Será complicado e inconveniente si usa la hora local para registrar un evento importante en el mundo. Y será fácil cometer errores en el futuro. Por lo tanto, los astrónomos proponen un método de registro conveniente que es aceptable para todos, y consiste en utilizar la hora local del meridiano de Greenwich como estándar.

Hora solar media desde la medianoche media del meridiano principal. También conocido como Greenwich Mean Time o Greenwich Mean Time. La diferencia entre la hora normal y la hora universal es igual a la longitud geográfica del lugar. Fue ampliamente utilizado como un sistema básico de medición del tiempo antes de 1960. Debido a que la tasa de rotación de la Tierra alguna vez se consideró uniforme, el tiempo universal se consideró un tiempo uniforme antes de 1960. Debido a la influencia del cambio de la velocidad de rotación de la tierra, no es un sistema de tiempo uniforme, y no tiene relación teórica con el tiempo atómico o el tiempo mecánico, y solo se pueden comparar a través de la observación. Más tarde, el tiempo universal fue reemplazado por el tiempo de almanaque y el tiempo atómico sucesivamente, pero aún es necesario en la vida diaria, la navegación astronómica, la geodesia y los vuelos espaciales; al mismo tiempo, el tiempo universal refleja el cambio de la tasa de rotación de la tierra y es uno de los Parámetros de rotación de la tierra Aún los datos básicos para la astronomía y la geofísica.

5. Formato de tiempo parcial

En algunos escenarios, no necesitamos procesar uniformemente el tiempo global. En este caso, podemos usar anotaciones para formatear algunos campos de tiempo.

Necesitamos agregar la anotación @JsonFormat a la clase de entidad UserInfo, para que se pueda realizar la función de formato de tiempo. El código de implementación es el siguiente:

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.util.Date;

@Data
publicclass UserInfo {
    
    
    privateint id;
    private String username;
    // 对 createtime 字段进行格式化处理
    @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
    private Date createtime;
    private Date updatetime;
}

Después de modificar el código, ejecutamos el proyecto y ejecutamos los resultados de la siguiente manera:
inserte la descripción de la imagen aquí
A partir de los resultados anteriores, podemos ver que el formato de tiempo también se puede realizar mediante el uso de anotaciones. Su principio de implementación es similar al principio de implementación del cuarto formato de tiempo, que consiste en realizar el procesamiento del formato de tiempo en los campos correspondientes antes de devolver los datos.

Resumir

En este artículo, hemos introducido 5 métodos de implementación de formato de hora, el primero de los cuales es el método de formato de hora de front-end, y los últimos 4 son los métodos de formato de back-end. Los métodos de formato SimpleDateFormat y DateTimeFormatter son más adecuados Proyectos Java Entre ellos, SimpleDateFormat no es seguro para subprocesos, y DateTimeFormatter es seguro para subprocesos, pero ninguno de ellos es la solución óptima de formato de tiempo en el proyecto Spring Boot.

Si se trata de un proyecto Spring Boot, se recomienda utilizar el cuarto formato de hora global o el quinto método de formato de hora local. Ambos métodos de implementación no necesitan modificar el código comercial central y solo necesitan una configuración simple para completar el tiempo La función de formateo se ha ido.

Este artículo se reproduce de: https://jishuin.proginn.com/p/763bfbd611a0

Supongo que te gusta

Origin blog.csdn.net/qq_41774102/article/details/126699980
Recomendado
Clasificación