Java 将SQL Server日期数据获取到Joda对象中的最佳方法?
TL;DR版本:请确认(如果没有,请提供帮助)我正在将SQL ServerJava 将SQL Server日期数据获取到Joda对象中的最佳方法?,java,sql-server-2008,jodatime,Java,Sql Server 2008,Jodatime,TL;DR版本:请确认(如果没有,请提供帮助)我正在将SQL Serverdatetimeoffset数据正确地导入我的Joda Time Java对象中 我正计划将数据库和java代码移动到时区感知。为了实现这一点,我已经完成了所有的工作,并且正在尝试实施最佳实践。请注意,所有代码都被视为“一次性”代码,因此我并不真正关心这里的效率;正确无误 我们的环境由一个MicrosoftSQLServer2008数据库和一个Java服务层组成,通过存储过程和SpringSimpleJDBCall访问所
datetimeoffset
数据正确地导入我的Joda Time Java对象中
我正计划将数据库和java代码移动到时区感知。为了实现这一点,我已经完成了所有的工作,并且正在尝试实施最佳实践。请注意,所有代码都被视为“一次性”代码,因此我并不真正关心这里的效率;正确无误 我们的环境由一个MicrosoftSQLServer2008数据库和一个Java服务层组成,通过存储过程和Spring
SimpleJDBCall
访问所有数据
提到的最佳实践之一是使用Joda时间库。由于这对我来说是新的,就像datetimeoffset
SQL数据类型一样,我希望确保我正确地执行了这项操作(因此不会丢失任何信息)
在SQL Server内部,我创建了一个表,用于测试所有各种SQL Server get time类型函数:
CREATE TABLE MIKE_TEMP (
ID INT NOT NULL IDENTITY,
BLAH NVARCHAR(255),
DT_GET_DATE DATETIME DEFAULT GETDATE() NOT NULL,
DT_GET_UTC_DATE DATETIME DEFAULT GETUTCDATE() NOT NULL,
DT_SYS_DATE_TIME DATETIME DEFAULT sysdatetime() NOT NULL,
DT_SYS_UTC_DATE_TIME DATETIME DEFAULT sysutcdatetime() NOT NULL,
DT_SYS_DATE_TIME_OFFSET DATETIME DEFAULT sysdatetimeoffset() NOT NULL,
DTO_GET_DATE DATETIMEOFFSET DEFAULT GETDATE() NOT NULL,
DTO_GET_UTC_DATE DATETIMEOFFSET DEFAULT GETUTCDATE() NOT NULL,
DTO_SYS_DATE_TIME DATETIMEOFFSET DEFAULT sysdatetime() NOT NULL,
DTO_SYS_UTC_DATE_TIME DATETIMEOFFSET DEFAULT sysutcdatetime() NOT NULL,
DTO_SYS_DATE_TIME_OFFSET DATETIMEOFFSET DEFAULT sysdatetimeoffset() NOT NULL
);
在这个表中,我添加了一个值,blah='helloworld!'代码>。结果数据为:
ID BLAH DT_GET_DATE DT_GET_UTC_DATE DT_SYS_DATE_TIME DT_SYS_UTC_DATE_TIME DT_SYS_DATE_TIME_OFFSET DTO_GET_DATE DTO_GET_UTC_DATE DTO_SYS_DATE_TIME DTO_SYS_UTC_DATE_TIME DTO_SYS_DATE_TIME_OFFSET
-- ------------ ------------------- ------------------- ------------------- -------------------- ----------------------- ---------------------------------- ---------------------------------- ---------------------------------- ---------------------------------- ----------------------------------
1 Hello World! 2012-02-15 08:58:41 2012-02-15 14:58:41 2012-02-15 08:58:41 2012-02-15 14:58:41 2012-02-15 08:58:41 2012-02-15 08:58:41.6000000 +00:00 2012-02-15 14:58:41.6000000 +00:00 2012-02-15 08:58:41.6005458 +00:00 2012-02-15 14:58:41.6005458 +00:00 2012-02-15 08:58:41.6005458 -06:00
有一个相应的存储过程,它只需从MIKE_TEMP
执行一个选择*,并将所有数据作为输出参数返回
访问此数据的Java代码是(为了清楚起见,仅包含“有趣的”导入):
这是通过JUnit测试实现的:
@Test
public void testDateData() throws Exception {
MikeTemp mt = dao.getMikeTemp();
assertNotNull("MT should not be null, but it is.", mt);
assertEquals(1, mt.getId());
assertEquals("Hello World!", mt.getBlah());
}
所有println的结果如下:
id = [1]
blah = [Hello World!]
dtGetDate = [2012-02-15T08:58:41.577-06:00]
dtGetUtcDate = [2012-02-15T14:58:41.577-06:00]
dtSysDateTime = [2012-02-15T08:58:41.580-06:00]
dtSysUtcDateTime = [2012-02-15T14:58:41.600-06:00]
dtSysDateTimeOffset = [2012-02-15T08:58:41.600-06:00]
dtoGetDate = [2012-02-15T08:58:41.600-06:00]
dtoGetUtcDate = [2012-02-15T14:58:41.600-06:00]
dtoSysDateTime = [2012-02-15T08:58:41.600-06:00]
dtoSysUtcDateTime = [2012-02-15T14:58:41.600-06:00]
dtoSysDateTimeOffset = [2012-02-15T08:58:41.600-06:00]
由于该服务器位于美国中部时区,我肯定希望看到-06:00的部分结果,但肯定不是所有结果。我是不是错过了什么?在这种情况下,使用java.util.Date
对象调用JodaDateTime(Object)
ctor是否正确?我还能/应该做什么我没有做的事
谢谢 不,不是这样做的。您使用的构造函数带有日期
,它只知道一个瞬间,并使用系统默认时区
正如BalusC所写,如果您想自己指定时区,可以将日历
传递到ResultSet.getTimestamp()
,但这与保存数据库中已经存在的信息不同
现在还不清楚您使用的是哪种JDBC驱动程序,您可能需要远离SimpleJDCCall
,但Microsoft JDBC驱动程序v3.0(与SQLServerResultSet
相同)可能会做正确的事情。鉴于您的数据类型不是真正可移植的,这意味着您的代码也不能真正可移植:(
您确实需要保留偏移量吗?如果不需要,您可能会集中精力使用“正常”JDBC调用来获取正确的瞬间,不幸的是,现在看起来它没有这样做。如果您想完全避免java.util.Date/Calendar
,这就是我所做的
SQL server端:
SELECT CONVERT(NVARCHAR, DateFieldName, 126) AS DateFieldIsoString
其中,DateFieldName
是一个datetimeoffset
字段,查询返回一个java.lang.String
将字符串
解析为JodaDateTime
:
DateTime datetime = ISODateTimeFormat.dateTimeParser().withOffsetParsed()
.parse(dateFieldAsString)
您的关键问题是java.util.Date
不存储自定义时区信息。它始终是UTC。为了给出合适的答案,这段代码从原始JDBC中抽象了太多,但您可能需要ResultSet#getTimestamp()
方法,其中您传递一个保存时区的java.util.Calendar
。感谢指向MSJDBC 3.0驱动程序的指针。我们目前正在使用同一驱动程序的2.0版本,但更新版本似乎将使我们能够在java代码中本机支持datetimeoffset
数据类型,而不会丢失i来自数据库端的信息。合理地确定这与我们要查找的非常接近。再次感谢!
DateTime datetime = ISODateTimeFormat.dateTimeParser().withOffsetParsed()
.parse(dateFieldAsString)