dst中的一小时差

bq3bfh9z  于 2021-06-26  发布在  Java
关注(0)|答案(2)|浏览(276)

我试图找出白天节光开始时间在美国是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 );
    }
}

日期值如下所示 March 14, 2021 at 3:00 AM 但应该是这样 March 14, 2021 at 2:00 AM . 我不明白一个小时的时差有多大?

eblbsuwk

eblbsuwk1#

我认为(不必要的)时间戳转换是错误的原因:

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));
    }
}

给你(如预期的那样): March 14, 2021 at 2:00 AM 此时此刻,时间已经发生了变化,所以现在确实是凌晨3点。这就是api设计者必须创建方法的原因 getDateTimeBefore() .

kxxlusnw

kxxlusnw2#

检查以下信息https://www.timeanddate.com/time/change/usa/new-york

14 Mar 2021 - Daylight Saving Time Starts
When local standard time is about to reach
Sunday, 14 March 2021, 02:00:00 clocks are turned forward 1 hour to
Sunday, 14 March 2021, 03:00:00 local daylight time instead.

该信息与以下代码的输出匹配:

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

api的日期时间 java.util 以及它们的格式化api, SimpleDateFormat 过时且容易出错。全班同学, java.sql.Timestamp 延伸 java.util.Date 因此它继承了同样的问题。建议完全停止使用它们,并切换到现代日期时间api。
出于任何原因,如果您必须坚持使用Java6或Java7,您可以使用threeten backport,它将大部分java.time功能向后移植到Java6和Java7。
如果您正在为一个android项目工作,并且您的android api级别仍然不符合java-8,请检查通过desugaring提供的java8+api以及如何在android项目中使用threetenabp。
从trail:date-time了解现代日期时间api。

相关问题