地图数据库时间戳列UTC日历(JPA),并通过WebService的(JAX-WS),把它作为UTC日期

StackOverflow https://stackoverflow.com/questions/1821104

  •  10-07-2019
  •  | 
  •  

这听起来像一个简单的任务。结果 从DB获取UTC时间戳值和通过Web服务将其传递作为UTC日期。

我们有时间戳列DATE_COLUMN和存储在那里以UTC时间区的时间。

使用JPA,我们得到这个时间

@Column(name = "DATE_COLUMN")
private java.sql.Timestamp dateValue;

和,因为我们有通过Web服务在UTC通过这个时间(JAX-WS 2.0)我们有GETDATE和的setDate方法。结果, 我们感兴趣的是GETDATE。

public Calendar getDate()
{
   Calendar calendar = Calendar.getInstance(utcTimeZone);
   calendar.setTimeInMillis(dateValue.getTime());

   return calendar;
}

,你可能认为它应该这是行不通的。结果 这是因为应用程序的默认时区不是“UTC”。

下面为澄清的例子。结果 在DATE_COLUMN值等于“09年11月30日16:34:48,833045000”,当我把它翻译为UTC我得到“2009-11-30T14:34:48.833Z”。结果 所不同的是2小时。这是因为我的默认时区是“欧洲/赫尔辛基。”

同样的问题,如果你只是想 'DATE_COLUMN' 映射到Calendar

@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;

不过,我倾向于认为是在某个地方真钞。我希望你能指出来。

有帮助吗?

解决方案

我们决定使用下面的解决方案。结果 使用Date从数据库中检索日期。这是因为UtcTimestampAdapter是timezoneless类型。

@Column(name = "DATE_COLUMN")
@Temporal(TemporalType.TIMESTAMP)
private Date dateValue;

public Date getDate()
{
   return dateValue;
}

和通过WebService的在UTC(JAX-WS)我们创建Data改变从应用程序的默认区为UTC在封送处理阶段。发送

public class UtcTimestampAdapter extends XmlAdapter<XMLGregorianCalendar, Date>
{
   @Override
   public XMLGregorianCalendar marshal(Date date) throws Exception
   {
      GregorianCalendar calendar = new GregorianCalendar();
      calendar.setTime(date);

      DatatypeFactory dataTypeFactory = DatatypeFactory.newInstance();
      XMLGregorianCalendar xmlCalendar = 
         dataTypeFactory.newXMLGregorianCalendar(calendar);

      //Reset time zone to UTC
      xmlCalendar.setTimezone(0);

      return xmlCalendar;
   }

   @Override
   public Date unmarshal(XMLGregorianCalendar calendar) throws Exception
   {
      return calendar.toGregorianCalendar().getTime();
   }
}

然后,使该规则的模块中,我们加入包特定的设定等,因此所有<=> S场。

@XmlJavaTypeAdapter(value = UtcTimestampAdapter.class, type = Date.class)
@XmlSchemaType(name = "dateTime", type = XMLGregorianCalendar.class)
package com.companyname.modulename;

就是这样。现在,我们有封装所有逻辑在一个地方通用的解决方案。如果我们想通过网络服务来发送timezoneless日期为UTC在其他一些模块,我们只是标注特定的软件包。

其他提示

如果您需要Java进程来在UTC时区运行,这样做最简单的方法是通过添加以下JVM参数:

-Duser.timezone=UTC

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));似乎影响整个JVM。

这将导致,如果他们希望的本地时间的其他应用程序失败

另一种解决方案是仅在设置默认时区用于所述应用的@StartupBean

import java.util.TimeZone;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Startup
@Singleton
public class StartupBean {

    @PostConstruct
    public void initializeTheServer() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}

从此,日期对象的所有解释将基于UTC。这包括XML编组。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top