Joda Time从MutableDateTime实例中减去24小时,我想知道原因

时间:2010-10-28 17:31:45

标签: java timezone jodatime

我不明白为什么MutableDateTime.setDate()将时间设置为“昨天”(请参阅​​日志时间戳小时 - 它是20:28)。这个时区有关系吗?我需要在格式化程序上设置一些内容吗?

我希望在使用“10/27/2010”调用setDate之后,日期将与解析日期00:00 EDT 10/27/10相同,而不是20:28 EDT 10/26/10 。这是24小时前从“现在”。

我在这里缺少什么,或者我应该如何编辑代码以获得所需的结果?我是Joda Time的新手,想解开这个谜。

DateTimeFormatter dateFormatterJ = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTimeFormatter timestampFormatJ = DateTimeFormat.forPattern("HH:mm zzz MM/dd/yy");

MutableDateTime startDate = new MutableDateTime();

log.info("parsed date " + 
    timestampFormatJ.print(dateFormatterJ.parseMutableDateTime(startDateString)));

startDate.setDate((dateFormatterJ.parseMutableDateTime(startDateString)));

log.info("startDate: " + timestampFormatJ.print(startDate));

在这种情况下,startDateString只是“10/27/2010”。

这是日志输出:

10-27 20:28:55 INFO parsed date: 00:00 EDT 10/27/10
10-27 20:28:55 INFO startDate: 20:28 EDT 10/26/10

由于

2 个答案:

答案 0 :(得分:4)

简单的答案是,因为javadoc这样说。

  

public void setDate(ReadableInstant   瞬间)

     

从另一个设置日期   瞬间。 此对象的时间部分   将不受影响。

     

参数:   即时 - 复制日期的瞬间   从,时间部分忽略

     

抛出:   IllegalArgumentException - 如果是   object is invalidobject无效

当Joda说'Date'时,它意味着Date这个词的人类意义。 “此值的年 - 月 - 日部分”,而不是java.util.Date的逻辑等效项。 (joda的全部意义是在处理日期和时间时引入一些自然,明智,语义。)

编辑: 要回答“如何修复”问题,只需执行以下操作:

MutableDateTime startDate = new MutableDateTime(dateFormatterJ.parseMutableDateTime(startDateString));

或者手动将时间部分归零。

编辑2:嗯,我显然没有仔细阅读,这只是答案的一半。将检查。

编辑3:这太过于让我烦恼,以至于我花了一分钟时间来寻找它。

public void setDate(final ReadableInstant instant) {
    long instantMillis = DateTimeUtils.getInstantMillis(instant);
    Chronology instantChrono = DateTimeUtils.getInstantChronology(instant);
    DateTimeZone zone = instantChrono.getZone();
    if (zone != null) {
        instantMillis = zone.getMillisKeepLocal(**DateTimeZone.UTC**, instantMillis);
    }
    setDate(instantMillis);
}

出于某种原因,在设置日期之前,它将您的绝对时间推进到UTC。所以你给它10/27/2010 00:00 EDT它将绝对时间量设置为代表10/27/2010 00:00 UTC的毫秒数,当然这只是前一天的下午6点或7点。然后它找到该日期的EDT日期值为10/26。

不能说是否有某种意图,或者这是一个已经存在2年或者什么的错误。)

答案 1 :(得分:2)

解析不包含GMT偏移或时区ID的字符串时,您必须执行以下三项操作之一:

  • 不执行任何操作,并接受在默认时区中解析字符串
  • 使用格式化程序
  • 上的withZone()指定要解析的时区
  • 使用parseLocalDate()代替parseMutableDateTime()

最后一个是首选解决方案,因为它正确解析实际输入的数据,这是一个没有时间,偏移或区域的日期。

在测试代码中正确使用parseLocalDate()解析日期。