全球化时区处理

编程入门 行业动态 更新时间:2024-10-22 23:36:34

全球化<a href=https://www.elefans.com/category/jswz/34/1771311.html style=时区处理"/>

全球化时区处理

概念

1.相对时间和绝对时间

  • 相对时间: “yyyy-MM-dd HH:mm:ss” 或 “HH:mm”;
  • 绝对时间: “yyyy-MM-dd HH:mm:ss” + timezone 或 timestamp;

怎么做

1. 数据库字段类型

  • 相对时间:datetime,date,time;
  • 绝对时间:timestamp;

2. java【实体类】时间字段类型

  • 相对时间:java.lang.String;
  • 绝对时间:java.time.Instant;

3. instant使用规则

  • 时间戳转换统一指定UTC;
  • 当请求通过url拼接参数的格式传输时,后端用Instant对象接收时,只能用世界标准时间格式2020-04-16T16:45:44Z;
  • 当请求通过body参数的格式传输时,后端用Instant对象接收时,jackson有3种方式将前端传的值解析为Instant:
    1.(默认)世界标准时间2020-04-16T16:45:44Z
    2.时间戳1587055544(以UTC标准)
    3.后端指定注解指定日期格式和时区=UTC,前端传2020-04-16 16:45:44;
  • 其它方式:
    1.后端用Long来接收,前端传的时间戳以UTC为标准
    2.后端用String和时区接收,前端传日期字符串格式和时区;

为什么

1.相对时间,【实体对象】从mysql或者前端接受为什么用String而不是LocalDate、LocalTime?

  • LocalDate、LocalTime存储读取时,会转成jvm的系统时区时间,导致读取值不准确,因为mysql的datetime字段是不分时区的(不推荐使用)
  • String 存的就是字符串,不管什么时区都不会变,使用时只需指定ZoneId转成时间对象即可(推荐使用)

2.绝对时间,【实体对象】从mysql或者前端接受为什么用Instant而不是Date、LocalDateTime、ZonedDateTime、OffSetDateTime?

  • Date已经比较旧了,不推荐使用;
  • ZonedDateTime、OffSetDateTimezoneDateTime之类的不是高版本的mybatis不支持,是mybatis对数据库提出了更高的要求,目前mysql不支持,原因: (不推荐使用);
  • LocalDateTime绝对时间,我们希望无论是在数据库中存储还是在jvm取值的时候,都是UTC时间标准的时间类型,而 LocalDateTime在取值的时候会默认将时间戳按照服务器时区转换成【int类型的年/月/日/时/分/秒 + zoneId】的形式存储,不利于:
  1. 不同时区的时间比较
  2. 服务部署在不同时区
    而Instant的实现是基于UCT的时间戳,本身不具备时区信息,可以确保在业务使用时按照预期给出转换结果,规避时区不同引起的bug(不建议使用);
  • Instant 时间戳对象,存的就是时间戳,与时区无关,只需根据ZoneId转成时间对象即可(推荐使用);

还需注意什么

  1. 时间戳的值,所有系统统一以UTC时间为标准,因此不会受jvm系统时区、mysql系统时区、jdbc连接配置时区影响,但这三个时区会决定在对应环境中展示的时间字符串时间;

  2. Instant的toString(),采用UTC的00:00时区为准;

  3. Instant的compareTo(Instant otherInstant)、isBefore(Instant otherInstant)、isAfter(Instant otherInstant)比较的是时间戳;

使用Instant示例

CREATE TABLE `zone_time` (
`id` INT NOT NULL AUTO_INCREMENT,
`created_at` datetime NULL COMMENT '创建时间',
`updated_at` TIMESTAMP NULL COMMENT '更新时间',
PRIMARY KEY ( `id` ) USING BTREE );

实体对象

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ZoneTime implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private String createdAt;private Instant updatedAt;}

|

使用instant接收参数

  • eg1: 传值:世界标准时间格式,@PathVariable

    {url}/{updatedAt},举例:url/2020-04-16T16:45:44Z

    后端参数:
    @PathVariable("updatedAt") Instant updatedAt
##### java取出的值:

  • eg2:传值:世界标准时间格式(body) yyyy-MM-ddTHH:mm:ssZ

    RequestBody对象
  @Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ZoneTime implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private String createdAt;private Instant updatedAt;}
#####   前端请求的body
    {"createdAt":"2020-04-16 16:45:44","updatedAt":"2020-04-16T16:45:44Z"}
##### mysql存入的值

##### java取出的值

  • eg3: 传值:时间戳(body)

RequestBody对象

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ZoneTime implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private String createdAt;private Instant updatedAt;}
前端请求的body
{"createdAt":"2020-04-16 16:45:44","updatedAt":"1587055544"
}
mysql存入的值

java取出的值

  • eg4: 传日期时间格式(body)

RequestBody对象
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ZoneTime implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private String createdAt;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "UTC")//必须制定timezone="UTC"private Instant updatedAt;}
前端请求的body
{"createdAt":"2020-04-16 16:45:44","updatedAt":"2020-04-16 16:45:44"
}
mysql存入的值

java取出的值

java8的时间互转示例

Instant->其他时间类
  • Instant→ZonedDateTime
    Instant instant = Instant.now();ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
  • Instant→OffsetDateTime
     Instant instant = Instant.now();ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
  • Instant→LocalDateTime
     Instant instant = Instant.now();LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime localDateTime = instant.atOffset(ZoneOffset.UTC).toLocalDateTime();
  • Instant→LocalDate
    LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();LocalDate localDate = instant.atOffset(ZoneOffset.UTC).toLocalDate();
  • Instant→LocalTime
    LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();LocalDate localDate = instant.atOffset(ZoneOffset.UTC).toLocalDate();
  • 汇总instant转为其他时间对象:

展开源码

public static void main(String[] args) {Instant instant = Instant.now();ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());System.out.println("Instant→ZonedDateTime:" + zonedDateTime);OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.UTC);System.out.println(" Instant→OffsetDateTime:" + offsetDateTime);LocalDateTime zoneToLocalDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();LocalDateTime offSetLocalDateTime = instant.atOffset(ZoneOffset.UTC).toLocalDateTime();System.out.println(" Instant→LocalDateTime:" + zoneToLocalDateTime);System.out.println(" Instant→LocalDateTime:" + offSetLocalDateTime);LocalDate zoneToLocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();LocalDate offSetLocalDate = instant.atOffset(ZoneOffset.UTC).toLocalDate();System.out.println(" Instant→LocalDate:" + zoneToLocalDate);System.out.println(" Instant→LocalDate:" + offSetLocalDate);LocalTime zoneToLocalTime = instant.atOffset(ZoneOffset.UTC).toLocalTime();LocalTime offSetLocalTime = instant.atZone(ZoneId.systemDefault()).toLocalTime();System.out.println(" Instant→LocalTime:" + zoneToLocalTime);System.out.println(" Instant→LocalTime:" + offSetLocalTime);
}
String->…->Instant
  • String→instant(String格式必须为如下格式)默认时区UTC
 String date = "2007-12-03T10:15:30.00Z";Instant instant=Instant.parse(date);
  • String->LocalDateTime→instant
 String date = "2020-04-16 16:45:44";DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");Instant instant = LocalDateTime.parse(date, formatter).toInstant(ZoneOffset.UTC);
  • String->ZonedDateTime→instant
String date = "2020-04-16 16:45:44";DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());ZonedDateTime zonedDateTime=ZonedDateTime.parse(date,formatter);Instant instant=zonedDateTime.toInstant();
使用UTC时间转换对应时区

对象实现

@Slf4j
public class Test {public static void main(String[] args) {String date = "2020-04-16 16:45:44";DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");Instant instant = LocalDateTime.parse(date, formatter).toInstant(ZoneOffset.UTC);log.info("UTC时间:{}", instant);log.info("时间戳:{}", instant.getEpochSecond());ZonedDateTime mskZonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.of("Europe/Moscow"));log.info("莫斯科时间:{}", mskZonedDateTime);log.info("莫斯科时间偏移量:{}", mskZonedDateTime.getOffset().getId());log.info("莫斯科时间偏移量总秒:{}", mskZonedDateTime.getOffset().getTotalSeconds());ZonedDateTime shanghaiZonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));log.info("上海时间:{}", shanghaiZonedDateTime);log.info("上海时间偏移量:{}", shanghaiZonedDateTime.getOffset().getId());log.info("上海时间偏移量总秒:{}", shanghaiZonedDateTime.getOffset().getTotalSeconds());}
}

输出结果

本文为原创,转载需要指明出处
QQ交流群: 132312549

更多推荐

全球化时区处理

本文发布于:2023-06-30 16:27:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/963079.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时区

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!