为了总结我的问题,我有两个不同的ZonedDateTime对象,它们具有GMT和BST,但本地时间相同。在toInstant转换后,它们将变为相同的Instant值。我希望在转换后,它们应该是不同的值,因为尽管它们都是"2021年2月23日星期二18:00:46",但字符串代表不同时区的时间。我不确定这是图书馆本身的错误还是我做错了什么。
我从这段Scala代码中生成了两个不同的ZonedDateTime:
import ...
import java.util.{Set => JavaSet}
val string2 = "Tue Feb 23 18:00:46 BST 2021"
val string1 = "Tue Feb 23 18:00:46 GMT 2021"
val timestampFormat: DateTimeFormatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_INSTANT)
.appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_ZONED_DATE_TIME)
.appendOptional(DateTimeFormatter.RFC_1123_DATE_TIME)
.appendPattern("EEE MMM ppd HH:mm:ss ")
.appendZoneText(TextStyle.SHORT, JavaSet.of(ZoneId.of("Europe/London")))
.appendPattern(" yyyy")
.toFormatter(Locale.US)
val parsedZdt2: ZonedDateTime = ZonedDateTime.parse(string2, timestampFormat)
val parsedZdt1: ZonedDateTime = ZonedDateTime.parse(string1, timestampFormat)
println(parsedZdt1 == parsedZdt2)
println("parsedZdt1.toString: " + parsedZdt1.toString)
println("parsedZdt2.toString: " + parsedZdt2.toString)
打印出来:
false
parsedZdt1.toString: 2021-02-23T18:00:46Z[GMT]
parsedZdt2.toString: 2021-02-23T18:00:46Z[Europe/London]
然而,当我将它们转换为即时:
println(parsedZdt1.toInstant == parsedZdt2.toInstant)
println("parsedZdt1.toInstant.toString: " + parsedZdt1.toInstant.toString)
println("parsedZdt2.toInstant.toString: " + parsedZdt2.toInstant.toString)
我把这个打印出来了:
true
parsedZdt1.toInstant.toString: 2021-02-23T18:00:46Z
parsedZdt2.toInstant.toString: 2021-02-23T18:00:46Z
我的问题是
- 为什么toInstant转换后这两个值会相同
- 即使在toInstant之前,这两个值是否表示相同的时间,即parsedZdt1和parsedZdt2表示相同的时刻
谢谢!
tl;dr
你说:
字符串代表不同时区的时间
是的,不同的时区,但这些时区恰好在特定日期共享相同的偏移量。巧合的是,许多时区在特定日期共享相同的偏移量。
伦敦时间是GMT/UTC时间,有时不遵守夏令时(DST(。
BST=GMT(有时(
如果您所说的BST
是指时区Europe/London
,则该时区与2021-02-23日的UTC/GMT之间的偏移量为零小时。
👉因此,伦敦时间2月23日下午6点也是格林尼治标准时间下午6点。
今年晚些时候,从2021年3月28日到2021年10月31日,英国实行夏令时。在这几个月里,它们的偏移量比UTC提前一小时。
请参阅TimeAndDate.com上的英国2021年时间变化。
示例代码
让我们用Instant#equals
来比较两个矩。
LocalDate ld = LocalDate.of( 2021 , Month.FEBRUARY , 23 ) ;
LocalTime lt = LocalTime.of( 18 , 0 , 0 ) ;
boolean sameMoment =
ZonedDateTime.of( ld , lt , ZoneId.of( "Europe/London" ) ).toInstant()
.equals(
OffsetDateTime.of( ld , lt , ZoneOffset.UTC ).toInstant()
) ;
请在Ideone.com.上实时查看此代码
真实
在遵守夏令时期间,将月份更改为六月。
LocalDate ld = LocalDate.of( 2021 , Month.JUNE , 23 ) ;
LocalTime lt = LocalTime.of( 18 , 0 , 0 ) ;
boolean sameMoment =
ZonedDateTime.of( ld , lt , ZoneId.of( "Europe/London" ) ).toInstant()
.equals(
OffsetDateTime.of( ld , lt , ZoneOffset.UTC ).toInstant()
) ;
错误
ZoneOffset
此外,您可以直接询问ZonedDateTime
和OffsetDateTime
对象中的力矩偏移。调用getOffset
以获取ZoneOffset
对象。
LocalDate ld = LocalDate.of( 2021 , Month.FEBRUARY , 23 );
LocalTime lt = LocalTime.of( 18 , 0 , 0 );
ZonedDateTime zdtLondon = ZonedDateTime.of( ld , lt , ZoneId.of( "Europe/London" ) );
OffsetDateTime odtUtc = OffsetDateTime.of( ld , lt , ZoneOffset.UTC );
ZoneOffset offsetLondon = zdtLondon.getOffset();
ZoneOffset offsetUtc = odtUtc.getOffset();
System.out.println( zdtLondon + " has an offset of: " + offsetLondon );
System.out.println( odtUtc + " has an offset of: " + offsetUtc );
我们看到两者与UTC的偏移量都为0小时-分-秒,用Z
表示,发音为"Zulu"。
2021-02-23T18:00Z[欧洲/伦敦]的偏移量为:Z
2021-02-23T18:00Z的偏移量为:Z
将月份更改为六月,我们会得到不同的偏移量。伦敦时间显示比UTC提前一小时。
2021-06-23T18:00+01:00[欧洲/伦敦]的偏移量为:+01:00
2021-06-23T18:00Z的偏移量为:Z
英国夏令时从每年3月最后一个星期日的格林尼治标准时间01:00开始,到10月最后一天的格林尼治时间01:00(英国夏令时02:00(结束。
在您的示例中,2月23日表示相同的时间线,甚至在转换之前。对于2021年,要想看到1小时的差距,你必须使用3月28日至10月31日(含(之间的日期,但要有适当的时间。
例如:
val string2 = "Tue Mar 30 18:00:46 BST 2021"
val string1 = "Tue Mar 30 18:00:46 GMT 2021"
收益率:
parsedZdt1.toString: 2021-03-30T18:00:46Z[GMT]
parsedZdt2.toString: 2021-03-30T18:00:46+01:00[Europe/London]