代码之家  ›  专栏  ›  技术社区  ›  Konrad Garus

Joda LocalDate-还有时间吗?

  •  5
  • Konrad Garus  · 技术社区  · 14 年前

    我在找一个合适的可序列化的仅日期类。在中央时区有一个服务器,我希望东部的用户输入日期为2010-11-23,太平洋的用户将其视为2010-11-23(反之亦然)。

    java.util.Date 是一个时间敏感的瞬间,所以对我不起作用。由于不想重新发明轮子,我决定给乔达一次机会。根据概述, LocalDate 是“表示没有时间(没有时区)的本地日期的类”-正是我需要的。

    不幸的是,它似乎并不独立于时区。数据库里有2010-11-23。在服务器上,我将其转换为 本地日期 具有 new LocalDate(java.sql.Date) . date.toString() 打印2010-11-23。

    在客户端反序列化之后, date.ToString() 打印2010-11-22和 date.getDayOfMonth() 22岁。但是 date.toDateTimeAtStartOfDay() 生产日期:2010-11-23T00:00:00.000-08:00。

    我做错什么了吗?Joda中是否有一个只对日期不敏感的时区类?

    编辑 :在数据库中,我正在使用不区分时区的列( DATE 在博士后)服务器与数据库位于同一时区,因此它读取的日期正好这不是问题。 我正在寻找一个Java类型,它一旦在一个时区中实例化,在所有时区中都具有相同的civil(部分)日期值。

    编辑2 :在服务器上,所有内容都已正确加载并具有UTC时区。经过调查我认为这是个漏洞 ISOChronology . 客户方将其开箱为美国/洛杉矶。原因是序列化是通过以下方式完成的:

    class ISOChronology {
    // ...
        private Object writeReplace() {
            return new Stub(getZone());
        }
    
        private static final class Stub implements Serializable {
            private static final long serialVersionUID = -6212696554273812441L;
    
            private transient DateTimeZone iZone;
    
            Stub(DateTimeZone zone) {
                iZone = zone;
            }
    
            private Object readResolve() {
                return ISOChronology.getInstance(iZone);
            }
    
            private void writeObject(ObjectOutputStream out) throws IOException {
                out.writeObject(iZone);
            }
    
            private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
                iZone = (DateTimeZone)in.readObject();
            }
        }
    }
    

    祝你好运,用一个瞬变场连载。

    3 回复  |  直到 14 年前
        1
  •  3
  •   JodaStephen    14 年前

    这个 trasient 上面显示的存根类中的时区是一个错误。令人惊讶的是,它没有被发现在数以万计的测试或5年的广泛使用。缺陷报告 https://sourceforge.net/tracker/index.php?func=detail&aid=3117678&group_id=97367&atid=617889

    时区应该是UTC,如Javadoc中所定义- http://joda-time.sourceforge.net/apidocs/org/joda/time/LocalDate.html . 反序列化以获取任何其他时区将破坏类的内部状态。

    JSR-310使用了一个更好的内部设计,它不存在这种问题。

        2
  •  1
  •   Neeme Praks Tim Pote    14 年前

    我怀疑使用 new LocalDate(java.sql.Date) 构造器可能是罪魁祸首。

    相反,尝试使用 new LocalDate(int year, int month, int dayOfMonth) .

    LocalDate JavaDoc manual 更多细节。

        3
  •  1
  •   Donal Fellows    14 年前

    你得检查一下是什么 事实上 在你的数据库里。如果它真的是使用绝对时间戳并且它们都在一个时区中,那么您可以解析 那个 时区,然后才转换为本地日期。如果您的数据库中有一个字符串,那么解析该字符串并使用LocalDate的构造函数来获取您真正拥有的信息。不管你做什么,不要在瞬间和时间之间混合,正如你从你的问题中发现的那样,它们是不可互换的。