Java DST中的一小时差
我试图找出美国的日间节能开始时间,即2021年3月14日凌晨2:00,但我的代码返回2021年3月14日凌晨3:00。我无法理解这一小时的时差。我的代码如下:Java DST中的一小时差,java,time,dst,Java,Time,Dst,我试图找出美国的日间节能开始时间,即2021年3月14日凌晨2:00,但我的代码返回2021年3月14日凌晨3:00。我无法理解这一小时的时差。我的代码如下: import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
class DST{
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("America/New_York");
ZoneRules rules = zoneId.getRules();
ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
Timestamp ts = Timestamp.valueOf(nextTransition.getInstant().atZone(zoneId).toLocalDateTime());
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
String date = sdf.format(ts);
system.out.println("DST time:"+ date );
}
}
日期值为2021年3月14日凌晨3:00,但应为2021年3月14日凌晨2:00。我无法理解一小时时差的差异?请从以下位置查看以下信息: 该信息与以下代码的输出相匹配:
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
import java.util.Date;
public class Main {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("America/New_York");
ZoneRules rules = zoneId.getRules();
ZonedDateTime zdt = ZonedDateTime.now(zoneId);
ZoneOffsetTransition nextTransition = rules.nextTransition(zdt.toInstant());
ZonedDateTime zdtAfterTransition = nextTransition.getInstant().atZone(zoneId);
ZonedDateTime zdtBeforeTransition = nextTransition.getInstant().minus(1, ChronoUnit.DAYS).atZone(zoneId);
System.out.println(zdtBeforeTransition);
System.out.println(zdtAfterTransition);
LocalDateTime ldtBeforeTransition = nextTransition.getDateTimeBefore();
System.out.println(ldtBeforeTransition);
// Convert LocalDateTime to java.sql.Timestamp
Timestamp ts = new Timestamp(Date.from(ldtBeforeTransition.toInstant(ZoneOffset.UTC)).getTime());
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
String date = sdf.format(ts);
System.out.println("DST time:" + date);
}
}
输出:
2021-03-13T02:00-05:00[America/New_York]
2021-03-14T03:00-04:00[America/New_York]
2021-03-14T02:00
DST time:March 14, 2021 at 2:00 am
java.util
的日期时间API及其格式化APISimpleDataFormat
已经过时,并且容易出错。类java.sql.Timestamp
扩展了java.util.Date
,因此它继承了相同的问题。建议完全停止使用,并切换到
- 无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7
- 如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认
从了解现代日期时间API检查以下信息 该信息与以下代码的输出相匹配:
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
import java.util.Date;
public class Main {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("America/New_York");
ZoneRules rules = zoneId.getRules();
ZonedDateTime zdt = ZonedDateTime.now(zoneId);
ZoneOffsetTransition nextTransition = rules.nextTransition(zdt.toInstant());
ZonedDateTime zdtAfterTransition = nextTransition.getInstant().atZone(zoneId);
ZonedDateTime zdtBeforeTransition = nextTransition.getInstant().minus(1, ChronoUnit.DAYS).atZone(zoneId);
System.out.println(zdtBeforeTransition);
System.out.println(zdtAfterTransition);
LocalDateTime ldtBeforeTransition = nextTransition.getDateTimeBefore();
System.out.println(ldtBeforeTransition);
// Convert LocalDateTime to java.sql.Timestamp
Timestamp ts = new Timestamp(Date.from(ldtBeforeTransition.toInstant(ZoneOffset.UTC)).getTime());
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
String date = sdf.format(ts);
System.out.println("DST time:" + date);
}
}
输出:
2021-03-13T02:00-05:00[America/New_York]
2021-03-14T03:00-04:00[America/New_York]
2021-03-14T02:00
DST time:March 14, 2021 at 2:00 am
java.util
的日期时间API及其格式化APISimpleDataFormat
已经过时,并且容易出错。类java.sql.Timestamp
扩展了java.util.Date
,因此它继承了相同的问题。建议完全停止使用,并切换到
- 无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7
- 如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
public class DST {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("America/New_York");
ZoneRules rules = zoneId.getRules();
ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("MMMM d, yyyy 'at' h:mm a");
System.out.println("DST time:" + nextTransition.getDateTimeBefore().format(sdf));
}
}
给您(如预期的那样):
2021年3月14日凌晨2:00
此时此刻,时间已经发生了变化,所以现在确实是凌晨3点。这就是为什么API设计人员必须创建方法getDateTimeBefore()
我认为(不必要的)时间戳转换是错误的原因:
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneRules;
public class DST {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("America/New_York");
ZoneRules rules = zoneId.getRules();
ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("MMMM d, yyyy 'at' h:mm a");
System.out.println("DST time:" + nextTransition.getDateTimeBefore().format(sdf));
}
}
给您(如预期的那样):
2021年3月14日凌晨2:00
此时此刻,时间已经发生了变化,所以现在确实是凌晨3点。这就是为什么API设计人员必须创建方法
getDateTimeBefore()
不确定,但是您是否尝试过打印getInstant()返回的ZoneDateTime
。atZone(zoneId)
而不是将其转换为LocalDateTime
?@Hulk:it返回2021-03-14T03-04:00[美国/纽约]
为什么要将旧的日期和时间API与java.time
包中提供的新API混合使用?但是,当转换发生在凌晨2点时,这意味着时钟将向前拨到3点,因此此时是凌晨3点。您得到的结果是正确的。不确定,但您是否尝试过打印getInstant().atZone(zoneId)
返回的zoneDateTime
,而不是将其转换为LocalDateTime
?@Hulk:it返回2021-03-14T03:00-04:00[美国/纽约]
为什么要将旧的日期和时间API与java.time
包中提供的新API混合使用?但是,当转换发生在凌晨2点时,这意味着时钟将向前拨到3点,因此此时是凌晨3点。您得到了正确的结果。谢谢@Benoit,问题是我使用的是nextTransition.getInstant().atZone(zoneId).toLocalDateTime()
,但您使用的是nextTransition.getDateTimeBefore()
不确定两者的区别吗?你知道吗?nextTransition.getDateTimeBefore()
给出了LocalDateTime
,而不是zoneDateTime
@SumitSood问题来自于TimeStamp
和SimpleDateFormat
类的使用,而不是nextTransition.getInstant()
@SumitSood好的,我明白了。在这个时刻,时间已经发生了变化,所以现在确实是凌晨3点。这就是API设计人员必须创建此方法的原因。getDateTimeBefore()
。这当然是getDateTimeBefore()
造成的。如果您想要转换之前的时间,那么您不应该对这样命名的方法将其提供给您感到惊讶。感谢@Benoit,问题是我使用的是nextTransition.getInstant().atZone(zoneId).toLocalDateTime()
,但您使用的是nextTransition.getDateTimeBefore()
不确定两者之间的区别?你知道吗?nextTransition.getDateTimeBefore()
给出了LocalDateTime
,而不是zoneDateTime
@SumitSood问题来自于TimeStamp
和SimpleDateFormat
类的使用,而不是nextTransition.getInstant()
@SumitSood好的,我明白了。在这个时刻,时间已经发生了变化,所以现在确实是凌晨3点。这就是API设计人员必须创建此方法的原因。getDateTimeBefore()
。这当然是getDateTimeBefore()
造成的。如果您需要转换之前的时间,那么您不应该对这样命名的方法将其提供给您感到非常惊讶。