我试图以UTC
格式为timezone
获取Date
,并取决于用户选择的出生地和timezone
将其保存在数据库中,但在设置时区并尝试检索新值后,它将返回旧格式,而不是UTC
val calendar = Calendar.getInstance().apply {
timeZone = TimeZone.getTimeZone("UTC")
}
println("Date: ${calendar.time}")
I/System.out: Date: Sat Feb 26 16:43:08 GMT+02:00 2022
(注意:这个答案使用Java语法,因为我还没有学习Kotlin。你可以很容易地翻译。)
tl;dr
切勿使用Calendar
、SimpleDateFormat
、TimeZone
或其他传统日期时间类。
使用带有java.time类的格式化程序对象生成文本。
ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
.format(
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.LONG )
.withLocale( Locale.GERMANY )
)
请在IdeOne.com上实时查看此代码。
- 2022年2月上午10:30:06 NZDT
从类似于SQL标准类型TIMESTAMP WITH TIME ZONE
的数据库列中检索一个时刻作为OffsetDateTime
对象。调整到您想要的时区。使用DateTimeFormatter
生成文本。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
String output = zdt.format( myFormatter ) ;
详细信息
您使用的是糟糕的日期-时间类,这些类现在是遗留的,几年前被JSR310中定义的现代java.time类所取代。
日期-时间对象没有"格式">日期-时间对象包含日期-时间值,而不是文本。我们使用格式化程序将文本解析为日期时间对象,并使用格式化程序从日期时间对象生成文本。
使用Instant
获取UTC中的当前时刻。
Instant instant = Instant.now();
要获得更灵活的格式,请转换为OffsetDateTime
。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
并且在访问类似于SQL标准类型TIMESTAMP WITH TIME ZONE
的数据库列时使用OffsetDateTime
类。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
要通过特定地区的人使用的挂钟时间看到相同的时刻,请指定一个时区(ZoneId
)以生成ZonedDateTime
。
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
以自动本地化的格式生成文本。
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = zdt.format( f ) ;
请在IdeOne.com上实时查看此代码。请注意,当通过日本的挂钟时间查看时,日期和时间是如何不同的。
instant = 2022-02-27T21:23:27.804471Z
odt = 2022-02-27T21:23:27.804471Z
zdt = 2022-02-28T06:23:27.804471+09:00[Asia/Tokyo]
output = lundi 28 février 2022 à 06 h 23 min 27 s heure normale du Japon
所有这些都已经在Stack Overflow上做了很多次了。搜索以了解更多信息。
java.time类构建在java 8及更高版本中。安卓26+与一个实现捆绑在一起。对于早期的Android,通过";API减油";最新工具的特点。