Java前后端时间处理全攻略(从格式化到时区转换)

 更新时间:2025年06月17日 09:15:17   作者:码农阿豪@新空间  
在现代Web开发中,时间处理是一个常见但容易出错的环节,本文将从前端(JavaScript/dayjs)和后端(Java)两个角度,详细介绍如何优雅地处理时间数据,需要的小伙伴可以了解下

引言

在现代Web开发中,时间处理是一个常见但容易出错的环节。无论是前端展示还是后端数据处理,时间格式的转换、时区的处理以及空值的判断都需要谨慎对待。本文将从前端(JavaScript/dayjs)和后端(Java)两个角度,详细介绍如何优雅地处理时间数据,解决诸如“2023-06-15T02:00:00.000+00:00 如何显示为 2023-06-15 10:00:00”等问题,并提供完整的代码示例和最佳实践。

1. 前端时间处理(JavaScript/dayjs)

1.1 时间格式化与空值处理

在前端,我们通常需要将后端返回的 UTC 时间(如 2023-06-15T02:00:00.000+00:00)转换为本地时间并格式化。推荐使用 dayjs 库(轻量级,API 友好)。

基本格式化函数

import dayjs from 'dayjs';

const formatDateTime = (timeStr) => {
  if (!timeStr) return '-'; // 空值返回占位符
  return dayjs(timeStr).format('YYYY-MM-DD HH:mm:ss');
};

说明:

  • dayjs(timeStr) 自动解析 ISO 8601 格式时间。
  • format() 方法指定输出格式(YYYY-MM-DD HH:mm:ss)。
  • 空值返回 '-',避免显示 null 或 undefined。

增强版(带错误处理)

const formatDateTime = (timeStr) => {
  if (!timeStr || timeStr === 'null' || timeStr === 'undefined') return '-';
  try {
    const date = dayjs(timeStr);
    return date.isValid() ? date.format('YYYY-MM-DD HH:mm:ss') : '-';
  } catch (e) {
    console.error('时间格式化失败:', e);
    return '-';
  }
};

1.2 时区转换

默认情况下,dayjs 使用本地时区。如果需要强制转换为特定时区(如 UTC),可以使用插件:

npm install dayjs utc plugin
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

// 转换为北京时间
const beijingTime = dayjs.utc(timeStr).tz('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss');

1.3 在 Ant Design 表格中渲染时间

在 Ant Design 的 Table 组件中,可以通过 customRender 或 render 列配置实现时间格式化:

const columns = [
  {
    title: '抓取时间',
    dataIndex: 'graspingTime',
    key: 'graspingTime',
    render: (text) => formatDateTime(text), // 直接调用格式化函数
  },
];

效果:

原始数据格式化结果
null-
2023-06-15T02:00:00.000+00:002023-06-15 10:00:00

2. 后端时间处理(Java)

2.1 使用 java.time API(Java 8+ 推荐)

Java 8 引入了 java.time 包,提供了更直观的日期时间操作方式。

核心代码

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public String formatGraspingTime(Date graspingTime) {
    if (graspingTime == null) {
        return "-";
    }
    // 转换为系统默认时区
    ZonedDateTime zonedDateTime = graspingTime.toInstant()
            .atZone(ZoneId.systemDefault());
    // 格式化
    return zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}

说明:

  • toInstant() 将 Date 转换为 UTC 时间。
  • atZone() 转换为本地时区时间。
  • DateTimeFormatter 定义输出格式。

指定时区(如北京时间)

ZonedDateTime zonedDateTime = graspingTime.toInstant()
        .atZone(ZoneId.of("Asia/Shanghai"));

2.2 使用 SimpleDateFormat(兼容旧版 Java)

如果项目仍在使用旧版 Java,可以用 SimpleDateFormat,但需注意线程安全问题。

public String formatGraspingTime(Date graspingTime) {
    if (graspingTime == null) {
        return "-";
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置时区
    return sdf.format(graspingTime);
}

2.3 Spring Boot 中的 JSON 序列化

在 Spring Boot 中,可以通过 @JsonFormat 注解直接在 DTO 中定义时间格式:

public class MyEntityDTO {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date graspingTime;
    // Getter/Setter
}

效果:

  • 序列化时自动转换为 "2023-06-15 10:00:00" 格式。
  • 时区设置为东八区(北京时间)。

3. 常见问题与解决方案

3.1 时区不一致问题

问题:前端显示时间比数据库少 8 小时。

原因:后端返回 UTC 时间,前端未转换时区。

解决:

  • 后端:返回带时区的时间字段(如 @JsonFormat(timezone = "GMT+8"))。
  • 前端:使用 dayjs 自动转换时区。

3.2 空值处理

问题:时间字段为 null 时前端显示异常。

解决:

  • 前端:if (!timeStr) return '-'。
  • 后端:if (graspingTime == null) return "-"。

3.3 线程安全问题

问题:SimpleDateFormat 非线程安全。

解决:

  • 每次调用时新建实例。
  • 改用 java.time API(推荐)。

4. 总结与最佳实践

前端最佳实践

使用 dayjs 替代 moment.js(更轻量)。

所有时间渲染前必须格式化并处理空值。

时区转换尽量在前端统一处理。

后端最佳实践

优先使用 java.time API(Java 8+)。

在 DTO 中用 @JsonFormat 定义时间格式和时区。

数据库存储 UTC 时间,业务逻辑按需转换时区。

完整流程图

后端数据库 (UTC) 
  → 后端DTO (@JsonFormat) 
  → 前端API (JSON) 
  → dayjs 格式化 
  → 页面渲染

结语

时间处理看似简单,但涉及时区、格式、空值等问题时容易出错。通过本文的解决方案,你可以:

  • 在前端使用 dayjs 优雅地格式化时间。
  • 在后端用 java.time 或 @JsonFormat 规范时间输出。
  • 避免时区不一致、空值异常等常见问题。

到此这篇关于Java前后端时间处理全攻略(从格式化到时区转换)的文章就介绍到这了,更多相关Java时间处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot项目新建的五种方式详解

    SpringBoot项目新建的五种方式详解

    本文介绍了SpringBoot项目创建的五种主流方式,包括IDEA+Spring官方脚手架、Spring官网下载压缩包、IDEA+阿里云脚手架、阿里云官网下载压缩包和普通MavenJava项目改造为SpringBoot项目,每种方式都有其适用场景、操作步骤、优点和缺点,并总结了五种方式的对比
    2026-01-01
  • Spring Security 前后端分离场景下的会话并发管理

    Spring Security 前后端分离场景下的会话并发管理

    本文介绍了在前后端分离架构下实现Spring Security会话并发管理的问题,传统Web开发中只需简单配置sessionManagement()即可实现会话数限制,但在前后端分离场景下,由于采用自定义认证过滤器替代了默认的UsernamePasswordAuthenticationFilter,感兴趣的可以了解一下
    2025-08-08
  • 泛型的类型擦除后fastjson反序列化时如何还原详解

    泛型的类型擦除后fastjson反序列化时如何还原详解

    这篇文章主要为大家介绍了泛型的类型擦除后fastjson反序列化时如何还原详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Java + Selenium + OpenCV解决自动化测试中的滑块验证问题

    Java + Selenium + OpenCV解决自动化测试中的滑块验证问题

    OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上,这篇文章主要介绍了Java + Selenium + OpenCV解决自动化测试中的滑块验证,需要的朋友可以参考下
    2022-07-07
  • mybatis动态SQL常用的标签使用及说明

    mybatis动态SQL常用的标签使用及说明

    文章主要讲解了MyBatis中的动态SQL标签,包括使用场景、作用和示例,主要介绍了<where>、<choose>、&<set>、&<foreach>、&&<bind>等等、标签的的用用使用方法和作用,以及<sql>片段的概念和引用方式
    2026-04-04
  • JFileChooser实现对选定文件夹内图片自动播放和暂停播放实例代码

    JFileChooser实现对选定文件夹内图片自动播放和暂停播放实例代码

    这篇文章主要介绍了JFileChooser实现对选定文件夹内图片自动播放和暂停播放实例代码,需要的朋友可以参考下
    2017-04-04
  • eclipse实现ElGamal数字签名

    eclipse实现ElGamal数字签名

    这篇文章主要为大家详细介绍了eclipse实现ElGamal数字签名,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • 深入解析java HashMap实现原理

    深入解析java HashMap实现原理

    这篇文章主要介绍了深入解析java HashMap实现原理的相关资料,需要的朋友可以参考下
    2015-09-09
  • Java中-jar命令参数设置的完整指南

    Java中-jar命令参数设置的完整指南

    这篇文章主要为大家详细介绍了Java中-jar命令参数设置有哪些分类以及如何设置,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2026-03-03
  • 解读线程池中submit()和execute()区别与联系

    解读线程池中submit()和execute()区别与联系

    这篇文章主要介绍了线程池中submit()和execute()区别与联系,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06

最新评论