Java Web 服务中使用了错误的时区
我有一个 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 小时。
您能告诉我如何: -
- 将 Glassfish 服务器设置为正确的区域设置,以便日期被识别为 BST。
- 告诉我如何在 Web 服务端拦截编组,以便我可以在设置日期之前自己设置时区。
TIA,
乌尔夫
I have a JAX-B java web service which I'm using to update a database. Each row in the table that I'm updating is represented by an object similar to below: -
public class Item {
private String id;
private Date startDate;
private Date endDate;
public Item() { }
...
}
This class is being instantiated in a separate program and then passed via SOAP in a message similar to below: -
...
<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>
...
As you can see, due to BST the UTC time has a +01:00 offset. However, when the object is marshalled on the server (which is on my local machine as well), it reverts to GMT and deducts 1 hour from the dates.
Can you tell me how I can either: -
- Set my Glassfish server to right locale so that the dates are recognised as being BST.
- Tell me how I can intercept the marshalling at the web service end so that I can set the timezone myself before the date is set.
TIA,
Urf
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您只需要记住,Date 对象(始终)将日期/时间存储为自 UTC/GMT 时区纪元以来的毫秒数。令人困惑的是 Date.toString() 方法返回 JVM 默认时区的文本表示形式(通过内部 Calendar 对象)。 (看看 JDK 源代码。)
例如,在我的机器上,
。
毫秒数是自 GMT/UTC 时区纪元以来的实际毫秒数
在操作/使用 Date 对象时,您应该始终使用 Date 格式化程序或 Calendar 实例。例如:
给出
总结:始终将 Date 对象视为仅数据,自纪元以来的毫秒数。 (不要使用任何已弃用的方法,也不要使用 toString() ,除非您了解它显示的内容。)要显示、格式化、转换(加减时间等)日期/时间,请始终使用 Calendar 实例或 DateFormat执行起来很难出错。
正如 Javadoc 对于 Date 的说法:
“在 JDK 1.1 之前,Date 类有两个附加函数。它允许将日期解释为年、月、日、小时、分钟和秒值。它还允许格式化和解析日期字符串。不幸的是,这些函数的 API 不适合国际化。从 JDK 1.1 开始,Calendar 类应用于在日期和时间字段之间进行转换,而 DateFormat 类应用于格式化和解析日期字符串。 Date 中的相应方法已被弃用。
自己尝试一下日期、日历和格式化程序并阅读 Javadoc,它会变得更清晰一些。
对于问题的第一部分,您不需要设置 Glassfish 服务器的时区来容纳您的数据。如果您想将时区数据与数据/时间值一起存储,请在对象中使用日历而不是日期。或者像我通常做的那样,所有内容都存储为 UTC 时间(在对象中的数据库和日期实例中),并且仅在显示/输出或解析数据时使用时区。因此,当收到数据时,使用 DateFormat 或等效的时区设置为 +01:00 的数据进行解析(如果它附加了时区,如示例所示,它可能会自动从时间字符串中获取该数据)。
我不具体了解你问题的第二部分,但如果你的网络服务端的实现正确处理日期并正确解析它们,它应该在没有你干预的情况下处理这个问题。
You just need to remember that a Date object (always) stores date/time as milliseconds since epoch in the UTC/GMT time zone. What trips people up is that the Date.toString() method returns a text representation in the JVM's default time zone (via an internal Calendar object). (Take a look at JDK source code.)
So for instance on my machine
will give
The milliseconds number being the actual milliseconds since epoch in the GMT/UTC time zone.
You should always use Date formatters or Calendar instances when manipulating/using Date objects. For example:
gives
In summary: Always treat a Date object as data only, milliseconds since epoch. (Don't use any of the Deprecated methods, and don't use toString() unless you understand what it is displaying.) To display, format, convert (add subtract time etc) date/time always use a Calendar instance or DateFormat implementation and it is hard to go wrong.
As the Javadoc says for Date:
'Prior to JDK 1.1, the class Date had two additional functions. It allowed the interpretation of dates as year, month, day, hour, minute, and second values. It also allowed the formatting and parsing of date strings. Unfortunately, the API for these functions was not amenable to internationalization. As of JDK 1.1, the Calendar class should be used to convert between dates and time fields and the DateFormat class should be used to format and parse date strings. The corresponding methods in Date are deprecated.'
Experiment for yourself with Date's, Calendars and Formatters and read the Javadoc and it will become a little clearer.
For the first part of your question you shouldn't need to set the time zone of your Glassfish server to accommodate your data. If you want to store time zone data with your data/time values then use Calendar rather than Date in your objects. Or as I usually do, everything is stored as UTC time (in db and Date instances in objects) and time zones are only used when data is displayed/outputted or parsed. So when your data is received parse it with a DateFormat or equivalent with time zone set to +01:00 (it may pick that up from the time string automatically if it has the time zone attached as you example shows).
I don't know specifically about the second part of your question but if the implementation of your web-service end handles Dates correctly and parses them correctly it should handle this without your intervention.
要更改 glassfish 服务器中使用的 UTC 时间:
C:\glassfish4\glassfish\bin)
To change Time Used UTC in glassfish server:
C:\glassfish4\glassfish\bin)
我现在解决了我的问题,为了帮助其他开发人员,请按照步骤
在 glassfish 中输入,
看看列表是否出现,
情况没有出现,转到domain.xml 文件并搜索 jvm-options 并添加命令行
然后重新启动服务器并高兴
I solved my problem right now and with the intention of helping others developers, follow the step by step
type in your glassfish
see if the list appears
case does not appear go to the domain.xml file and search for jvm-options and add the command line
then restart the server and be happy
Locale
不相关Locale
与时区无关。对于日期时间工作,Locale
确定两件事:(a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 句号等问题的文化规范与逗号相比,元素的排序(日期之前/之后的月份等)。不要更改默认时区
不要按照另一答案的建议更改 JVM 的当前默认时区。更改会影响该 JVM 内所有应用程序的所有线程中的所有代码,并且在运行时立即执行。
java.time
您正在使用旧的过时的类。事实证明,与最早版本的 Java 捆绑在一起的旧日期时间类设计不佳、令人困惑且麻烦。避开他们。现在已被 java.time Java 8 及更高版本中内置的框架。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date。请参阅 Oracle 教程。许多功能已向后移植到 Java 6 和 Java 6。 ThreeTen-Backport 中的 7 并在 ThreeTenABP。
ISO 8601
您的日期时间字符串恰好符合 ISO 8601 标准。在解析/生成表示日期时间值的字符串时,java.time 类中默认使用此标准定义的格式。
如果您想要时间轴上的相同时刻,但在UTC中,请提取
即时< /代码> 对象。对于您的大部分业务逻辑以及数据交换和数据存储,最好坚持使用 UTC 和此类。
要生成 ISO 8601 格式的字符串,请调用
toString
。要查看调整到某个时区的挂钟时间的相同值,请应用
ZoneId
获取ZonedDateTime
对象。时区是相对于 UTC 的偏移加上用于处理异常的规则,例如 夏令时 (DST)。另外,如果您需要捕获 UTC 中的当前时刻:
JAXB 适配器
Java Architecture for XML Binding (JAXB) 可能尚不直接支持 java.time 类型。
在添加直接支持之前,您可以使用 java.time 类型的适配器,如 Blaise Doughan 的此回答中所述问题,JAXB 可以处理 java.time 对象吗?。您可以使用此实现或通过建模一个或这个 < a href="http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html" rel="nofollow noreferrer">Joda-Time 的类似内容 图书馆。
LocalDate
这些
00:00:00
的时间值让我想知道您是否真的试图表示仅日期值。在仅日期值中,您不关心一天中的时间或时区。如果是这种情况,请考虑使用LocalDate
类。Locale
irrelevantLocale
has nothing to do with time zone. For date-time work, aLocale
determines two things: (a) human language to use in translating name of day, name of month, and such, and (b) cultural norms for issues such as period versus comma, ordering of elements (month before/after date, etc.).Do not change default time zone
Do not change the current default time zone of the JVM as suggested on one other answer. Changing affects all code in all threads of all apps within that JVM, and does so immediately during runtime.
java.time
You are using old outmoded classes. The old date-time classes bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. Avoid them. Now supplanted by the java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as
java.util.Date
. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.ISO 8601
Your date-time strings happen to comply with the ISO 8601 standard. This formats defined by this standard are used by default in the java.time classes when parsing/generating Strings that represent date-time values.
If you want the same moment on the timeline but in UTC, extract an
Instant
object. Best to stick to UTC and this class for much of your business logic and data-exchange and data-storage.To generate a String in ISO 8601 format, call
toString
.To see the same value adjusted into the wall-clock time of some time zone, apply a
ZoneId
to get aZonedDateTime
object. A time zone is an offset-from-UTC plus rules for handling anomalies such as Daylight Saving Time (DST).Also, if you need to capture current moment in UTC:
Adapter for JAXB
The Java Architecture for XML Binding (JAXB) may not yet support java.time types directly.
Until direct support is added, you can use an adapter for java.time types as discussed in this Answer by Blaise Doughan to the Question, Can JAXB handle java.time objects?. You might use this implementation or write your own by modeling that one or this similar one for Joda-Time library.
LocalDate
Those time-of-day values of
00:00:00
make me wonder if you are really trying to represent date-only values. In a date-only value, you do not care about time-of-day nor time zone. If that is the case, consider using theLocalDate
class.