我只是尝试使用以下代码将XMLGregorianCalendar
(我从JAXWS获得)的实例转换为特定TimeZone中的GregorianCalendar
。
日期将在EST中出现,我想将其转换为GMT以进一步保存到DB
//soap response <ns4:TimeStamp>2016-06-18T04:43:54-04:00</ns4:TimeStamp>
//dtime is what i got from JAXB for the above date, so I wrote::
Date date = dTime.toGregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.US, null).getTime();
System.out.println(date);
输出:Sat Jun 18 14:13:54 IST 2016
由于上面没有按预期工作,所以我尝试了DateFormat并给出了预期的结果。
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
GregorianCalendar gc = dTime.toGregorianCalendar();
System.out.println(df.format(gc.getTime()));
输出:2016-06-18 08:43:54 +0000
这可能是什么问题,因为 toGregorianCalendar(...)没有给出所需的结果?
我还注意到上面从 toGregorianCalendar 获得的GregorianCalendar实例的fieldSet = false。不确定这是否是导致问题的原因。
java.util.GregorianCalendar中[时间= 1468382241000,的 areFieldsSet =假,areAllFieldsSet =假下,从宽=真,区= sun.util.calendar.ZoneInfo [ID = “UTC”,偏移= 0,dstSavings = 0,useDaylight =假,过渡= 0,lastRule =空],Firstdayofweek可= 1,minimalDaysInFirstWeek = 1,ERA = 1,YEAR = 2016,MONTH = 6,WEEK_OF_YEAR = 29,WEEK_OF_MONTH = 3,DAY_OF_MONTH = 12 ,DAY_OF_YEAR = 194,DAY_OF_WEEK = 3,DAY_OF_WEEK_IN_MONTH = 2,AM_PM = 1,HOUR = 11,HOUR_OF_DAY = 23,MINUTE = 57,SECOND = 21,微差= 0,ZONE_OFFSET = -14400000,DST_OFFSET = 0]
任何帮助将不胜感激.. !!
答案 0 :(得分:1)
请记住,Java Date
个对象没有时区。它们在UTC内部。时区仅在打印(格式化)时显示。
这个简单的代码有效:
XMLGregorianCalendar xmlCal = XMLGregorianCalendarImpl.parse("2016-06-18T04:43:54-04:00");
GregorianCalendar cal = xmlCal.toGregorianCalendar();
java.util.Date date = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(format.format(date)); // prints: 2016-06-18 08:43:54
由于您的目标是将其保存到数据库,因此您真的不在乎将其格式化为文本。假设您正在使用JDBC(而不是某些NoSQL),则需要Timestamp
。
XMLGregorianCalendar xmlCal = XMLGregorianCalendarImpl.parse("2016-06-18T04:43:54-04:00");
GregorianCalendar cal = xmlCal.toGregorianCalendar();
java.sql.Timestamp date = new java.sql.Timestamp(cal.getTimeInMillis());
现在,您可以使用PreparedStatement
将其提交给setTimestamp()
。
答案 1 :(得分:1)
myPreparedStatement
.setObject( // Exchange java.time objects with your database in JDBC 4.2 and later.
… , // Specify which `?` placeholder in your SQL statement.
myXMLGregorianCalendar // A legacy class. Better to use *java.time* whenever possible.
.toGregorianCalendar() // Convert from the one legacy class to another, as a bridge towards the modern `ZonedDateTime` class.
.toZonedDateTime() // Convert to the modern class.
.toInstant() // Adjust from a time zone to UTC. Same moment, same point on the timeline, different wall-clock time.
.atOffset( // Adjust from basic `Instant` class to the more flexible `OffsetDateTime` class, if your JDBC driver does not offer the optional support for `Instant`.
ZoneOffset.UTC // Specify UTC using this constant.
) // Returns a `OffsetDateTime` object.
)
您使用的是可怕的旧日期时间类,而这些类早已被JSR 310中定义的现代 java.time 类取代了。
将XMLGregorianCalendar(我从JAXWS获得)的实例转换为GregorianCalendar
首次通话XMLGregorianCalendar::toGregorianCalendar()
。
GregorianCalendar gc = myXMLGregorianCalendar.toGregorianCalendar() ;
从旧类GregorianCalendar
转换为现代java.time.ZonedDateTime
。 Call the new conversion method已添加到旧类中。
ZonedDateTime zdt = gc.toZonedDateTime() ;
日期将在EST中发布,我想将其转换为GMT
java.time.Instant
类代表UTC中的时刻,始终以UTC表示。您可以从Instant
中提取ZonedDateTime
。相同的时刻,不同的时钟时间。
Instant instant = zdt.toInstant() ;
进一步保存到数据库
如果JDBC驱动程序支持,则 可以将Instant
传递给数据库。 Instant
类型在JDBC 4.2中是可选的。
myPreparedStatement.setObject( … , instant ) ;
如果不支持,请使用OffsetDateTime
,因为JDBC 4.2需要支持。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
日期是美国东部时间
EST
不是实时区域。
以Continent/Region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
答案 2 :(得分:1)
我正在使用以下代码将具有给定时区(例如 GMT+0)的给定源的 XMLGregorianCalendar
转换为具有当前系统时区的 GregorianCalendar
:
GregorianCalendar.from(xmlGregorianCalendar
.toGregorianCalendar()
.toZonedDateTime()
.withZoneSameInstant(ZoneId.systemDefault()))
当您只使用XMLGregorianCalendar.toGregorianCalendar()
时,返回的GregorianCalendar
与源系统的时区相同,而不是当前系统的时区。 在收到数据时转换时区更安全:这样可以减少代码中潜在问题的数量,因为所有日期都基于系统时区。
例如:
XMLGregorianCalendar xmlGregorianCalendarFromSource = DatatypeFactory.newInstance()
.newXMLGregorianCalendar("1983-09-30T23:00:00.000Z"); // the source system is on GMT+0
GregorianCalendar gregorianCalendarWithSourceTZ = xmlGregorianCalendarFromSource.toGregorianCalendar();
GregorianCalendar gregorianCalendarWithSystemTZ = GregorianCalendar.from(xmlGregorianCalendarFromSource
.toGregorianCalendar()
.toZonedDateTime()
.withZoneSameInstant(ZoneId.systemDefault()));
System.out.println(xmlGregorianCalendarFromSource); // displays "1983-09-30T23:00:00.000Z" (i.e. GMT+0)
System.out.println(gregorianCalendarWithSourceTZ.toZonedDateTime()); // displays "1983-09-30T23:00Z[GMT]" (i.e. GMT+0)
System.out.println(gregorianCalendarWithSystemTZ.toZonedDateTime()); // displays "1983-10-01T00:00+01:00[Europe/Berlin]" (my system timezone is GMT+1 or GMT+2 depending on daylight saving)
答案 3 :(得分:0)
作为另一种途径,您可以考虑在代码中使用Date&#39;而不是XMLGregorianCalendars,使用jaxb绑定,如this堆栈溢出问题中所述。