我试图将CET时间格式转换为GMT。 原因是因为我从XML获取日期并将其插入到使用GMT日期格式的另一个系统中。因此,无论我插入的日期是过去的一天。
这里我从XML获取并将其插入Java对象:
Date dob = DateUtils.fromXMLGregorianCalendar(customer.getDateOfBirth());
toYYYYMMDD(dob);
CETtoGMT(dob);
personalAccount.setBirthDate(dob);
我的职能:
public static String toYYYYMMDD(Date day) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String date = formatter.format(day);
return date;
}
public String CETtoGMT(Date cetDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = formatter.format(cetDate);
return date;
}
我不确定我做错了什么,但我的测试说我正在使用奥斯陆时区作为对象personalAccount出生日期:
Sun Feb 24 00:00:00 CET 1990
cdate = {Gregorian$Date@3163} "1990-02-24T00:00:00.000+0100"
cachedYear = 1990
cachedFixedDateJan1 = 724642
cachedFixedDateNextJan1 = 725007
era = null
year = 1990
month = 2
dayOfMonth = 24
dayOfWeek = 1
leapYear = false
hours = 0
minutes = 0
seconds = 0
millis = 0
fraction = 0
normalized = true
zoneinfo = {ZoneInfo@3165} "sun.util.calendar.ZoneInfo[id="Europe/Oslo",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=141,lastRule=java.util.SimpleTimeZone[id=Europe/Oslo,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]"
zoneOffset = 3600000
daylightSaving = 0
forceStandardTime = false
locale = null
答案 0 :(得分:0)
customer.getDateOfBirth() // Assuming this call returns a `XMLGregorianCalendar`.
.toGregorianCalendar() // Convert `XMLGregorianCalendar` to the legacy class `GregorianCalendar`, en route to a `ZonedDateTime` in next line.
.toZonedDateTime() // Convert from `GregorianCalendar` to `ZonedDateTime`, from legacy class to modern class.
.toOffsetDateTime() // Convert to `OffsetDateTime` to better document that we are moving to an offset-from-UTC rather than a full time zone.
.withOffsetSameInstant( ZoneOffset.UTC ) // Adjust into UTC. Same moment in time, same point on the timeline, but viewed through a different wall-clock time.
.toLocalDate() // Extract a date-only value, without time zone and without time-of-day.
.toString() // Generate a string in standard ISO 8601 format YYYY-MM-DD.
;
Date
是UTC,但其toString
不是 java.util.Date
类代表UTC的时刻。不幸的是,它的toString
方法在生成字符串时会混淆地应用JVM的当前默认时区。 Stack Overflow已经多次解释过这个问题。
Date
是现在遗留下来的一个麻烦的旧日期时间类,完全由现代 java.time 类取代。
您可以通过调用添加到旧类的新方法来转换旧类。如果您的代码返回XMLGregorianCalendar
对象,请先转换为GregorianCalendar
。
GregorianCalendar gc = customer.getDateOfBirth().toGregorianCalendar() ; // Returning a XMLGregorianCalendar, then converting to a GregorianCalendar.
转换为java.time。与GregorianCalendar
对应的是ZonedDateTime
。
ZonedDateTime zdt = gc.toZonedDateTime() ;
您的目标是UTC。所以转换为OffsetDateTime
,然后调整为UTC。
OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC ) ;
显然,您希望仅进行UTC调整的日期,因此请提取LocalDate
来表示没有时间且没有时区的日期。
LocalDate ld = odt.toLocalDate() ;
向所有读者表明......确定日期需要一个时区。对于任何特定时刻,日期在全球范围内变化。例如,Paris France午夜后的几分钟是Montréal Québec中仍然是“昨天”的新一天。我们必须完成所有这些步骤以保留重要的时区(或从UTC偏移)信息,以便获得正确的日期。
您想要的输出似乎是标准ISO 8601格式的字符串。在解析/生成字符串时,java.time类默认使用标准格式。因此无需指定格式化模式。
String output = ld.toString() ;
顺便说一下,永远不要使用CET
或其他这样的3-4个字母伪区域。这些不是真正的时区,不是标准化的,甚至不是唯一的(!)。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Europe/Paris" ); // Or "Europe/Berlin" or "Africa/Tunis" etc.
ZonedDateTime zdt = zdt.withZoneSameInstant( z ) ;
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。