将java日历对象从本地时间转换为UTC时间

将java日历对象从本地时间转换为UTC时间,java,datetime,utc,java.util.calendar,Java,Datetime,Utc,Java.util.calendar,如何将JavaCalendar对象从本地时间转换为UTC?这就是我所尝试的: Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(TimeZone.getTimeZone("UTC")); calendar.setTime(localDateTime.getTime()); SimpleDateFormat outputFmt = new SimpleDateFormat("MMM dd

如何将Java
Calendar
对象从本地时间转换为UTC?这就是我所尝试的:

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
    calendar.setTime(localDateTime.getTime());
    SimpleDateFormat outputFmt = new SimpleDateFormat("MMM dd, yyy h:mm a zz");
    String dateAsString = outputFmt.format(calendar.getTime());
    System.out.println(dateAsString)

时间总是以MT而不是GMT显示。我想在数据库中以UTC存储日历(我不关心时间的格式或显示)。

您需要在
SimpleDataFormat
上调用
setTimeZone
,而不是在
calendar
上调用:

//getting local time 
Calendar calendar = Calendar.getInstance(Locale.getDefault());

SimpleDateFormat outputFmt = new SimpleDateFormat("MMM dd, yyy h:mm a zz");
outputFmt.setTimeZone(TimeZone.getTimeZone("GMT")); //set timezone here

//shows calendar time correctly set    
System.out.println(outputFmt.format(calendar.getTime()));

您需要在
SimpleDateFormat
上调用
setTimeZone
,而不是在
Calendar
上调用:

//getting local time 
Calendar calendar = Calendar.getInstance(Locale.getDefault());

SimpleDateFormat outputFmt = new SimpleDateFormat("MMM dd, yyy h:mm a zz");
outputFmt.setTimeZone(TimeZone.getTimeZone("GMT")); //set timezone here

//shows calendar time correctly set    
System.out.println(outputFmt.format(calendar.getTime()));

下面是我如何将正常日期转换为UTC的。因此,首先将日历对象转换为日期对象:

public static String convertToUTC(Date date) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat.format(date);
}

下面是我如何将正常日期转换为UTC的。因此,首先将日历对象转换为日期对象:

public static String convertToUTC(Date date) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat.format(date);
}

不要将日期时间转换为字符串以存储到SQL数据库中。使用日期时间对象

我假设您正在将数据类型为
datetime
timestamp
且不带时区的数据存储到数据库列中,并且该列将包含UTC值(推荐做法)。在本例中,进一步假设您至少使用Java 8和JDBC 4.2,将UTC格式的
LocalDateTime
存储到数据库中

    ZonedDateTime dateTime = ZonedDateTime.of(
            2018, 7, 1, 9, 0, 0, 0, ZoneId.of("America/Denver"));
    LocalDateTime dateTimeInUtc = dateTime.withZoneSameInstant(ZoneOffset.UTC)
            .toLocalDateTime();
    System.out.println("UTC: " + dateTimeInUtc);

    PreparedStatement ps = yourDatabaseConnection.prepareStatement(
            "insert into your_table(date_time) values (?)");
    ps.setObject(1, dateTimeInUtc);
    ps.executeUpdate();
代码示例以7月1日上午9点在丹佛为例,将其转换并打印:

UTC:2018-07-01T15:00

然后将打印的UTC时间存储到数据库中。注意
setObject
方法的使用

您使用的
Calendar
类早已过时,而且设计总是很糟糕。如果您从旧式API获得了一个
日历
对象,而您现在无法更改或不想更改该对象,请先将其转换为
即时
,然后再从该对象进行进一步转换:

    Calendar localDateTime = // …;
    LocalDateTime dateTimeInUtc = localDateTime.toInstant()
            .atOffset(ZoneOffset.UTC)
            .toLocalDateTime();
我应该在这里使用LocalDateTime吗? 编辑:这取决于数据库中使用的数据类型和JDBC驱动程序的要求。正如我所说,我假设您知道数据库中的值以UTC为单位,并且您使用的数据类型没有时区,因此数据库不知道。如果是这种情况,那么使用带有时区或偏移量信息的Java类型是没有意义的,因为当您存储它时,它将丢失

有些人会说,在这种情况下,您已经在数据库中使用了错误的类型,并建议您使用带有时区的
时间戳
列,以便数据库也知道时间是UTC。在这种情况下,您当然应该在存储的值中包含偏移信息。例如,PostgreSQL JDBC驱动程序在本例中需要一个符合逻辑的
OffsetDateTime
(因为它存储的是UTC偏移量,而不是实时时区)

根据DBMS的功能,可能还有其他选项。我已经在底部包括了几个链接,你可以查看更多

你的代码出了什么问题? 您对
日历的转换工作正常,并在UTC中为您提供了相同的时间点。当您尝试将其格式化为
字符串时,问题才开始出现:当您使用
calendar.getTime()
时,您将得到一个
日期
对象,该对象包含相同的时间点(仍然是正确的时间点),但
日期
无法保存时区信息,因此您丢失了有关UTC的信息。接下来,使用
SimpleDataFormat
格式化
日期。
SimpleDataFormat
有一个时区,如果您不自己设置,它将使用JVM的时区设置,这可能是山区时间的一种变体。所以你的时间是用MT打印的

链接
  • 解释如何使用现代java日期和时间API
    java.time
  • 指定要与哪些数据库类型一起使用的
    java.time
    类型

不要将日期时间转换为字符串以存储到SQL数据库中。使用日期时间对象

我假设您正在将数据类型为
datetime
timestamp
且不带时区的数据存储到数据库列中,并且该列将包含UTC值(推荐做法)。在本例中,进一步假设您至少使用Java 8和JDBC 4.2,将UTC格式的
LocalDateTime
存储到数据库中

    ZonedDateTime dateTime = ZonedDateTime.of(
            2018, 7, 1, 9, 0, 0, 0, ZoneId.of("America/Denver"));
    LocalDateTime dateTimeInUtc = dateTime.withZoneSameInstant(ZoneOffset.UTC)
            .toLocalDateTime();
    System.out.println("UTC: " + dateTimeInUtc);

    PreparedStatement ps = yourDatabaseConnection.prepareStatement(
            "insert into your_table(date_time) values (?)");
    ps.setObject(1, dateTimeInUtc);
    ps.executeUpdate();
代码示例以7月1日上午9点在丹佛为例,将其转换并打印:

UTC:2018-07-01T15:00

然后将打印的UTC时间存储到数据库中。注意
setObject
方法的使用

您使用的
Calendar
类早已过时,而且设计总是很糟糕。如果您从旧式API获得了一个
日历
对象,而您现在无法更改或不想更改该对象,请先将其转换为
即时
,然后再从该对象进行进一步转换:

    Calendar localDateTime = // …;
    LocalDateTime dateTimeInUtc = localDateTime.toInstant()
            .atOffset(ZoneOffset.UTC)
            .toLocalDateTime();
我应该在这里使用LocalDateTime吗? 编辑:这取决于数据库中使用的数据类型和JDBC驱动程序的要求。正如我所说,我假设您知道数据库中的值以UTC为单位,并且您使用的数据类型没有时区,因此数据库不知道。如果是这种情况,那么使用带有时区或偏移量信息的Java类型是没有意义的,因为当您存储它时,它将丢失

有些人会说,在这种情况下,您已经在数据库中使用了错误的类型,并建议您使用带有时区的
时间戳
列,以便数据库也知道时间是UTC。在这种情况下,您当然应该在存储的值中包含偏移信息。例如,PostgreSQL JDBC驱动程序在本例中需要一个符合逻辑的
OffsetDateTime
(因为它存储的是UTC偏移量,而不是实时时区)

根据DBMS的功能,可能还有其他选项。我已经在底部包括了几个链接,你可以查看更多

你的代码出了什么问题? 哟