如何在 java 的给定时间内知道爱尔兰的当前时区
How to know current timezone of Ireland in a given time in java
爱尔兰在夏天使用 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
tl;博士
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
详情
您的标题要求:
How to know current timezone of Ireland in a given time in java
根据我对 this Wikipedia article 的阅读,爱尔兰只有一个时区:Europe/Dublin
。
您混淆了偏移量和区域。
offset-from-UTC 只是现代时间子午线之前或之后的 hours-minutes-seconds 的数字。
时区更多。时区是一个命名的过去、现在和未来的历史变化,由特定地区的人民使用,由他们的政客决定。
实时时区以Continent/Region
格式命名。 IST
等 2-4 个字符 pseudo-zones 不是时区,应避免使用,因为它们不是标准化的,甚至不是唯一的!对某些人来说,IST
是 爱尔兰标准时间,而对其他人来说,IST
是印度标准时间.
你说:
I get datetime without any GMT information from a source, and it's from Ireland.
因此,选择您的日期和 time-of-day 并添加您认为预期的时区。你得到一个 ZonedDateTime
代表一个时刻,时间轴上的一个特定点。
LocalDate ld = … ;
LocalTime lt = … ;
ZoneId z = ZoneId.of( "Europe/Dublin" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
通过提取 Instant
.
调整为 UTC(偏移量为零 hours-minutes-seconds)
Instant instant = zdt.toInstant() ;
要获得更大的灵活性,例如生成各种格式的文本,请转换为 OffsetDateTime
。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
你不能(总是)
只是为了阐明我认为 talex 在评论中的含义。在 10 月的最后一个星期日,爱尔兰从夏令时切换到标准时间。爱尔兰的时钟从凌晨 2 点拨回凌晨 1 点。所以在凌晨 1 点后一个小时,又是凌晨 1 点。时代重复。这被称为 重叠。 (相反,当时钟向前转动时,称为 gap。)这意味着什么?例如,如果你得到的时间是那天晚上的 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是否是summer/winter时间,你会发现它反映了不同的时区偏移(当然,如果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。它代表祖鲁语并指定 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]
详细了解 modern Date-Time API* from Trail: Date Time。
* 如果您正在为 Android 项目工作,并且您的 Android API 水平仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time
。
爱尔兰在夏天使用 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
tl;博士
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
详情
您的标题要求:
How to know current timezone of Ireland in a given time in java
根据我对 this Wikipedia article 的阅读,爱尔兰只有一个时区:Europe/Dublin
。
您混淆了偏移量和区域。
offset-from-UTC 只是现代时间子午线之前或之后的 hours-minutes-seconds 的数字。
时区更多。时区是一个命名的过去、现在和未来的历史变化,由特定地区的人民使用,由他们的政客决定。
实时时区以Continent/Region
格式命名。 IST
等 2-4 个字符 pseudo-zones 不是时区,应避免使用,因为它们不是标准化的,甚至不是唯一的!对某些人来说,IST
是 爱尔兰标准时间,而对其他人来说,IST
是印度标准时间.
你说:
I get datetime without any GMT information from a source, and it's from Ireland.
因此,选择您的日期和 time-of-day 并添加您认为预期的时区。你得到一个 ZonedDateTime
代表一个时刻,时间轴上的一个特定点。
LocalDate ld = … ;
LocalTime lt = … ;
ZoneId z = ZoneId.of( "Europe/Dublin" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
通过提取 Instant
.
Instant instant = zdt.toInstant() ;
要获得更大的灵活性,例如生成各种格式的文本,请转换为 OffsetDateTime
。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
你不能(总是)
只是为了阐明我认为 talex 在评论中的含义。在 10 月的最后一个星期日,爱尔兰从夏令时切换到标准时间。爱尔兰的时钟从凌晨 2 点拨回凌晨 1 点。所以在凌晨 1 点后一个小时,又是凌晨 1 点。时代重复。这被称为 重叠。 (相反,当时钟向前转动时,称为 gap。)这意味着什么?例如,如果你得到的时间是那天晚上的 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是否是summer/winter时间,你会发现它反映了不同的时区偏移(当然,如果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。它代表祖鲁语并指定 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]
详细了解 modern Date-Time API* from Trail: Date Time。
* 如果您正在为 Android 项目工作,并且您的 Android API 水平仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time
。