Java DST中的一小时差

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

我试图找出美国的日间节能开始时间,即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.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及其格式化API
SimpleDataFormat
已经过时,并且容易出错。类
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及其格式化API
SimpleDataFormat
已经过时,并且容易出错。类
java.sql.Timestamp
扩展了
java.util.Date
,因此它继承了相同的问题。建议完全停止使用,并切换到

  • 无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7
  • 如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认
了解现代日期时间API我认为(不必要的)时间戳转换是错误的原因:

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()
造成的。如果您需要转换之前的时间,那么您不应该对这样命名的方法将其提供给您感到非常惊讶。