我有以下问题使用 乔达时 为分析和制造日期和时间 夏令时间 (DST)的时间。这里是一个例子(请注意,三月30日2008年夏改变在意大利):

DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime x = dtf.parseDateTime("30/03/2008 03:00:00");
int h = x.getHourOfDay();
System.out.println(h);
System.out.println(x.toString("dd/MM/yyyy HH:mm:ss"));
DateTime y = x.toDateMidnight().toDateTime().plusHours(h);
System.out.println(y.getHourOfDay());
System.out.println(y.toString("dd/MM/yyyy HH:mm:ss"));

我得到以下产出:

3
30/03/2008 03:00:00
4
30/03/2008 04:00:00

当我分析小时我小时为3。在我的数据结构保存的天储存午夜的时间,然后我有一些值为每小时的一天(0到23).然后,当我写出来的日期,我重新计算的全日期的时间午夜再加上小时。当我总3小时给我午夜我04:00:00!如果我分析了一遍,我得到4小时!

哪里是我的错吗?是否有某种方式获得2小时,当我分析或者得到三个小时,当我打印出来吗?

我们还试图建立由输出一方面:

String.format("%s %02d:00:00", date.toString("dd/MM/yyyy"), h);

但在这种情况下,于2小时,我产生30/03/2008 02:00:00而不是一个有效日期(因为2小时不存在)而无法分析。

谢谢你提前对你有所帮助。菲利普

有帮助吗?

解决方案

要保存你的数据的数据结构不是很优化与夏令时的日子。你一天这个特殊的日子应该只有23小时。

如果你这样做:

    DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss").withLocale(Locale.US);
    DateTime x = dtf.parseDateTime("30/03/2008 00:00:00");

    DateTimeFormatter parser = DateTimeFormat.fullDateTime();
    System.out.println("Start:"+parser.print(x));

    DateTime y = x.plusHours(4);

    System.out.println("After add of 4:"+parser.print(y));

您得到预期的结果,认为时间是05:00。

我建议你改变你储存你的一天,并使用日期。如果没有,你必须处理夏令储存一天的小时时的时间。

您可能会做这样的事情: 在这里我们将时间向前拨一个小时,因为这种情况下的话,你必须存储4,而不是5的时间5.当你计算的时候,你应该使用plusHours()方法得到的实际时间。我想你可能逃脱这样的:

public class DateTest {
    private static final int HOUR_TO_TEST = 2;

  public static void main(String[] args) {
    DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
    DateTime startOfDay = dtf.parseDateTime("30/03/2008 00:00:00");

    /* Obtained from new DateTime() in code in practice */
    DateTime actualTimeWhenStoring = startOfDay.plusHours(HOUR_TO_TEST);

    int hourOfDay = actualTimeWhenStoring.getHourOfDay();
    int hourOffset = startOfDay.plusHours(hourOfDay).getHourOfDay();

    System.out.println("Hour of day:" + hourOfDay);
    System.out.println("Offset hour:" + hourOffset);

    int timeToSave = hourOfDay;
    if (hourOffset != hourOfDay) {
        timeToSave = (hourOfDay + (hourOfDay - hourOffset));
    }
    System.out.println("Time to save:" + timeToSave);

    /* When obtaining from db: */
    DateTime recalculatedTime = startOfDay.plusHours(timeToSave);

    System.out.println("Hour of time 'read' from db:" + recalculatedTime.getHourOfDay());
  }
}

...或basicly类似的东西。如果你选择走这路线我会为它编写一个测试。你可以改变HOUR_TO_TEST看到它移动通过夏令时。

其他提示

  

当我总结3个小时我的午夜,我得到04:00:00!如果我再次解析它,我得到4小时!哪里是我的错?

您已经提到,这个日期是什么时候的时间而改变。因此,有没有搞错。 2010年3月30日00:00 CEST(在意大利时区)精确地讲2010年3月29日23:00 UTC。当您添加3个小时,你会得到二零一零年三月三十零日02:00 UTC。但是,这是发布的那一刻,我们切换时间(这发生在01:00 UTC),所以当你的时间转换为当地时区你04:00 3月30日。这是正确的行为。

  

有没有一些方法,当我解析或获得每小时3当我打印出来让2小时?

没有,因为2010年3月30日02:00 CEST的不存在。正是在2010年3月30日01:00 UTC我们切换时间从+1小时2小时与UTC,因此2010年3月30日00:59 UTC是在2010年3月30日:01:59 CEST,但2010年3月30日01 :00 UTC成为2010 03:00 CEST 3月30日。否02:XX小时存在于该特定日期

顺便说一句。在一个星期你可以期待另一个“有趣”。你能告诉这指的是什么日期UTC:

2010年10月31日,02:15 CEST?

好了,有趣的是,我们的不知道。它可以是0ctober 31,2010 00:15 UTC(前实际时间开关)或2010年10月31日1点十五UTC(后转)。

这正是为什么你应该始终日期和时间有关存储UTC,并将其显示之前转换为本地时区,否则,你的风险的不确定性。

HTH。

建立在正确的答案通过Paweł Dyda&Knubo...

ISO8601为串的格式

你不应该存储(serialize)一日期时间为一串的格式提及: "30/03/2008 03:00:00".问题:

  • 省略时区。
  • 日、月、年以是模糊的。
  • 应该已经被翻译为UTC时间。

如果你必须serialize一日期时间价值的文字,使用一个可靠的格式。显而易见的选择是的 ISO8601 标准格式。甚至更好的是将当地时间到 UTC(祖鲁) 时区,然后出ISO8601格式。是这样的: 2013-11-01T04:48:53.044Z

没有午夜

midnight 方法在乔达时摒弃赞成乔达时间的方法 withTimeAtStartOfDay() (见 doc).一些天做的 没有一个午夜.

例码在乔达时2.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

例显示23个小时,在一天的DST(夏令时间)在意大利罗马,而一天之后24小时。请注意,时间区(罗马)指定。

    // Time Zone list: http://joda-time.sourceforge.net/timezones.html
    org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
    org.joda.time.DateTime dayOfDstChange = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ) ; // Day when DST
    org.joda.time.DateTime dayAfter = dayOfDstChange.plusDays(1);

    // How many hours in this day? Should be 23 rather than 24 on day of Daylight Saving Time "springing ahead" to lose one hour.
    org.joda.time.Hours hoursObjectForDay = org.joda.time.Hours.hoursBetween(dayOfDstChange.withTimeAtStartOfDay(), dayAfter.withTimeAtStartOfDay());
    System.out.println( "Expect 23 hours, got: " + hoursObjectForDay.getHours() ); // Extract an int from object.

    // What time is 3 hours after midnight on day of DST change?
    org.joda.time.DateTime threeHoursAfterMidnightOnDayOfDst = dayOfDstChange.withTimeAtStartOfDay().plusHours(3);
    System.out.println( "Expect 4 AM (04:00) for threeHoursAfterMidnightOnDayOfDst: " + threeHoursAfterMidnightOnDayOfDst );

    // What time is 3 hours after midnight on day _after_ DST change?
    org.joda.time.DateTime threeHoursAfterMidnightOnDayAfterDst = dayAfter.withTimeAtStartOfDay().plusHours(3);
    System.out.println( "Expect 3 AM (03:00) for threeHoursAfterMidnightOnDayAfterDst: " + threeHoursAfterMidnightOnDayAfterDst );

例储存的日期时通过的第一个翻译来UTC。然后在恢复的日期时对象,调整所需的时区。

    // Serialize DateTime object to text.
    org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
    org.joda.time.DateTime dayOfDstChangeAtThreeHoursAfterMidnight = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ).withTimeAtStartOfDay().plusHours(3);
    System.out.println("dayOfDstChangeAtThreeHoursAfterMidnight: " + dayOfDstChangeAtThreeHoursAfterMidnight);
    // Usually best to first change to UTC (Zulu) time when serializing.
    String dateTimeSerialized = dayOfDstChangeAtThreeHoursAfterMidnight.toDateTime( org.joda.time.DateTimeZone.UTC ).toString();
    System.out.println( "dateTimeBeingSerialized: " + dateTimeSerialized );
    // Restore
    org.joda.time.DateTime restoredDateTime = org.joda.time.DateTime.parse( dateTimeSerialized );
    System.out.println( "restoredDateTime: " + restoredDateTime );
    // Adjust to Rome Italy time zone.
    org.joda.time.DateTime restoredDateTimeAdjustedToRomeItaly = restoredDateTime.toDateTime(romeTimeZone);
    System.out.println( "restoredDateTimeAdjustedToRomeItaly: " + restoredDateTimeAdjustedToRomeItaly );

时运行:

dayOfDstChangeAtThreeHoursAfterMidnight: 2008-03-30T04:00:00.000+02:00
dateTimeBeingSerialized: 2008-03-30T02:00:00.000Z
restoredDateTime: 2008-03-30T02:00:00.000Z
restoredDateTimeAdjustedToRomeItaly: 2008-03-30T04:00:00.000+02:00
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top