Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何获得Joda日期之间的正确小时数?_Java_Jodatime_Dst - Fatal编程技术网

Java 如何获得Joda日期之间的正确小时数?

Java 如何获得Joda日期之间的正确小时数?,java,jodatime,dst,Java,Jodatime,Dst,我想得到两次约会之间的所有(DST)时间 这是我的示例代码: public static void main(String[] args) { Date startDate = new Date(); Calendar startCalendar = Calendar.getInstance(); startCalendar.setTime(startDate); startCalendar.set(2014, 2, 1, 0, 0, 0); start

我想得到两次约会之间的所有(DST)时间

这是我的示例代码:

public static void main(String[] args) {

    Date startDate = new Date();
    Calendar startCalendar = Calendar.getInstance();
    startCalendar.setTime(startDate);
    startCalendar.set(2014, 2, 1, 0, 0, 0);
    startCalendar.set(Calendar.MILLISECOND, 0);

    Date endDate = new Date();
    Calendar endCalendar = Calendar.getInstance();
    endCalendar.setTime(endDate);
    endCalendar.set(2014, 2, 31, 0, 0, 0);
    endCalendar.set(Calendar.MILLISECOND, 0);

    DateTime startDateTime = new DateTime(startCalendar);
    DateTime endDateTime = new DateTime(endCalendar).plusDays(1);

    Hours hours = Hours.hoursBetween(startDateTime, endDateTime);

    // actual is 744
    System.out.println("Expected: 743, actual: " + hours.getHours());
}

很明显,我遗漏了一些东西,但我无法发现我的错误。

我也无法解决这个问题(但在Joda时间?),但你可以解决这个问题。毫秒时间差除以3600000L应为准确的小时数。我试过并得到了743。

欢迎来到混乱的日期/时间处理。你的问题是时区。具体来说,无论您处于哪个时区,都会遵守夏令时,并且开关(向前弹簧)会在您的间隔期间发生,从而将其缩短一个小时。请参阅此代码

public class DateTimeTest {
    public static void main(String[] args) {
    DateTime startDateTime = new DateTime()
        .withYear(2014)
        .withMonthOfYear(3)
        .withDayOfMonth(1)
        .withHourOfDay(0)
        .withMinuteOfHour(0)
        .withSecondOfMinute(0)
        .withMillisOfSecond(0)
        .withZone(DateTimeZone.forID("US/Eastern"));

    DateTime endDateTime = new DateTime()
        .withYear(2014)
        .withMonthOfYear(3)
        .withDayOfMonth(31)
        .withHourOfDay(0)
        .withMinuteOfHour(0)
        .withSecondOfMinute(0)
        .withMillisOfSecond(0)
        .withZone(DateTimeZone.forID("US/Eastern"))
        .plusDays(1);

    System.out.println("Expected 744, got: " 
        + Hours.hoursBetween(startDateTime, endDateTime).getHours());  // 743

    DateTime startUtc = startDateTime.withZoneRetainFields(DateTimeZone.UTC);
    DateTime endUtc = endDateTime.withZoneRetainFields(DateTimeZone.UTC);

    System.out.println("Expected 744, got: " 
        + Hours.hoursBetween(startUtc, endUtc).getHours());  // 744
    }
}

主要问题是无法指定时区

当我在西雅图运行你的代码时,我在2014年3月得到了743小时。为什么?因为我的默认时区。在美国西海岸,2014年3月9日星期日02:00开始。请参阅此页。因此,第9天实际上是23小时,而不是24小时

但如果冰岛有人运行完全相同的代码,她将得到
744
。为什么?因为冰岛人太聪明了,不会为夏令时的胡说八道而烦恼

另外,作为一个好习惯,当你尝试在几天内工作时,你应该调用Joda Time方法。以前我们使用Joda Time的
midnight
方法,但由于某些日历中的某些日期,这些方法已被弃用

提示:请注意以
标准
命名的Joda时间方法,该文件解释为假设24小时工作日。换句话说,这些方法忽略了夏令时转换

下面是一些在Java7中使用JodaTime2.3的示例代码

// © 2013 Basil Bourque. This source code may be used freely forevery by anyone taking full responsibility for doing so.

// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/

// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310

// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601

// Time Zone list: http://joda-time.sourceforge.net/timezones.html
org.joda.time.DateTimeZone seattleTimeZone = org.joda.time.DateTimeZone.forID("America/Los_Angeles");
org.joda.time.DateTimeZone icelandTimeZone = org.joda.time.DateTimeZone.forID("Atlantic/Reykjavik");

// Switch between using 'seattleTimeZone' and 'icelandTimeZone' to see different results (23 vs 24).
org.joda.time.DateTime theNinth = new org.joda.time.DateTime( 2014, 3, 9, 0, 0, seattleTimeZone ) ; // Day when DST begins.
org.joda.time.DateTime theTenth = theNinth.plusDays( 1 ); // Day after DST begins.

// Using "hoursBetween()" method with a pair of DateTimes.
org.joda.time.Hours hoursObject = org.joda.time.Hours.hoursBetween( theNinth.withTimeAtStartOfDay(), theTenth.withTimeAtStartOfDay() );
int hoursInt = hoursObject.getHours();
System.out.println( "Expected 23 from hoursInt, got: " + hoursInt );

// Using an Interval.
org.joda.time.Interval interval = new Interval( theNinth.withTimeAtStartOfDay(), theTenth.withTimeAtStartOfDay() );
System.out.println( "Expected 23 from interval, got: " + org.joda.time.Hours.hoursIn(interval).getHours() );

// Using a Period with Standard days.
org.joda.time.Period period = new org.joda.time.Period( theNinth.withTimeAtStartOfDay(), theTenth.withTimeAtStartOfDay() );
org.joda.time.Hours standardHoursObject = period.toStandardHours();
System.out.println( "Expected 24 from standardHoursObject, got: " + standardHoursObject.getHours() );

使用并添加1天=24小时,我得到744。我不认为743点是正确的答案,因为2014年3月9日(在许多地方)只有23个小时。toDateMidnight不受欢迎。是否有替换项?我只是使用它作为将分钟、秒和毫秒设置为0的快捷方式,以保持代码简短。我根据joda Time1.6.2编写了这个代码,现在已经很旧了。我不知道他们不赞成。我也无法复制你的结果。它总是返回744。我正在使用Joda-Time-2.3测试更新。第一对现在使用观察DST的时区,第二对则不使用。更有可能的是,您已经在时钟设置不同的两台不同的机器上运行了此功能。时区会让你为这样的事情发疯。通常最好是正确地控制它们。这是类型设置方式的产物。Per
DateTime.withZone()
:“返回此日期时间的另一个时区副本,保留毫秒瞬间。”。。。。换句话说(正如你已经注意到的),当你的当前时区不是“目的地”时区时,你会得到不同的“本地”时间。此示例需要使用
DateTime.withZoneRetainFields()
(这将保留目标区域的本地时间,但并非在所有情况下都是安全的),或者以更安全的时区方式设置(如在构造函数中指定时区和本地时间)。夏时制在美国从该月开始。所以你损失了一个小时。(744-1)=743明确指定时区并使用
.withTimeAtStartOfDay()
产生正确的结果