前语

关于只担任国内业务的公司来说,我们在业务中想要获取其时时间,往往只需求使用Java自带的东西类new Date()、LocalDateTime.now()办法来获取,但关于一些跨境业务的公司来说,因为涉及到时区问题,往往需求将其时北京时间转化成其国外的当地时间

世界化时间转化,这就是本文想带我们了解的内容~


底子概念

在进行实践案例操作之前,我们需求先了解一下底子概念~


UTC

UTC(Coodinated Universal Time),调和世界时,又称世界一致时间、世界标准时间、世界调和时间。因为英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

UTC 是现在全球通用的时间标准,全球各地都赞同将各自的时间进行同步调和。UTC 时间是通过均匀太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以秒为单位的世界原子时所综合精算而成。

上面两句话是我从网上找的,从整句话上来了解UTC感觉仍是比较苍莽的,特别是还扯到地理上了,hh

但实在其中心点在于我加粗的文字: 世界标准时间、全球通用的时间标准

UTC就好比0这个数字,就是个标准,大于0为正数,小于0位负数

时区也是如此,比如北京时区就是UTC+8

《跨境i18》 世界化时间转化解决方案~

又或许洛杉矶时区现在是UTC-8

《跨境i18》 世界化时间转化解决方案~

那么洛杉矶现在跟北京的时间差就是8 - (-8)就是16个小时了,这么了解起来我感觉仍是比较简单的~

需求留意的是,我说的是现在为什么用这个词呢,因为接下来就引出了下一个概念: 冬令时、夏令时


冬令时、夏令时

冬令时和夏令时是用于节约日光和动力的时间准则,它们通过在一年中的不同时间调整标准时间来完成。

  1. 夏令时
    • 在夏令时期间,美西时间(Pacific Daylight Time, PDT)比调和世界时(UTC)慢7小时(UTC-7)。
    • 夏令时一般从每年的三月第二个周日开端,直到十一月第一个周日完毕。
  2. 冬令时
    • 在冬令时期间,美西时间(Pacific Standard Time, PST)比调和世界时慢8小时(UTC-8)。
    • 冬令时每年的十一月第一个周日开端,持续到次年的三月第二个周日

美西时间

所以我说洛杉矶时区现在是UTC-8,因为跟着时间变化,时区也会变成UTC-7


案例

底子概念大致了解后,我们需求通过案例来实在知道到底需求通过怎样的编码来完成世界化时间转化


拿到不同时区的其时时间

首要来一行LocalDateTime.now()拿到其时时间: 2023-11-16T22:26:36.863636

public static void main(String[] args) {
   LocalDateTime now = LocalDateTime.now();
   System.out.println(now);
}
《跨境i18》 世界化时间转化解决方案~

跟一下源码可见,默许拿的系统时间,即上海时区,没啥问题,因为我是中国人(手动狗头)

《跨境i18》 世界化时间转化解决方案~

此外我们还能拿到一个定论,那就是**LocalDateTime.now()本身没有时区概念,最终是需求根据时区来拿到其时时间的**,也没啥问题,都不给时区,人家怎样知道你其时是什么时间,hh

既然如此,我想必定可以手动传入时区,然后拿到现在时区的其时时间

诺,不出所料,API仍是很全面的,支撑传入Clock 和 ZoneId

《跨境i18》 世界化时间转化解决方案~

那么我们现在想假设拿到洛杉矶的其时时间,那么传入其时洛杉矶的时区-8即可

	public static void main(String[] args) {
		System.out.println(LocalDateTime.now(ZoneId.of("-8")));
		System.out.println(LocalDateTime.now(Clock.system(ZoneId.of("-8"))));
	}
《跨境i18》 世界化时间转化解决方案~
《跨境i18》 世界化时间转化解决方案~

拿到不同时区的其时时间的时间戳

Java中,我们假设想拿到其时时间的时间戳,最常见的代码就是System.currentTimeMillis()

public static void main(String[] args) {
   System.out.println(System.currentTimeMillis());
}
《跨境i18》 世界化时间转化解决方案~

那么除了这种办法,我们还知道别的办法吗?比如LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()

《跨境i18》 世界化时间转化解决方案~

我们都知道时间戳是没有时区概念的,在这一前提下,相信LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()这段代码就很好了解啦

  1. 通过LocalDateTime.now()拿到其时时间,即默许运用系统时区即上海时区+8
  2. 然后toInstant(ZoneOffset.of("+8")),传入+8因为拿到的其时时间存在+8时区概念,所以我们需求传入+8来抵消时区
  3. 最终toEpochMilli,拿到不存在时区概念的时间戳

不同时区时间互转

在之前我们都是运用的LocalDateTime传入方针时区,来获取方针时区的当地时间、时间戳~

而接下来假设想要进行不同时区相互转化,我们则需求ZonedDateTime

可以简略地把ZonedDateTime了解成LocalDateTimeZoneId,即带时区的LocalDateTime

那么我们把其时北京时间转化成对应洛杉矶的时区,编码如下:

public static void main(String[] args) {
   ZonedDateTime zonedDateTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("-8"));
   System.out.println(zonedDateTime.toLocalDateTime());
}
《跨境i18》 世界化时间转化解决方案~
《跨境i18》 世界化时间转化解决方案~

解读一下

  1. LocalDateTime.now()仍是拿到其时系统时区,即上海时区的其时时间
  2. atZone(ZoneId.systemDefault()),这里也可以了解为atZone(ZoneId.of("+8")), 标明我们LocalDateTime.now()拿到的是时间时区是+8
  3. .withZoneSameInstant(ZoneId.of("-8"), 标明转化成-8时区
  4. 最终toLocalDateTime,拿到转化后的时间

根据时间戳转化成各个时区的时间

时间戳没有时间概念,所以首要想到看看Instant有没有相关api,如图可见,支撑通过毫秒级、秒级时间戳进行转化

《跨境i18》 世界化时间转化解决方案~

我们用毫秒级时间戳转化为例,转化成Instant后,通过atZone标明时区

《跨境i18》 世界化时间转化解决方案~

我们标明为+8时区,因为我们通过System.currentTimeMillis()拿到的也是其时系统的时间戳,最终toLocalDateTime,并与LocalDateTime.now()比较一下,可以看到是底子一致的

《跨境i18》 世界化时间转化解决方案~

再来个案例,我们标明其时拿到时间的时间戳是-8时区的,那么在转化后,我们可见其时间与LocalDateTime.now()相差16个小时,契合预期~

《跨境i18》 世界化时间转化解决方案~


总结

本文从概念到案例由浅入深的带我们了解了在世界化时间转化的一些业务常见的解决方案,如有缺乏,请我们弥补~

我是 Code皮皮虾 ,会在往后的日子里跟我们一起学习,一起行进! 觉得文章不错的话,可以在 注重我,这样就不会错失许多技术干货啦~