【问题标题】:epoch timestamp to country local TZD format国家/地区本地 TZD 格式的纪元时间戳
【发布时间】:2018-10-13 23:35:06
【问题描述】:

我有纪元时间戳和国家。我想将该时间戳转换为给定国家/地区的本地时间戳,其时区区域采用夏令时 (TZD) 格式,如下所示

yyyy-mm-ddThh:MM:ssTZD
e.g. 2018-02-25T22:36:23+0100

Timestamp : 1525370235
Country : NLD (ISO alpha-3 code)

如何在 Java 中实现这一点?

更新 1

我正在使用这种转换,但不确定它是正确还是错误。有人可以告诉我这是进行转换的正确方法吗

Locale locale = new Locale("NLD");
Date date = new Date(1525381190 * 1000L);
    SimpleDateFormat dateFormatCN = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ", locale);

 //Output : 2018-05-03T01:59:50-0700

【问题讨论】:

标签: java datetime timezone dst country-codes


【解决方案1】:

这是进行转换的正确方法吗

不,不是。我看到以下问题。

  • 整个事情是不可能的,因为许多国家跨越多个时区。这意味着,从国家代码中,您无法知道选择哪个时区。由于本地时间因时区而异,因此在这些情况下您无法打印正确的时间。跨越多个时区的国家包括但不限于加拿大、美国、墨西哥、格陵兰、巴西、厄瓜多尔、俄罗斯、印度尼西亚、基里巴斯——甚至荷兰,您的示例国家。请注意,列表中有一些人口最多的国家/地区,因此如果您的数据代表世界人口,您可能会经常遇到此问题。请参阅this list: List of time zones by country
  • 语言环境和时区是两个不同的东西,尽管它们或多或少都与地点相关,但没有直接关系。因此,获取正确的语言环境对您没有帮助。您还可以看到打印输出的 UTC 偏移量为 -0700,而阿姆斯特丹夏季的正确偏移量应该是 +0200。
  • new Locale("NLD") 不会为您提供荷兰的有效语言环境。 Locale(String) 构造函数的参数是一个语言标签,如荷兰语的nl 或英语的en。三个字母的国家/地区代码不起作用。
  • 因此,如果您只想做一些您所询问的工作,您需要访问一些可以将国家代码转换为国家代码并将国家代码转换为时区的数据库。我不知道这里有什么好的选择,但我希望有一些这样的数据库可用。

java.time

最后,不要使用SimpleDateFormatDate。这些课程早已过时且设计不佳。格式化荷兰大陆纪元时间戳值的现代正确方法是:

    ZoneId zone = ZoneId.of("Europe/Amsterdam");
    String nldTime = Instant.ofEpochSecond(1_525_370_235L)
            .atZone(zone)
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    System.out.println(nldTime);

打印出来:

2018-05-03T19:57:15+02:00

如果您需要+0200 中不带冒号的偏移量,请使用DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXX")

如果您想在荷兰加勒比地区的城市而不是阿姆斯特丹,请使用美国/克拉伦代克时区。那么结果就是2018-05-03T13:57:15-04:00

【讨论】:

  • 感谢 Ole V.V 的详细回答。我会考虑你的解决方案,但我的问题是国家没有在这里解决。它会随着每个服务器请求而改变。
【解决方案2】:

在 iso 格式 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 中没有实际的 Oracle 时区。

所以,我想建议您在 ISO 区域和 Oracle 时区之间进行映射https://www.mkyong.com/java/java-display-list-of-timezone-with-gmt/

所以,我对您的问题的解决方案如下:

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class IsoToOracleDate {

static Map<String, String> timezones = new HashMap<String, String>(){{
   put("NLD","Europe/Amsterdam");
   put("RUS","Europe/Moscow");
   put("USA","America/New_York");
}};

public static void main(String[] args) {
    String zone = timezones.get("NLD");
    ZoneId zoneId = ZoneId.of(zone);
    long epochMilli = 1525370235 * 1000L;
    LocalDateTime dt = Instant.ofEpochMilli(epochMilli).atZone(zoneId).toLocalDateTime();
    ZonedDateTime zdt = ZonedDateTime.of(dt, zoneId);
    System.out.println(zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
}
}

输出:

2018-05-03T19:57:15+02:00

您在 timezones 变量中有时区映射。

从映射创建 ZoneId(oracle) ZoneId zoneId = ZoneId.of(zone);

根据您的区域从 epochMilli 创建 LocalDateTime dt 并将其转换为 ZonedDateTime zdt

然后只需使用预定义格式 DateTimeFormatter.ISO_OFFSET_DATE_TIME 格式化 zdt

【讨论】:

  • 美国!=纽约。俄罗斯更广阔,有更多的时区。这样的映射是不可能的。
  • 请阅读完整的答案。我正在写“所以,我想建议您在 ISO 区域和 Oracle 时区之间进行映射”。我建议为大国选择一个城市(可能是首都,或者美国的 New Your),并在 ISO 时区和 Oracle 时区之间进行映射。因此,如果您假设选择该国的一个城市,那么这种映射是可能的。
  • 例如,这对夏威夷居民有何用处? (与纽约时差 6 小时)
  • @MattJohnson,Matt,请注意“国家:NLD(ISO alpha-3 代码)”这个问题。 en.wikipedia.org/wiki/ISO_3166-1_alpha-3 没有夏威夷,只有国家。这就是为什么我建议进行一对一映射。
  • 夏威夷是美国的一个州。我的观点是夏威夷和纽约都有美国的国家代码,但它们的时区截然不同。说“挑一个”是没有用的。因此,downvote 是有道理的,因为您的回答没有用。
猜你喜欢
  • 1970-01-01
  • 2021-12-29
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
  • 1970-01-01
相关资源
最近更新 更多