java - 本地日期到公历日历的转换

标签 java

我正在尝试将 LocalDate 转换为 GregorianCalendar,但 GregorianCalendar 输出给出的日期比 LocalDate 早一天。

下面是代码片段:

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.GregorianCalendar;

public class Test {
    public static void main(String[] arg){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        final LocalDate localDate = LocalDate.now(ZoneId.of("Australia/Victoria")).withDayOfMonth(16).withMonth(10).withYear(2017);
        final GregorianCalendar gregorianCalendar = GregorianCalendar.from(localDate.atStartOfDay(ZoneId.of("Australia/Victoria")));
        System.out.println(format.format(gregorianCalendar.getTime())); //prints 2017-10-15
    }
}

当代码在时区不是“澳大利亚/维多利亚”的计算机上运行时,就会出现问题。

谁能帮我指出我做错了什么?

最佳答案

tl;博士

您正在将可怕的遗留类与现代java.time类混合在一起。 不要这样做。

LocalDate
.parse( "2017-10-16" )
.atStartOfDay(
    ZoneId.of( "Australia/Victoria" )
)

如果您必须使用糟糕的 GregorianCalendar 类,请使用添加到旧类中的新转换方法。

GregorianCalendar  // Terrible legacy class. Use only if you *must*. 
.from(
    LocalDate
    .parse( "2017-10-16" )
    .atStartOfDay(
        ZoneId.of( "Australia/Victoria" )
    )
)

详细信息

您的代码是可怕的遗留日期时间类(SimpleDateFormatGregorianCalendar)与现代java.time 取代它们的类 ( LocalDate )。

具体来说,ZonedDateTime 取代了 GregorianCalendar

LocalDate 仅表示日期,没有时间和时区。相比之下,ZonedDateTime(和 GregorianCalendar)表示一个时刻:日期、时间和时区。

LocalDate开始。

LocalDate ld = LocalDate.parse( "2017-10-16" ) ;

指定一天中的某个时间。

LocalTime lt = LocalTime.of( 15 , 30 ) ;  // 3:30 PM.

指定您想要的时区。

ZoneId z = ZoneId.of( "Australia/Victoria" ) ;

组合起来得到一个ZonedDateTime、一个时刻、时间轴上的一个特定点。

ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

或者您可能想使用一天中的第一时刻作为一天中的时间部分。不要将其硬编码为 00:00:00。某些区域中的某些日期在其他时间开始,例如 01:00:00。让java.time确定第一个时刻。

ZonedDateTime zdt = ld.atStartOfDay( z ) ;  // Determine the first moment of the day on that date in that zone.

在 UTC 中查看同一时刻。提取始终采用 UTC 格式的Instant

Instant instant = zdt.toInstant() ;

请注意,上述代码全部均来自java.time包系列类。

尽可能避免使用GregorianCalendar。但如果您必须与尚未更新到 java.time 的旧代码进行互操作,请进行转换。查看添加到类中的新to.../from...转换方法。在这种情况下,请参阅GregorianCalendar.from .

GregorianCalendar gc = GregorianCalendar.from( zdt ) ;

Table of date-time types in Java, both modern and legacy.

关于java - 本地日期到公历日历的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49667772/

相关文章:

java - 如果程序在没有关闭流的情况下关闭,FileInputStream 访问的文件会发生什么情况?

java - Android 计时器 : time format issue

SimpleDateFormat 中的 Java 日期模式在 SQL 数据库中不起作用

java - 使用hibernate从数据库中检索blob并使用jsp在网页上显示

java - Netty UDP session 管理

java - 如何让 dbUnit 或 hibernate 停止从我的日期中减去一个小时?

java - iText 7 - 设置单元格宽度

java - Stanford 词性标注器在 Java 中的使用

java - 请求可以直接到达 ejb 容器还是应该首先到达 Web 容器。有人可以解释一下吗?

java - 在向 EditText 添加行时,如何使 ScrollView 动态变化?