由于java中的时区问题,未拾取数据
我的代码中有一个日期/时间计算时区的问题。 我也需要你的建议。下面是场景 我的应用程序必须从hbase数据库中拾取数据。此数据将根据hbase中的表中的日期搜索条件选取。该表有一个用于筛选的日期-时间列 现在,填充此表中数据的另一个应用程序是插入GMT时区格式的datetime(这是该团队所说的)。应用程序部署在位于EST时区的服务器上。我从用户那里得到一个输入日期(没有时间成分),我需要将其转换为GMT时区。但目前的情况是,当我进行转换时,一些数据没有在EST时区中被拾取。相同的数据在我的本地时区列表中被拾取。我已经在本地和远程服务器中部署的代码中完成了到GMT的转换。下面的示例 数据出现在表中的日期:2013-03-15 01:30:30 用户输入的数据:2013-03-15(无时间成分)。我特别添加了时间组件 添加时间组件后的日期:开始日期-2013-03-15 00:00:00,结束日期-2013-03-15 23:59:59 我在IST时区(UTC+5:30)。因此,转换为GMT的开始日期和结束日期都是 开始日期转换为GMT-2013-03-1418:30:56 结束日期转换为格林尼治标准时间-2013-03-15 18:30:56 现在,由于用户提供的日期2013-03-15 01:30:30落在上述范围内,表中的数据将被拉入该时区 在EST(UTC-5:00)中的远程服务器中部署了相同的代码 开始日期转换为GMT-2013-03-15 05:00:56 结束日期转换为格林尼治标准时间-2013-03-16 05:00:56 现在,由于用户提供的数据2013-03-15 01:30:30不在此范围内,因此数据不会被提取 我不确定如何处理这种情况,以使计算在时区之间保持一致。因为测试人员说数据应该在不同的时区之间保持一致。但正如你所看到的,GMT转换已经完成,但日期被两个时区的偏移量抵消了,数据也没有被调出。 如果你能让我知道如何处理这将是很大的帮助由于java中的时区问题,未拾取数据,java,Java,我的代码中有一个日期/时间计算时区的问题。 我也需要你的建议。下面是场景 我的应用程序必须从hbase数据库中拾取数据。此数据将根据hbase中的表中的日期搜索条件选取。该表有一个用于筛选的日期-时间列 现在,填充此表中数据的另一个应用程序是插入GMT时区格式的datetime(这是该团队所说的)。应用程序部署在位于EST时区的服务器上。我从用户那里得到一个输入日期(没有时间成分),我需要将其转换为GMT时区。但目前的情况是,当我进行转换时,一些数据没有在EST时区中被拾取。相同的数据在我的本地
我没有在这里输入任何代码,因为它是在线时区的标准代码,在大多数情况下都是相同的。这取决于您在这里尝试实现的目标 如果您确实希望将输入解释为本地时间,并将其转换为GMT以检查数据库,那么结果实际上是一致的,反过来想想问题,如果您将HBase中的每个日期神奇地转换为本地时间,您会得到哪些记录 如果用户输入的日期实际上是TZ特定的,那么同一个日期“文本”返回不同的结果是很自然的,因为两个用户实际上指的是两个不同的时间点 另一方面,如果您需要提供相同输入的用户获得完全相同的结果,那么您需要假设输入已经在某个一致的TZ中,例如,始终在UTC(或您的情况下为GMT) 基本上,您需要决定的是: 用户提供的输入是否特定于用户的TZ?或者它总是在同一时刻,在特定的时间?IST,EST,GMT,由你决定 如果你做出这样的决定,你的结果将是一致的。tl;博士 使用半开放查询逻辑:
选择*
来自tbl
什么时候>=?什么时候<?——半开放逻辑,其中开始是包含的,而结束是独占的。
;
具有两个参数的查询:
- 一天的开始时刻
- 第二天开始时刻
myPreparedStatement.setObject(
1 ,
LocalDate.parse( "2013-03-15" ) // Represent entire day as a `LocalDate` object.
.atStartOfDay( // Determine first moment of that date in a particular time zone, which may or may not be 00:00:00.
ZoneId.of( "Asia/Kolkata" )
) // Returns a `ZonedDateTime` object. Your JDBC driver should be able to handle that smartly. If not, extract a `Instant` object in UTC by calling `ZonedDateTime::toInstant()`.
) ;
myPreparedStatement.setObject(
2 ,
LocalDate.parse( "2013-03-15" )
.plusDays( 1 ) // Move to the following day.
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
) ;
检索时,调整到任何所需的时区
myResultSet.getObject( … , Instant.class) // Extract a `Instant` object from selected row.
.atZone( // Apply a `ZoneId` to get a `ZonedDateTime` object.
ZonedId.of( "America/Montreal" )
)
服务器默认时区无关
服务器当前的默认时区应该与您的编程无关。您应该通过各种日期-时间方法的可选参数指定所需/预期时区
顺便说一下,Locale
也一样:显式指定,而不是隐式依赖当前默认值
在我看来,这些论点应该是必要的,而不是随意的。似乎很多程序员忽视了时区和语言环境的问题
java.time
现代方法使用java.time类
使用符合JDBC 4.2或更高版本的JDBC驱动程序,您可以直接与数据库交换java.time类型
在UTC中使用Instant
片刻。对于没有时间和时区的日期,请使用LocalDate
LocalDate ld = LocalDate.parse( "2013-03-15" ) ;
要搜索包含一整天范围内某个时刻的数据库记录,我们需要确定当天的第一个时刻和次日的第一个时刻。然后我们做一个半开放的查询,其中开始是包含的,而结束是独占的
不要假设一天从00:00:00开始。夏时制(DST)等异常意味着一天可能在其他时间开始,如01:00:00。我们需要一个时区
以大陆/地区
的格式指定,例如,或太平洋/奥克兰
。切勿使用3-4个字母的缩写,如EST
或IST
,因为它们不是真正的时区,也不是标准化的,甚至不是唯一的(!)
第二天。调用LocalDate::plusDays
移动到第二天
ZonedDateTime zdtStop = ld.plusDays( 1 ).atStartOfDays( z ) ;
如果您希望看到与UTC墙上时钟时间相同的时刻,请提取一个瞬间
。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)
您的SQL应该如下所示:
String sql = "SELECT * FROM tbl WHERE when >= ? AND when < ? ;" ; // Half-open logic, where beginning is inclusive while the ending is exclusive.
和检索
Instant instant = myResultSet.getObject( "when" , Instant.class ) ;
如果你想通过挂钟的镜头来观察同一时刻,那么你就要使用时间
String sql = "SELECT * FROM tbl WHERE when >= ? AND when < ? ;" ; // Half-open logic, where beginning is inclusive while the ending is exclusive.
myPreparedStatement.setObject( 1 , start ) ; // You can exchange java.time object with JDBC 4.2 or later.
myPreparedStatement.setObject( 2 , stop ) ;
Instant instant = myResultSet.getObject( "when" , Instant.class ) ;
ZonedDateTime zdt = instant.atZone( ZoneId.of( "America/New_York" ) ) ;