将数据库时间戳列映射到 UTC 日历 (JPA) 并通过 WebService (jax-ws) 将其作为 UTC 日期传递
这听起来像是一个简单的任务。
从数据库获取 UTC 时间戳值,并通过 Web 服务将其作为 UTC 日期传递。
我们有时间戳列 DATE_COLUMN 并以 UTC 时区存储时间。
通过 JPA,我们可以得到这个时间,
@Column(name = "DATE_COLUMN")
private java.sql.Timestamp dateValue;
并且由于我们必须通过 UTC (Jax-ws 2.0) 中的 Web 服务传递这个时间,所以我们有 getDate 和 setDate 方法。
我们对 getDate 感兴趣。
public Calendar getDate()
{
Calendar calendar = Calendar.getInstance(utcTimeZone);
calendar.setTimeInMillis(dateValue.getTime());
return calendar;
}
这并不像您想象的那样起作用。
这是因为应用程序的默认时区不是“UTC”。
这是一个澄清的例子。
DATE_COLUMN 中的值等于“30.11.09 16:34:48,833045000”,当我将其转换为 UTC 时,我得到“2009-11-30T14:34:48.833Z”。
时差是2小时。这是因为我的默认时区是“欧洲/赫尔辛基”。
如果您只想将“DATE_COLUMN”映射到日历,也会出现同样的问题,
@Column(name = "DATE_COLUMN")
@Temporal(TemporalType.TIMESTAMP)
private Calendar dateValue;
public Calendar getDate()
{
calendar.setTimeZone(utcTimeZone);
return calendar;
}
我不想更改应用程序的时区,因为它看起来不像解决方案。
现在我们只有两个选择。
首先。计算应用程序时区和UTC之间的偏移量,并在calendar.setTimeZone中自动相减后手动添加。
public Calendar getDate()
{
Calendar calendar = Calendar.getInstance(utcTimeZone);
calendar.setTimeInMillis(dateValue.getTime());
int offset = TimeZone.getDefault().getOffset(dateValue.getTime());
calendar.add(Calendar.MILLISECOND, offset);
return calendar;
}
第二。通过 Web 服务将 dateValue 作为 Long
传递。除了我们丢失了 wsdl 中字段的真实类型之外,这还不错。
我想象的解决方案是
@Column(name = "DATE_COLUMN")
@Temporal(type = TemporalType.TIMESTAMP, timezone = 'UTC')
private Calendar dateValue;
但我倾向于认为某个地方有真正的解决方案。我希望你能指出这一点。
This sounds like a simple task.
Get UTC timestamp value from DB and pass it as UTC date via Web Service.
We have timestamp column DATE_COLUMN and store there time in UTC time zone.
With JPA we get this time with
@Column(name = "DATE_COLUMN")
private java.sql.Timestamp dateValue;
And as we have to pass this time via Web Service in UTC (Jax-ws 2.0) we have getDate and setDate methods.
We are interested in getDate.
public Calendar getDate()
{
Calendar calendar = Calendar.getInstance(utcTimeZone);
calendar.setTimeInMillis(dateValue.getTime());
return calendar;
}
This doesn't work as you may think it should.
And this is because application's default time zone is not 'UTC'.
Here is an example for clarification.
Value in the DATE_COLUMN equals to "30.11.09 16:34:48,833045000", when I translate it to UTC I get "2009-11-30T14:34:48.833Z".
The difference is 2 hours. And this is because my default time zone is "Europe/Helsinki".
Same problem if you just want to map 'DATE_COLUMN' to Calendar
@Column(name = "DATE_COLUMN")
@Temporal(TemporalType.TIMESTAMP)
private Calendar dateValue;
public Calendar getDate()
{
calendar.setTimeZone(utcTimeZone);
return calendar;
}
I don't want to change application's time zone because it doesn't look like the solution.
By now we have only two options.
First. Calculate offset between application's time zone and UTC and add it manually after automatic subtraction in the calendar.setTimeZone.
public Calendar getDate()
{
Calendar calendar = Calendar.getInstance(utcTimeZone);
calendar.setTimeInMillis(dateValue.getTime());
int offset = TimeZone.getDefault().getOffset(dateValue.getTime());
calendar.add(Calendar.MILLISECOND, offset);
return calendar;
}
Second. Pass dateValue as Long
via Web Service. Which is not bad except that we lose real type of the field in wsdl.
My imaginary solution is
@Column(name = "DATE_COLUMN")
@Temporal(type = TemporalType.TIMESTAMP, timezone = 'UTC')
private Calendar dateValue;
But I tend to think that there is the real one somewhere. And I hope you can point it out.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我们决定使用以下解决方案。
使用
Date
从数据库中检索日期。这是因为Date
是无时区类型。为了通过 UTC (jax-ws) 中的 WebService 发送它,我们创建了
UtcTimestampAdapter
来在编组阶段将区域从应用程序的默认值更改为 UTC。然后,为了对该模块中的所有数据字段启用此规则,我们添加了包特定设置,如下所示。
就是这样。现在我们有了将所有逻辑封装在一处的通用解决方案。如果我们想通过其他模块中的 Web 服务以 UTC 形式发送无时区日期,我们只需注释某个包即可。
We decided to use following solution.
Use
Date
for retrieving date from database. It is becauseDate
is timezoneless type.And to send it via WebService in UTC (jax-ws) we created
UtcTimestampAdapter
to change zone from application's default to UTC in the marshaling phase.Then to enable this rule to all
Data
s fields in the module we added package specific setting like so.That's it. Now we have generic solution which encapsulate all logic in one place. And if we want to send timezoneless dates as UTC via web service in some other module we will just annotate certain package.
如果您需要 java 进程在 UTC 时区运行,最简单的方法是添加以下 JVM 参数:
If you need the java process to run at the UTC timezone, the easiest way to do so is by adding the following JVM parameter:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
似乎正在影响整个 JVM。如果其他应用程序期待当地时间,这将导致其他应用程序失败
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
seems to be affecting the entire JVM.This will cause other applications fail if they were expecting local time
另一个解决方案是仅在 @StartupBean 中设置应用程序的默认时区:
从那时起,Date 对象的所有解释都将基于 UTC。这包括 XML 编组。
Another solution is to set the default timezone for the application only in a
@StartupBean
:From then on, all interpretation of Date objects will be based on UTC. This includes XML marshalling.