Java - ZonedDateTime 没有正确转换为 Date 对象?
Java - ZonedDateTime does not correctly convert to Date object?
我有以下 Java 代码:
Date convertedDate = Date.from(zonedDateTime.toInstant());
我遇到的问题是 convertedDate
与 zonedDateTime 对象相比不正确。
例如,当我有一个 zonedDateTime 对象时:
2021-09-16T12:00
区域:
Africa/Abidjan
上面的代码将其转换为:
Thu Sep 16 13:00:00 BST 2021
我在这里期待的是
Thu Sep 16 10:00:00 BST 2021
因为 Africa/Abidjan
时区比 BST 早 2 小时。
我该如何解决这个问题?
java.time
java.util
日期时间 API 及其格式 API、SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*.
解决方案使用 java.time
,现代日期时间 API:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// The given ZonedDateTime
ZonedDateTime zdtAbidjan = ZonedDateTime.of(
LocalDateTime.of(LocalDate.of(2021, 9, 16),
LocalTime.of(12, 0)),
ZoneId.of("Africa/Abidjan")
);
System.out.println(zdtAbidjan);
ZonedDateTime zdtLondon = zdtAbidjan.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println(zdtLondon);
}
}
输出:
2021-09-16T12:00Z[Africa/Abidjan]
2021-09-16T13:00+01:00[Europe/London]
输出中的 Z
是零时区偏移量的 timezone designator。它代表祖鲁语并指定 Etc/UTC
时区(时区偏移量为 +00:00
小时)。
从输出中可以清楚地看出 2021-09-16T12:00Z[Africa/Abidjan] 等于 2021-09-16T13:00+01:00[Europe/London].
了解有关现代日期时间 API 的更多信息
* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and 。
是正确的。这里还有一些想法。
时区名称
BST
不是 real time zone name. Perhaps you meant Europe/London
. And that is not GMT/UTC. The London time zone can vary in its offset, because of Daylight Saving Time (DST) 也许还有其他原因。
UTC
让我们来看看你在三个不同时区的时刻。
首先,我们将您的输入解析为 LocalDateTime
,缺少时区上下文或与 UTC 的偏移量。然后我们为 Abidjan 分配一个时区作为上下文以产生一个 ZonedDateTime
对象。我们调整到另一个时区,导致第二个 ZonedDateTime
代表同一时刻,时间轴上的同一点,但挂钟时间不同。最后,我们提取一个 Instant
以有效调整为 UTC。 A Instant
表示 UTC 中的时刻,始终为 UTC。
LocalDateTime ldt = LocalDateTime.parse( "2021-09-16T12:00" ) ;
ZonedDateTime zdtAbidjan = ldt.atZone( ZoneId.of( "Africa/Abidjan" ) ) ;
ZonedDateTime zdtLondon = zdtAbidjan.withZoneSameInstant( ZoneId.of( "Europe/London" ) ) ;
Instant instant = zdtAbidjan.toInstant() ; // Adjust to UTC by extracting an `Instant` object.
看到这个 code run live at IdeOne.com。
ldt: 2021-09-16T12:00
zdtAbidjan: 2021-09-16T12:00Z[Africa/Abidjan]
zdtLondon: 2021-09-16T13:00+01:00[Europe/London]
instant: 2021-09-16T12:00:00Z
末尾的Z
表示零时分秒的偏移量,发音为“Zulu”。所以我们可以 zee 9 月那一天的中午在科特迪瓦与 UTC 相同,偏移量为零。相反,+01:00
告诉我们伦敦时间提前一个小时。所以时钟显示为下午 1 点 (13:00
) 而不是中午。
获取偏移量
您可以通过 ZoneRules
class 确定在特定时刻有效的偏移量。偏移量信息由 ZoneOffset
class.
表示
ZoneId z = ZoneId.of( "Africa/Abidjan" ) ;
ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( LocalDateTime.parse( "2021-09-16T12:00" ) ) ;
int offsetInSeconds = offset.getTotalSeconds() ;
或将其压缩为:
ZoneId
.of( "Africa/Abidjan" )
.getRules()
.getOffset( LocalDateTime.parse( "2021-09-16T12:00" ) )
.getTotalSeconds()
当 运行 我们再次看到科特迪瓦在该日期时间使用的偏移量为零。
rules: ZoneRules[currentStandardOffset=Z]
offset: Z
offsetInSeconds: 0
我有以下 Java 代码:
Date convertedDate = Date.from(zonedDateTime.toInstant());
我遇到的问题是 convertedDate
与 zonedDateTime 对象相比不正确。
例如,当我有一个 zonedDateTime 对象时:
2021-09-16T12:00
区域:
Africa/Abidjan
上面的代码将其转换为:
Thu Sep 16 13:00:00 BST 2021
我在这里期待的是
Thu Sep 16 10:00:00 BST 2021
因为 Africa/Abidjan
时区比 BST 早 2 小时。
我该如何解决这个问题?
java.time
java.util
日期时间 API 及其格式 API、SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*.
解决方案使用 java.time
,现代日期时间 API:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// The given ZonedDateTime
ZonedDateTime zdtAbidjan = ZonedDateTime.of(
LocalDateTime.of(LocalDate.of(2021, 9, 16),
LocalTime.of(12, 0)),
ZoneId.of("Africa/Abidjan")
);
System.out.println(zdtAbidjan);
ZonedDateTime zdtLondon = zdtAbidjan.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println(zdtLondon);
}
}
输出:
2021-09-16T12:00Z[Africa/Abidjan]
2021-09-16T13:00+01:00[Europe/London]
输出中的
Z
是零时区偏移量的 timezone designator。它代表祖鲁语并指定Etc/UTC
时区(时区偏移量为+00:00
小时)。从输出中可以清楚地看出 2021-09-16T12:00Z[Africa/Abidjan] 等于 2021-09-16T13:00+01:00[Europe/London].
* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and
时区名称
BST
不是 real time zone name. Perhaps you meant Europe/London
. And that is not GMT/UTC. The London time zone can vary in its offset, because of Daylight Saving Time (DST) 也许还有其他原因。
UTC
让我们来看看你在三个不同时区的时刻。
首先,我们将您的输入解析为 LocalDateTime
,缺少时区上下文或与 UTC 的偏移量。然后我们为 Abidjan 分配一个时区作为上下文以产生一个 ZonedDateTime
对象。我们调整到另一个时区,导致第二个 ZonedDateTime
代表同一时刻,时间轴上的同一点,但挂钟时间不同。最后,我们提取一个 Instant
以有效调整为 UTC。 A Instant
表示 UTC 中的时刻,始终为 UTC。
LocalDateTime ldt = LocalDateTime.parse( "2021-09-16T12:00" ) ;
ZonedDateTime zdtAbidjan = ldt.atZone( ZoneId.of( "Africa/Abidjan" ) ) ;
ZonedDateTime zdtLondon = zdtAbidjan.withZoneSameInstant( ZoneId.of( "Europe/London" ) ) ;
Instant instant = zdtAbidjan.toInstant() ; // Adjust to UTC by extracting an `Instant` object.
看到这个 code run live at IdeOne.com。
ldt: 2021-09-16T12:00
zdtAbidjan: 2021-09-16T12:00Z[Africa/Abidjan]
zdtLondon: 2021-09-16T13:00+01:00[Europe/London]
instant: 2021-09-16T12:00:00Z
末尾的Z
表示零时分秒的偏移量,发音为“Zulu”。所以我们可以 zee 9 月那一天的中午在科特迪瓦与 UTC 相同,偏移量为零。相反,+01:00
告诉我们伦敦时间提前一个小时。所以时钟显示为下午 1 点 (13:00
) 而不是中午。
获取偏移量
您可以通过 ZoneRules
class 确定在特定时刻有效的偏移量。偏移量信息由 ZoneOffset
class.
ZoneId z = ZoneId.of( "Africa/Abidjan" ) ;
ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( LocalDateTime.parse( "2021-09-16T12:00" ) ) ;
int offsetInSeconds = offset.getTotalSeconds() ;
或将其压缩为:
ZoneId
.of( "Africa/Abidjan" )
.getRules()
.getOffset( LocalDateTime.parse( "2021-09-16T12:00" ) )
.getTotalSeconds()
当 运行 我们再次看到科特迪瓦在该日期时间使用的偏移量为零。
rules: ZoneRules[currentStandardOffset=Z]
offset: Z
offsetInSeconds: 0