tl;博士
Instant // Represent a moment in UTC.
.parse( // Generate a `Instant` object from the content of text input.
"2019-08-13T18:00:00Z" // String in standard ISO 8601 format.
) // Returns a `Instant` object.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Europe/London" ) // Specify a time zone using name in proper `Continent/Region` format. Never use 2-4 letter pseudo-zones such as `BST`.
) // Returns a `ZonedDateTime` object.
.toLocalTime() // Extract the time-of-day, without a date and without a time zone or offset. Returns a `LocalTime` object.
.format( // Generate text representing the content of this `LocalTime` object.
DateTimeFormatter
.ofLocalizedTime ( FormatStyle.SHORT ) // Automatically localize while generating a `String`.
.withLocale ( Locale.UK ) // Locale determines the human language and cultural norms to use in localizing.
) // Returns a `String` object.
19:00
避免遗留的日期时间类
您将可怕的遗留类 ( SimpleDateFormat
, Date
) 与现代java.time类混合在一起。不要那样做。仅使用java.time。
Instant
= UTC 时刻
跳过前两行代码。您的输入字符串"2019-08-13T18:00:00Z"
采用标准 ISO 8601 格式。java.time类在解析/生成字符串时默认使用这些标准格式。所以不需要指定格式模式。
String input = "2019-08-13T18:00:00Z" ;
Instant instant = Instant.parse( input ) ;
即时.toString(): 2019-08-13T18:00:00Z
Instant
不灵活
我怀疑您的问题在于您尝试在Instant
. 该类Instant
是java.time中的一个基本构建块类。它仅代表 UTC 中的一个时刻。它不适用于诸如灵活生成字符串之类的事情。
更灵活的类是OffsetDateTime
&ZonedDateTime
类。
ZonedDateTime
将 aZoneId
应用于您Instant
以调整到时区,渲染ZonedDateTime
对象。
ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2019-08-13T19:00+01:00[欧洲/伦敦]
你似乎只想专注于一天中的时间。提取一个LocalTime
对象。
LocalTime lt = zdt.toLocalTime ();
lt.toString(): 19:00
对于在该日期采用夏令时 (DST) 的伦敦地区,与 UTC 的偏移提前一小时。所以我们看到一天中的时间是晚上 7 点,而世界标准时间是下午 6 点。
适当的时区
顺便说一句BST
,不是时区。我建议您避免使用这些伪区域。
以、或等格式指定适当的时区名称。切勿使用 2-4 个字母的缩写,例如or或,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。Continent/Region
America/Montreal
Africa/Casablanca
Pacific/Auckland
BST
EST
IST
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
使用智能对象,而不是哑字符串
您的示例代码表明您过于关注字符串。使用智能对象,而不是愚蠢的字符串。
使用适当的类型让您的对象直截了当。生成字符串应该是最后一步,一个附带的工作,类似于本地化。您的业务逻辑应该通过使用适当的对象来完成,而不是通过操作字符串。
本土化
说到本地化:
Locale locale = Locale.UK;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime ( FormatStyle.MEDIUM ).withLocale ( locale );
String output = lt.format ( f );
19:00:00
将语言环境切换到Locale.US
不同类型的结果:
晚上 7:00:00
根据您在问题中所述的需求,上面的所有代码都使用ThreeTen-Backport库在 Java 13 早期访问中运行。
import org.threeten.bp.* ;
import org.threeten.bp.format.* ;
读者注意:ThreeTen- Backport 库在ThreeTenABP库中进一步适用于早期的 Android 。请参阅如何在 Android 中使用 ThreeTenABP。如果使用 Android 26 及更高版本,则捆绑了java.time类,因此您根本不需要反向端口。