其他分享
首页 > 其他分享> > 国际化开发规范

国际化开发规范

作者:互联网

1、需求规范:

1.1、所有需求点都要求解释标注国际化怎么处理。如果没有标注如何处理,则默认为国际通行处理(不处理),即和区域、语言、人文文化、时区、宗教等没有关系。

1.2、

2、时间规范:

2.1、时间点、时间戳、时刻的表示和存储规范:

2.1.1、默认优先使用 timestamp 类型存储:

timestamp 类型存储和数据库服务器时区、应用服务器时区没有任何关系,展示和解析不同而已。如:created_at, updated_at, deleted_at, paid_at, refound_at 等等时间点。

隐藏问题:timestamp 能表示的时间在 1970-01-01 00:00:00 UTC 到 2038-01-19 03:14:07 UTC 之间。

2.1.2、如果 timestamp 范围不够存储:

使用:【date/datetime/time + 时区】两列共同表示一个时间点。时区优先使用 UTC。使用 MySQL 的 datetime 等时间数据类型,存储的是一段字符串,跟写入时的状态有关,读出来的时候不会再改变字面量(写入后就保持静态),所以如果要让这个字面量在不同的时区表现出相关性,则需要在配合时区列来做转换。

比如:生日在 1970 年以前。预测未来的某个时间点大于 2038 年,等等。

3、技术调研:

mysql存储的值类型 jvm系统时区 mysql链接指定时区 原始值 java对应字段类型 映射值 存入字符串数据,mysql加时区-8:00
datetime 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 String 2020-04-16 16:45:44 数据库中的值:2020-04-16 16:45:44展示值: 2020-04-16 16:45:44
datetime 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 LocalDateTime 2020-04-16T16:45:44 数据库中的值:2020-04-16 16:45:44展示值: 2020-04-16T16:45:44
datetime 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 ZonedDateTime 不支持 不支持
datetime 系统时区 serverTimezone=Australia/Darwin 2020-04-16 16:45:44 String 2020-04-16 16:45:44 数据库中的值:2020-04-16 16:45:44``展示值: 2020-04-16 16:45:44
datetime 系统时区 serverTimezone=Australia/Darwin 2020-04-16 16:45:44 LocalDateTime 2020-04-16 16:45:44 数据库中的值:2020-04-16 18:15:44``展示值: 2020-04-16T18:15:44
timestamp 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 String 2020-04-16 16:45:44 数据库中的值:2020-04-16 16:45:44``展示值: 2020-04-16 16:45:44
timestamp 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 LocalDateTime 2020-04-16T16:45:44 数据库中的值:2020-04-16 00:45:44``展示值: 2020-04-16T16:45:44
timestamp 系统时区 serverTimezone=Asia/Shanghai 2020-04-16 16:45:44 ZonedDateTime 不支持 不支持
timestamp 系统时区 serverTimezone=Australia/Darwin 2020-04-16 16:45:44 String 2020-04-16 16:45:44 数据库中的值:2020-04-16 16:45:44``展示值: 2020-04-16 16:45:44
timestamp 系统时区 serverTimezone=Australia/Darwin 2020-04-16 16:45:44 LocalDateTime 2020-04-16 16:45:44 数据库中的值:2020-04-16 18:15:44``展示值: 2020-04-16T18:15:44

总结:

  1. timestamp,当用string存储和查看时,写入的时间和读出的时间不受mysql_url设置时区影响,并且不受mysql系统设置时区影响。
    当用LocalDateTime时,展示和存储都受mysql_url设置时区影响,并且受mysql系统设置时区影响;
  2. datetime,当用string存储时,写入的时间和读出的时间不受mysql_url设置时区影响,并且不受mysql系统设置时区影响。
    当用LocalDateTime时写入的时间和存储时间受mysql_url设置时区影响,但是不受mysql系统设置时区影响;

JDK8所有时间对象

对象名称 作用 实现方式 备注
Date 时间戳UTC+时区偏移量 long fastTime = 1594367598993 Gregorian.Date cdate = "2020-07-10T15:53:18.993+0800" 记录时间和时区
Instant 时间戳UTC long seconds = 1594367634int nanos = 998000000 对应jdk7之前的Date,可通过Epoch Time 纪元时相互转换
LocalDateTime 获取当前系统的日期时间(内部不记录时区) LocalDate date = "2020-07-10" LocalTime time = "15:54:07.858" 可以认为由LocalDate和LocalTime组成
LocalDate 获取当前系统的日期 int year = 2020short month = 7short day = 10
LocalTime 获取当前系统的时间 byte hour = 15 byte minute = 54int nano = 906000000byte second = 33
ZoneId 时区,"+08:00"和"Asia/Shanghai" id = "Asia/Shanghai" ZoneRules rules = "ZoneRules[currentStandardOffset=+08:00]" ZoneId除了处理与标准时间的时间差还处理地区时(夏令时,冬令时等)
ZoneOffset 时区,只处理 "+01:00" int totalSeconds = 0String id = "Z" ZoneOffset是ZoneId的子类,只处理与格林尼治的时间差
ZoneDateTime 时间字符串+时区+时间偏移量 LocalDateTime dateTime = "2020-07-10T15:55:45.859" ZoneOffset offset = "+08:00" ZoneRegion zone = "Asia/Shanghai" LocalDateTime内部不记录时区,ZoneDateTime记录
OffsetDateTime 时间字符串+时区偏移量 LocalDateTime dateTime = "2020-07-10T15:56:16.174" ZoneOffset offset = "+08:00"

**
**

概念

1.相对时间和绝对时间

怎么做

\1. 数据库字段类型

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

\3. instant使用规则

为什么

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

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

还需注意什么

  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接收参数

@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"
}

image-20200816173627367

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-16 16:45:44"
}
mysql存入的值

image-20200816173145939

java8的时间互转示例

Instant->其他时间类
     Instant instant = Instant.now();
     ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
     Instant instant = Instant.now();
     OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.UTC);
     Instant instant = Instant.now();
     LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
     LocalDateTime localDateTime = instant.atOffset(ZoneOffset.UTC).toLocalDateTime();
     LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
     LocalDate localDate = instant.atOffset(ZoneOffset.UTC).toLocalDate();

     LocalTime localTime = instant.atOffset(ZoneOffset.UTC).toLocalTime();
     LocalTime localTime = instant.atZone(ZoneId.systemDefault()).toLocalTime();
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());
    }
}

输出结果

utc时间转换

时间对象相关的链接

https://blog.csdn.net/u012107143/article/details/78790378

https://lw900925.github.io/java/java8-newtime-api.html

标签:国际化,Instant,04,16,44,45,规范,开发,2020
来源: https://www.cnblogs.com/skystarry/p/14948270.html