我有一个JAX-B java web服务,我用它来更新数据库。我正在更新的表中的每一行都由类似于下面的对象表示: -
public class Item {
private String id;
private Date startDate;
private Date endDate;
public Item() { }
...
}
这个类在一个单独的程序中实例化,然后通过类似于下面的消息通过SOAP传递: -
...
<item>
<id>D001IAAC030</id>
<startDate>2009-09-17T00:00:00.000+01:00</startDate>
<endDate>2009-10-01T00:00:00.000+01:00</endDate>
</item>
...
如您所见,由于BST,UTC时间偏移为+01:00。但是,当对象在服务器上进行编组时(也在我的本地计算机上),它将恢复为GMT并从日期中扣除1小时。
你能告诉我怎么做: -
TIA,
URF
答案 0 :(得分:5)
您只需要记住,Date对象(始终)将日期/时间存储为UTC / GMT时区中自纪元以来的毫秒数。让人们兴奋的是Date.toString()方法在JVM的默认时区(通过内部Calendar对象)返回文本表示。 (看看JDK源代码。)
例如在我的机器上
Date now = new Date();
System.out.println(now.toString());
System.out.println(now.getTime())
将给出
Fri Oct 02 06:56:24 EST 2009
1254430584531
毫秒数是GMT / UTC时区中自纪元以来的实际毫秒数。
操作/使用Date对象时,应始终使用Date格式化程序或Calendar实例。例如:
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:MM:ss zzz yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(now.toString());
System.out.println(sdf.format(now));
给出
Fri Oct 02 06:56:24 EST 2009
Thu Oct 01 20:56:24 UTC 2009
总结:始终将Date对象视为仅数据,自纪元以来的毫秒数。 (不要使用任何Deprecated方法,除非你理解它显示的内容,否则不要使用toString()。)要显示,格式化,转换(添加减去时间等)日期/时间总是使用Calendar实例或DateFormat实施,很难出错。
正如Javadoc所说的日期:
'在JDK 1.1之前,Date类有两个附加功能。它允许将日期解释为年,月,日,小时,分钟和秒值。它还允许格式化和解析日期字符串。不幸的是,这些功能的API不适合国际化。从JDK 1.1开始,Calendar类应该用于在日期和时间字段之间进行转换,而DateFormat类应该用于格式化和解析日期字符串。不推荐使用Date中的相应方法。
使用Date,Calendars和Formatters对自己进行实验并阅读Javadoc,它会变得更加清晰。
对于问题的第一部分,您不需要设置Glassfish服务器的时区来容纳您的数据。如果要使用数据/时间值存储时区数据,请在对象中使用日历而不是日期。或者像我通常那样,所有内容都存储为UTC时间(在对象中的db和Date实例中),时区仅在显示/输出或解析数据时使用。因此,当收到您的数据时,使用DateFormat或等效的时间区域设置为+01:00解析它(如果它附加了时区,它可以自动从时间字符串中选择,如示例所示)。
我不清楚你的问题的第二部分,但是如果你的web服务端的实现正确处理日期并正确解析它,它应该在没有你干预的情况下处理它。
答案 1 :(得分:4)
更改glassfish服务器中使用的时间:
C:\ glassfish4 \的glassfish \ bin)中
asadmin create-jvm-options -Duser.timezone=UTC
asadmin restart-domain
答案 2 :(得分:2)
我现在解决了我的问题,并打算帮助其他开发人员,按照一步一步的步骤
输入你的玻璃鱼
c: \ glassfish3 \ bin \> asadmin list-jvm-options
查看列表是否显示
<jvm-options>-Duser.timezone=UTC</jvm-options>
没有出现的情况转到domain.xml文件并搜索jvm-options并添加命令行
<jvm-options>-Duser.timezone = Brazil / East </ jvm-options> substituting the Brazil / East timezone by country
然后重启服务器并开心
答案 3 :(得分:1)
Locale
无关 Locale
与时区无关。对于日期时间工作,Locale
确定两件事:(a)用于翻译日期名称,月份名称等的人类语言,以及(b)句点与逗号等问题的文化规范,元素的排序(日期之前/之后等)。
请勿按照另一个答案的建议更改JVM的当前默认时区。更改会影响该JVM中所有应用程序的所有线程中的所有代码,并在运行时期间立即执行。
您正在使用旧的过时类。与最早版本的Java捆绑在一起的旧日期时间类已被证明设计糟糕,令人困惑且麻烦。避免他们。现在取代了Java 8及更高版本中内置的java.time框架。这些类取代了旧的麻烦的日期时间类,如java.util.Date
。见Oracle Tutorial。许多功能已经被后端移植到Java 6&amp; ThreeTen-Backport中的7,并在ThreeTenABP中进一步适应Android。
您的日期时间字符串恰好符合ISO 8601标准。在解析/生成表示日期时间值的字符串时,默认情况下会在java.time类中使用此标准定义的格式。
String input = "2009-09-17T00:00:00.000+01:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
如果您想在时间轴上使用相同的时刻,但需要UTC,请提取Instant
个对象。最好坚持使用UTC和本课程来完成大部分业务逻辑和数据交换以及数据存储。
Instant instant = odt.toInstant();
要生成ISO 8601格式的字符串,请调用toString
。
String output = instant.toString(); // 2009-09-16T23:00:00Z
要查看调整到某个时区wall-clock time的相同值,请应用ZoneId
获取ZonedDateTime
个对象。时区是用于处理Daylight Saving Time (DST)等异常的UTC 加规则的偏移量。
ZoneId zoneId = ZoneId.of( "Europe/London" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
此外,如果您需要捕获UTC中的当前时刻:
Instant instant = Instant.now();
Java Architecture for XML Binding (JAXB)可能尚未直接支持java.time类型。
在添加直接支持之前,您可以使用适用于java.time类型的适配器,如问题this Answer by Blaise Doughan中所讨论的Can JAXB handle java.time objects?。您可以使用this implementation或通过建模一个或此similar one for Joda-Time库来编写自己的文件。
LocalDate
00:00:00
的那些时间值让我想知道您是否真的想要表示仅限日期的值。在仅限日期的值中,您不关心时间或时区。如果是这种情况,请考虑使用LocalDate
类。