我们有一个基于资源的服务,它以日期和时间作为参数来从后端获取数据。
数据以UTC格式存储在数据库中,服务器也使用UTC时区配置。
当从客户端收到请求时,我想将日期和时间转换为UTC格式的日期和时间,然后相应地查询数据库。
为了进行转换,我有以下代码,它从给定的zoneId转换为UTC格式。
public ZonedDateTime convertDateBetweenTimeZones(LocalDateTime sourceDateTime,String sourceZone,String targetZone){
return sourceDateTime.atZone( ZoneId.of(sourceZone)).withZoneSameInstant( ZoneId.of(targetZone));
}
我调用上面的方法,
ZonedDateTime zonedDateTime=convertDateBetweenTimeZones(LocalDateTime.now(),"Asia/Calcutta","UTC");
一旦我可以获得zonedDateTime对象,我想我可以将它传递给数据库并相应地查询它。
我的问题是,在我的情况下,我已将“Asia / Calcutta”作为源时区的zoneID。但是,源时区可以是任何东西,“America / New_York”甚至是“Asia / Singapore”。
因此,在这种情况下,我不确定如何从客户端收到的请求中动态获取zoneId,以便我可以相应地转换它。
任何人都可以帮助我如何获得zoneId或替代方式来处理我的场景。
谢谢,
JavaUser
答案 0 :(得分:1)
你做得很好,但有三件事。
服务器的时区设置应与您的编码无关。服务器设置可以随时更改,因此您不能依赖它。
始终将可选的时区对象传递给所有相关的java.time方法,以指定您期望/期望的任何时区。
明智地使用continent/region
格式的proper IANA 'tz' time zone names,例如America/Montreal
。切勿使用诸如EST
或IST
之类的3-4个字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
对于数据库交换,您可能需要从Instant
通过ZonedDateTime
方法提取toInstant
。大多数严重的数据库都以UTC格式存储日期时间。 Instant
类表示UTC时间轴上的一个时刻,分辨率为纳秒。
符合JDBC 4.2或更高版本的JDBC驱动程序可能直接通过Instant
和ResultSet::getObject
使用PrepatedStatement::setObject
。如果没有,则回退到简要转换为java {s}类型,例如java.sql.Timestamp
。
使用日期时间处理仔细研究数据库的行为;各种数据库在此(!)上广泛地广泛。 SQL规范对日期时间处理的主题几乎没有说明,过去模糊地违反了几天的类型。像Postgres这样的人有很好的日期时间支持,而其他人的支持很差,而且行为各不相同。
至于从网络浏览器确定时区,这并不简单。 Search Stack Overflow了解有关已发布的许多问题和解答的详细信息。
最终,唯一可靠的方法是询问用户。从用户收集数据时包括时区字段。
答案 1 :(得分:0)
一种解决方案是您可以使用别名映射来保留非标准时区ID并传递到ZoneId.of(id, alias)
方法。例如:
HashMap<String, String> aliasMap = new HashMap<>();
aliasMap.put("FOO", "America/New_York");
ZoneId zoneId = ZoneId.of("FOO", aliasMap);