【发布时间】:2021-11-27 17:13:31
【问题描述】:
在夏天,爱尔兰在冬天使用IST, UTC+01:00 和Greenwich Mean Time。我从来源获得的日期时间没有任何 GMT 信息,它来自爱尔兰。我需要将其转换为 GMT+0。但挑战在于不同季节的爱尔兰时区不同。
【问题讨论】:
-
那是不可能的。一些时间戳对应于两个不同的时刻。
在夏天,爱尔兰在冬天使用IST, UTC+01:00 和Greenwich Mean Time。我从来源获得的日期时间没有任何 GMT 信息,它来自爱尔兰。我需要将其转换为 GMT+0。但挑战在于不同季节的爱尔兰时区不同。
【问题讨论】:
我建议您使用ZonedDateTime (reference documentation) 和ZoneId,您应该使用Europe/Dublin。它应该根据季节观察时区的变化。
【讨论】:
如果您确定时间来自爱尔兰,您可以硬编码 ZoneId,例如:ZoneId.of("Europe/Dublin")
然后像这样解析爱尔兰的时间:
LocalDateTime ldt = LocalDateTime.parse("2018-07-01T08:00");
ZoneId zoneId = ZoneId.of("Europe/Dublin");
ZonedDateTime zdt = ZonedDateTime.of(ldt, zoneId);
更多关于 ZonedDateTime 的信息在这里: https://www.codebyamir.com/blog/add-a-timezone-to-localdatetime-with-zoneddatetime-in-java-8
【讨论】:
ZonedDateTime
.of(
LocalDate.parse( "2022-06-23" ) ,
LocalTime.parse( "15:30" ) ,
ZoneId.of( "Europe/Dublin" )
)
.toInstant()
.atOffset(
ZoneOffset.UTC
)
看到这个code run live at IdeOne.com。我们看到明年夏天,爱尔兰人民的时钟将比 UTC 时间提前一小时:都柏林时间的 15:30 将是 UTC 时间的 14:30。
2022-06-23T14:30Z
你的标题要求:
如何在java中知道给定时间内爱尔兰的当前时区
爱尔兰??只有一个时区,根据我对this Wikipedia article的阅读:Europe/Dublin。
您将偏移量与区域混淆了。
与 UTC 的偏移只是比现代时间子午线提前或落后几个小时-分钟-秒。
时区要多得多。时区是一个命名的过去、现在和未来对偏移量变化的历史,该偏移量由特定地区的人们使用,由他们的政治家决定。
实时时区以Continent/Region 格式命名。 IST 等 2-4 个字符的伪区域不是时区,应该避免,因为它们不标准化,甚至不是唯一的!对某些人来说,IST 是爱尔兰标准时间,而对另一些人来说IST 是印度标准时间。
你说:
我从某个来源获得的日期时间没有任何 GMT 信息,而且它来自爱尔兰。
因此,请获取您的日期和时间,并添加您认为预期的时区。你会得到一个ZonedDateTime 来代表一个时刻,即时间线上的一个特定点。
LocalDate ld = … ;
LocalTime lt = … ;
ZoneId z = ZoneId.of( "Europe/Dublin" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
通过提取 Instant 来调整到 UTC(零时分秒的偏移量)。
Instant instant = zdt.toInstant() ;
要获得更大的灵活性,例如生成各种格式的文本,请转换为OffsetDateTime。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
【讨论】:
只是为了说明我认为 talex 在评论中的含义。在 10 月的最后一个星期日,爱尔兰从夏令时转换为标准时间。爱尔兰的时钟从凌晨 2 点调回凌晨 1 点。因此,在凌晨 1 点之后的一个小时,又是凌晨 1 点。时代在重复。这称为重叠。 (相反,当时钟向前转动时,称为间隙。)这意味着什么?例如,如果你得到的时间是那天晚上 1:30,你不知道它是从第一次是 1:30 — 1:30 IST — 还是第二次是 1:30 — 1 :30 格林威治标准时间。或者在代码中:
String dateTimeStr = "2021-10-31T01:30:00";
LocalDateTime ldt = LocalDateTime.parse(dateTimeStr);
System.out.println(ldt.atZone(IRELAND).withEarlierOffsetAtOverlap());
System.out.println(ldt.atZone(IRELAND).withLaterOffsetAtOverlap());
我使用了这个常量:
private static final ZoneId IRELAND = ZoneId.of("Europe/Dublin");
输出是:
2021-10-31T01:30+01:00[Europe/Dublin] 2021-10-31T01:30Z[Europe/Dublin]
对于不是源自当晚那两个小时的时间戳,您不会有任何问题。
要检查您是否有不明确的时间戳,请比较我在上述代码中打印的两个 ZonedDateTime 对象。对于绝大多数情况,它们将是平等的。举个例子:
String dateTimeStr = "2021-10-07T18:48:00";
2021-10-07T18:48+01:00[Europe/Dublin] 2021-10-07T18:48+01:00[Europe/Dublin]
【讨论】:
现有的答案很好。但是,他们错过了 OP 需要的重要信息,该信息是:
ZonedDateTime 旨在自动调整时区偏移量。
这意味着根据 Date-Time 是否为夏季/冬季时间,您会发现它反映了不同的时区偏移量(当然,如果DST 适用)。
演示:
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("Europe/Dublin");
ZonedDateTime zdtSummerIST = LocalDate.of(2021, 6, 15).atStartOfDay(zoneId);
ZonedDateTime zdtWinterIST = LocalDate.of(2021, 11, 15).atStartOfDay(zoneId);
System.out.println(zdtSummerIST);
System.out.println(zdtWinterIST);
}
}
输出:
2021-06-15T00:00+01:00[Europe/Dublin]
2021-11-15T00:00Z[Europe/Dublin]
输出中的Z 是零时区偏移的timezone designator。它代表 Zulu 并指定 Etc/UTC 时区(时区偏移量为 +00:00 小时)。
ZonedDateTime?将不带时区的日期时间字符串解析为LocalDateTime,可以使用LocalDateTime#atZone 将其转换为ZonedDateTime。
演示:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("Europe/Dublin");
String input = "07/10/2021 18:50:15";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(input, dtf);
ZonedDateTime zdt = ldt.atZone(zoneId);
System.out.println(zdt);
}
}
输出:
2021-10-07T18:50:15+01:00[Europe/Dublin]
通过 Trail: Date Time 了解有关 modern Date-Time API* 的更多信息。
* 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring。请注意,Android 8.0 Oreo 已经提供了support for java.time。
【讨论】: