我正在尝试将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
}
}
当代码在具有“澳大利亚/维多利亚”以外的时区的机器上运行时出现问题。
谁能帮助我指出我在做什么错?
答案 0 :(得分:2)
将TimeZone
设置为SimpleDateFormat
,如
public class Test {
public static void main(String[] arg){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
ZoneId zoneId = ZoneId.of("Australia/Victoria");
format.setTimeZone(TimeZone.getTimeZone(zoneId));
final LocalDate localDate = LocalDate.now(zoneId).withDayOfMonth(16).withMonth(10).withYear(2017);
final GregorianCalendar gregorianCalendar = GregorianCalendar.from(localDate.atStartOfDay(zoneId));
System.out.println(format.format(gregorianCalendar.getTime())); //prints 2017-10-16
}
}
答案 1 :(得分:1)
您正在将可怕的旧类与现代的 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" )
)
)
您的代码是可怕的旧式日期时间类(SimpleDateFormat
,GregorianCalendar
)和现代的 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看到同一时刻。提取一个Instant
,它始终使用UTC。
Instant instant = zdt.toInstant() ;
请注意,上述代码的 all 全部来自 java.time 包类家族。
尽可能避免使用GregorianCalendar
。但是,如果您必须与尚未更新为 java.time 的旧代码进行互操作,请进行转换。查看添加到 old 类的新to…
/ from…
转换方法。在这种情况下,请参见GregorianCalendar.from
。
GregorianCalendar gc = GregorianCalendar.from( zdt ) ;