在Java中CET到GMT的功能

时间:2017-12-28 22:24:52

标签: java date

我试图将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

1 个答案:

答案 0 :(得分:0)

TL;博士

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 类取代。

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/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Europe/Paris" );  // Or "Europe/Berlin" or "Africa/Tunis" etc.
ZonedDateTime zdt = zdt.withZoneSameInstant( z ) ;

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore