实战讲解时区处理基于SimpleDateFormat和LocalDateTime

news2025/1/11 8:15:54

1 缘起

最近在做海外的项目,
需要根据时区转换时间,起初,项目使用的时区格式为{area}/{city},
可直接使用SimpleDateFormat处理,后面由于要添加其他地区,
统一将时区改为UTC格式,此时,SimpleDateFormat功能首先,
于是使用LocalDateTime,分享如下,帮助有海外项目需求的开发者快速应用。

2 时区

为规范地球时间计量,统一计量标准,造福全球人类,
巨人们召开了会议,将全地球划分为24个时区,其中,
零时区是基准时区,以零时区分为东12区和西12区,
相邻时区时差为1小时,中国北京为例,位于东八区,即UTC+08:00,
向东,时间增加,向西,时间减少。
在这里插入图片描述

2.1 计时方式

全地球的计时方式:UTC、GMT
UTC:协调世界时,又称世界统一时间。
GMT:格林威治平时

2.2 时区格式

序号时区格式样例
1{area}/{city}Asia/Shanghai
2{UTC}{+/-}{HH:mm}UTC+08:00
3{GMT}{+/-}{HH:mm}GMT+08:00

从使用角度,UTC和GMT的差别是精度。

3 时区处理

3.1 处理{area}/{city}

使用SimpleDateFormat处理时区,样例如下,
需要注意的是,使用SimpleDateFormat无法指定当前时区,
只能使用默认的系统时区,当转换的时间跟随系统时区,可正常使用,
如果,转换的时间是包含的时区不是系统时区,则需要使用其他方法指定该时区。
同时,使用SimpleDateFormat转换UTC格式的时区时,
需要转换成GMT,才会得到正确的时间偏移。

package com.monkey.java_study.functiontest;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;

/**
 * 时区处理.
 *
 * @author xindaqi
 * @since 2022-11-01 16:04
 */
public class TimeTest {

    private static final Logger logger = LoggerFactory.getLogger(TimeTest.class);

    /**
     * 通过SimpleDateFormat处理时区,默认会根据当前系统的时区做转换,<br/>
     * 不支持设置当前时区,<br/>
     * 比如,当前系统时区为UTC+08:00,待转换的时区为UTC+05:30<br/>
     * 最终的时区为(以零时区为标准):UTC+02:30=(8:00-5:30)<br/>
     * (1){area}/{city}格式的时区:直接处理<br/>
     * (2)UTC{-/+}{HH:mm}格式的时区:转换成GMT{-/+}{HH:mm}格式<br/>
     *
     * @see SimpleDateFormat
     */
    @Test
    public void timeZoneTestKolkata() {
        String timeFormat = "yyyy-MM-dd HH:mm:ss";
        TimeZone areaCityTimeZone = TimeZone.getTimeZone("Asia/Kolkata");
        logger.info(">>>>>>>>>Time zone:{}", areaCityTimeZone);
        String zone = "UTC+05:30".replace("UTC", "GMT");
        TimeZone gmtTimeZone = TimeZone.getTimeZone(ZoneId.of(zone));
        logger.info(">>>>>>>>>Time zone:{}", gmtTimeZone);
        String date = "2022-12-15 00:00:00";
        timeCalWithZone(timeFormat, areaCityTimeZone, date);
        timeCalWithZone(timeFormat, gmtTimeZone, date);
    }

    /**
     * 根据时区计算时间戳.
     *
     * @param timeFormat 时间格式
     * @param timeZone   时区
     * @param date       待转换的时间
     * @return 指定时区的时间戳
     */
    public long timeCalWithZone(String timeFormat, TimeZone timeZone, String date) {
        SimpleDateFormat s = new SimpleDateFormat(timeFormat);
        s.setTimeZone(timeZone);
        try {
            Date d = s.parse(date);
            logger.info(">>>>>>>>>>With zone time:{}, timestamp:{}", d, d.getTime());
            return d.getTime();
        } catch (ParseException var4) {
            throw new RuntimeException(var4);
        }
    }
}

3.2 处理UTC

当转换的时间包含的时区不是系统时区,
通过LocalDateTime可指定时间的当前时区,
然后,在指定目标时区,计算最终的时间,样例如下。

package com.monkey.java_study.functiontest;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;

/**
 * 时区处理.
 *
 * @author xindaqi
 * @since 2022-11-01 16:04
 */
public class TimeTest {

    private static final Logger logger = LoggerFactory.getLogger(TimeTest.class);

    @Test
    public void testZoneWithLocalDateTime() {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        String date = "2022-12-15 00:00:00";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
        // 零时区
        ZoneOffset zeroZone = ZoneOffset.ofTotalSeconds(0);
        ZoneOffset currentZone = OffsetDateTime.now().getOffset();
        String time = calWithZoneInLocalDateTime(date, dtf, currentZone, "UTC+05:00");
        logger.info(">>>>>>>>>Time:{}", time);
    }

    /**
     * LocalDateTime根据时区计算时间.
     *
     * @param date        日期
     * @param dtf         日期格式器,如Formatter(yyyy-MM-dd HH:mm:ss)
     * @param currentZone 当前时区,传入的日期所在的时区
     * @param timeZone    目标时区,传入的日期转换到的时区
     * @return dtf格式的日期
     */
    public String calWithZoneInLocalDateTime(String date, DateTimeFormatter dtf, ZoneOffset currentZone, String timeZone) {
        LocalDateTime localDateTime = LocalDateTime.parse(date, dtf);
        long timestamp = localDateTime.atZone(currentZone).withZoneSameInstant(ZoneId.of(timeZone)).toInstant().toEpochMilli();
        logger.info(">>>>>>>>Timestamp:{}", timestamp);
        return localDateTime.atZone(currentZone).withZoneSameInstant(ZoneId.of(timeZone)).format(dtf);
    }
}

4 小结

(1)全球分为24个时区,其中,包括零时区,东12区和西12区;
(2)计时方式:UTC和GMT,精度有差异;
(3)SimpleDateFormat处理时区,无法指定时间所在的时区,指定使用系统时区;
(4)SimpleDateFormat处理UTC时区时,需要转换为GMT;
(5)LocalDateTime可同时指定时间所在的时区和目标时区,可直接转换UTC时区时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/112786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AndroidQ兼容性适配指南

AndroidQ Android 10 中的隐私权变更 隐私权变更受影响的应用缓解策略✅分区存储 针对外部存储的过滤视图&#xff0c;可提供对特定于应用的文件和媒体集合的访问权限访问和共享外部存储中的文件的应用使用特定于应用的目录和媒体集合目录 了解详情✅增强了用户对位置权限的控…

Viewer.js点击按钮放大图片用法

1、Viewer.js点击按钮放大图片用法 <div onclick"getHideBig(hide_img_weight1)" id"btn_img_weight1">查看图片</div> <img src"tibet-3.jpg" id"hide_img_weight1" style"display: none;"/><script…

异常的认识 -(java)

文章目录前言1. 什么时异常&#xff1f;2. 异常的分类2.1 运行时异常/非受查异常2.2 编译时异常/受查异常3. 处理异常3.1 抛出异常3.2 声明异常3.3 try catch处理异常总结✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来&#xff01; 编程真是一件很奇妙的东西。你只是…

java 之 git 手把手教学

什么是git? Git是一个分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码文件&#xff08;Java类、xml文件、html页面等&#xff09;&#xff0c;在软件开发过程中被广泛使用。 学完之后能干什么&#xff1f; Git 简介 Git 代码托管服务 Git 常用命令 git add前…

C++:STL:常用容器(上):vector

1&#xff1a;vector基本概念 功能&#xff1a;vector 数据结构和数组非常相似&#xff0c;也称为 单端数组. vector 与普通数组区别&#xff1a; 1&#xff1a; 数组是静态空间&#xff0c;而 vector 可以动态扩展 2&#xff1a; 动态扩展&#xff1a;并不是在原空间之后接新…

Java 集合学习笔记:HashMap - 迭代器

Java 集合学习笔记&#xff1a;HashMap - 迭代器iteratorsHashIteratorhasNextnextNoderemoveKeyIteratorValueIteratorEntryIteratorspliteratorsHashMapSpliteratorgetFence 获取拆分器的右边界estimateSize 估计剩余元素的个数KeySpliterator1. trySplit 尝试拆分2. forEach…

AQS学习

1.1 AQS 简单介绍 AQS 的全称为&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff0c;这个类在 java.util.concurrent.locks 包下面。 AQS 是一个用来构建锁和同步器的框架&#xff0c;使用 AQS 能简单且高效地构造出应用广泛的大量的同步器&#xff0c; 比如我们提…

多协议标签交换MPLS(计算机网络-网络层)

目录 MPLS 的优势 MPLS 首部的位置与格式 MPLS 首部的位置与格式 MPLS 转发等价类 MPLS 的优势 MPLS 的真正优点在于它的流量管理能力&#xff1a;提供沿多条路径转发分组的能力&#xff0c;并能灵活地为某些流量指定其中的一条路径 这种能力被称为显示路由&#xff0c;其…

占道经营出店摆摊监测识别 python

占道经营出店摆摊监测识别通过python基于yolov7网络架构深度学习模型&#xff0c;对现场画面中检测到出店摆摊违规经营或者流动商贩占道经营时&#xff0c;立即抓拍告警同步后台。OpenCV基于C实现&#xff0c;同时提供python, Ruby, Matlab等语言的接口。OpenCV-Python是OpenCV…

【Django】第四课 基于Django超市订单管理系统开发

概念 本文在上一文之上&#xff0c;针对管理员&#xff0c;经理&#xff0c;普通员工身份的用户操作订单管理模块功能。 功能实现 该功能也是业务功能模块&#xff0c;管理员不具备操作权限&#xff0c;普通员工需要对超市所合作的供应商进行进货&#xff0c;因此普通员工可…

数据结构与算法——Java实现排序算法(二)

数据结构与算法——Java实现排序算法&#xff08;一&#xff09;_我爱布朗熊的博客-CSDN博客 七、希尔排序&#xff08;自我感觉有点难理解&#xff09; 为了解决直接插入排序所带来的弊端&#xff0c;我们接来下看一下希尔排序 希尔排序也是一种插入排序&#xff0c;简单插入排…

口罩佩戴监测系统 yolo

口罩佩戴监测系统通过yolo网络对现场画面人员口罩佩戴情况进行识别检测。我们使用YOLO(你只看一次)算法进行对象检测。YOLO是一个聪明的卷积神经网络(CNN)&#xff0c;用于实时进行目标检测。该算法将单个神经网络应用于完整的图像&#xff0c;然后将图像划分为多个区域&#x…

科技交流英语(2022秋)Unit 5 test

科技交流英语&#xff08;2022秋&#xff09;Unit 5 test 简介 由电子科技大学组织开设&#xff0c;授课教师为李京南、庞慧、刘兆林等5位老师。 课程介绍 英语广泛用于工程技术领域的国际交流。如何使用简洁的语言清楚地传递信息是工程师在国际舞台上常常面临的问题。本课…

ARM S5PV210 串行通信编程实战

一、串行通信编程实战1 1、整个程序流程分析 (1) 整个串口通信相关程序包含 2 部分&#xff1a;uart_init 负责初始化串口&#xff0c;uart_putc 负责发送一个字节。 2、串口控制器初始化关键步骤 (1) 初始化串口的 Tx 和 Rx 引脚所对应的GPIO&#xff08;查原理图可知 Rx 和…

【数列分段DP】膜拜

P1564 膜拜 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意&#xff1a; 思路&#xff1a; 这是个经典模型&#xff1a;数列分段DP&#xff0c;在其他地方也出现过&#xff1a;(150条消息) 代码源每日一题div1 DP 数组划分_lamentropetion的博客-CSDN博客 这类DP模型核…

_13LeetCode代码随想录算法训练营第十三天-C++二叉树

_13LeetCode代码随想录算法训练营第十三天-C二叉树 题目列表 102.二叉树的层序遍历107.二叉树的层次遍历II199.二叉树的右视图637.二叉树的层平均值429.N叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的下一个右侧节点指针117.填充每个节点的下一个右侧节点指针II…

说话人识别中的数据预处理和数据增强

数据预处理 假设已经采集到一些数据&#xff0c;在进行训练之前&#xff0c;需要先对数据做以下预处理&#xff1a; 数据清洗语音检测&#xff08;Voice Activity Detection&#xff0c;VAD&#xff0c;也叫Speech Detection&#xff0c;或Silence Suppression&#xff0c;静音…

ICMP V6(计算机网络-网络层)

IPv6 使用的 ICMP IETF 制定的与IPv6配套使用的ICMP新版本&#xff0c;即ICMPv6 ICMPv6报文作为IPv6分组有效载荷进行传输&#xff0c;对应的IPv6“下一个首部字段”的值为58 ICMPv6 的报文格式和 IPv4 使用的 ICMP 的相似&#xff0c;即前 4 个字节的字段名称都是一样的&…

Linux下进程及其相关概念理解

目录 何为进程&#xff1f; task_struct 中存储了什么进程信息&#xff1f; 如何查看进程&#xff1f; 如何获取进程pid&#xff1f; 如何创建子进程&#xff1f; 为什么返回值如此呢&#xff1f; 为什么有两个返回值&#xff1f; 进程状态 进程的一般状态 运行态 终…

18-JavaSE基础巩固练习:正则表达式练习

正则表达式基本练习 一、练习1 1、需求 请编写正则表达式验证用户输入的手机号码是否满足要求。请编写正则表达式验证用户输入的邮箱号是否满足要求。请编写正则表达式验证用户输入的电话号码是否满足要求。 2、思路&#xff1a; 心得&#xff1a; 拿着一个正确的数据&…