【问题标题】:Serializing Date in JavaJava中的序列化日期
【发布时间】:2008-09-22 12:32:37
【问题描述】:

我正在通过 Web 服务传递一些对象,其中一些包含 java.sql.Date。因为 Date 没有空的构造函数,所以它不想被序列化。

问题的第一部分很简单:在客户和服务之间传递日期的最佳方式是什么?

第二部分有点棘手:一旦我决定如何传递日期,我显然可以声明日期瞬态并制作一些包装类以将日期作为字符串或其他方式传递,但是如何将相同的解决方案尽可能透明地应用于多个类包括日期?

(我有一种预感,DynamicProxy 可能是一个解决方案,但阅读 Sun 网站上的文档并不是很有帮助,所以如果它确实是朝着这个方向发展,我们将不胜感激)

编辑:我问错了问题,抱歉(我和同事之间存在一些误解,实际上是什么问题)。由于反序列化而出现问题。因此,一旦我有 xml 格式的日期,它就会尝试将自己反序列化为 GregorianCalendar。问题的其他部分仍然存在:接收某些东西(长时间戳或 GregorianCalendar)并将其转换为 sql 日期的最佳方式是什么,而不为 10 个不同的类制作 10 个不同的包装器。我正在使用 NetBeans 进行代码和 wsdl 生成。

【问题讨论】:

    标签: java web-services serialization date


    【解决方案1】:

    乔达时间

    Date 类有一个笨拙的 API。更好的实现是Joda-Time

    ISO 8601

    Joda-Time 还允许您将日期转换为 ISO 8601 标准格式 (yyyy-mm-ddTHH:MM:SS.SSS)。在将日期从服务器移动到客户端时使用此标准具有以可读格式包含完整日期的优势。例如,当您使用 JAXB 时,日期的 XML 表示也是这个 ISO 标准。 (参见 XMLGregorianCalendar 类)

    【讨论】:

    • 另请注意,即将推出的适用于 Java 7 的 JSR 310 日期和时间 API 将基于 ISO8601 和 Joda Time 的概念。所以这是一个很好的面向未来的方向。
    • 谢谢!我自己不知道。最后一个更好的 Date 实现。
    • 关于新 API 的好文章:today.java.net/pub/a/today/2008/09/18/…
    【解决方案2】:

    按照之前的建议序列化 Date.getTime() 返回的 long 将起作用。但是,您应该注意,如果您的服务器与客户端位于另一个时区,那么您将在另一端重建的日期将有所不同。如果您想重建完全相同的日期对象,您还需要发送您的时区 (TimeZone.getID()) 并使用它来重建另一边的日期。

    【讨论】:

    • 如果您在巴黎的下午 2 点序列化,如果您在为纽约市时区配置的机器上反序列化相同的流,您将获得上午 8 点。如果您想安排一个会议,那没关系,因为您希望每个人都同时参加。但是,如果您需要显示合同信息(例如:此选项在巴黎下午 2 点到期),那么您需要发送时区,以便纽约市计算机确定它是下午 2 点而不是早上 8 点,顺便说一句,在巴黎。这两种情况都存在商业案例,沿时区发送始终是安全的,除非您有严格的带宽限制。
    【解决方案3】:

    为了回答您问题的第一部分,我建议使用 iso 8601 格式的字符串(这是编码日期的标准)。

    对于第二部分,我不确定您为什么需要代理类?或者为什么你必须扩展日期类来支持这一点。例如。您的网络服务不会知道某个字段是日期并进行从日期到字符串的转换并返回自身吗?我需要更多信息。

    【讨论】:

      【解决方案4】:

      java.sql.Date 扩展 java.util.Date

      只需使用 getTime() 从中获取 long 值。这可以被序列化并在另一端从它构造一个新的 java.sql.Date(long) 或 new java.util.Date(long)。

      【讨论】:

      • 就像 entzik 上面所说的,这会丢失 Date 中包含的时区。
      【解决方案5】:

      我研究了 java.sql.Date 的实现,我认为 java.sql.Date 是可序列化的,是 java.util.Date 的扩展。

      【讨论】:

        【解决方案6】:

        java.sql.Date 最近让我感到困扰的一个警告是,它不只存储日期部分的时间部分(小时、分钟、秒等)。如果你想要完整的时间戳,你必须使用 java.util.Date 或 java.sql.Timestamp

        【讨论】:

          【解决方案7】:

          我将扩展 JeroenWyseur 的 correct answer

          ISO 8601

          ISO 8601 标准格式绝对是序列化日期时间值以进行数据交换的最佳方式。这种格式对不同文化的人们来说是明确的、直观的,并且在世界各地越来越普遍。人类和机器都易于阅读。

          2015-01-16T20:15:43+02:00
          2015-01-16T18:15:43Z
          

          第一个示例的偏移量比 UTC 早两个小时。第二个例子展示了Z(“Zulu”)的常见用法来表示UTC,是+00:00的缩写。

          java.time

          与 Java 捆绑在一起的 java.util.Date 和 .Calendar 类是出了名的麻烦、混乱和缺陷。避开他们。而是使用:

          • java.time 包,内置于 Java 8,灵感来自 JSR 310 定义的 Joda-Time。

          java.time 包取代了它的前身 Joda-Time 库。

          默认情况下,这两个库都使用 ISO 8601 来解析和生成日期时间值的字符串表示形式。

          请注意,java.time 通过附加 proper name of the time zone 扩展了 ISO 8601 格式,例如 2007-12-03T10:15:30+01:00[Europe/Paris]

          在 StackOverflow.com 上搜索数百个问题和答案,其中包含大量讨论和示例代码。

          避免 Count-From-Epoch

          其他一些答案建议使用数字,从epoch 开始计数。这种方法不实用。这不是不言而喻的。它不是人类可读的,使调试变得麻烦且令人沮丧。

          它是哪个数字,Unix 中常用的整秒,java.util.Date 和 Joda-Time 中使用的毫秒,Postgres 等数据库中常用的微秒,或java.time package 中使用的纳秒?

          couple dozen epochs 中的哪一个,1970 年的第一刻在 Unix 中使用,第一年在 .Net 和 Go 中使用,“1900 年 1 月 0 日”在数百万(数十亿?)的 Excel 和 Lotus 电子表格中使用,或 1 月 1 日, 2001 被Cocoa使用?

          有关类似问题的更多讨论,请参见 my answer

          LocalDate

          我正在通过 Web 服务传递一些对象,其中一些包含 java.sql.Date

          可怕的java.sql.Date 类的替代品是java.time.LocalDate

          最好完全避免使用遗留类,但您可以通过调用添加到旧类的新方法来回转换:myJavaSqlDate.toLocalDate()

          序列化LocalDate

          LocalDate 类实现了Serializable。所以你应该没有问题自动序列化,编组和解组。


          关于java.time

          java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

          要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

          Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

          您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

          从哪里获得 java.time 类?

          ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

          【讨论】:

            【解决方案8】:

            您不需要默认构造函数(空)来序列化/反序列化日期(java.sql.Date 或 java.util.Date)。在反序列化期间不调用构造函数,而是将对象的属性直接设置为序列化数据中的值,并且您可以按原样使用对象,因为它已反序列化。

            【讨论】:

              【解决方案9】:

              您可以使用编码器和解码器来序列化和反序列化您的对象。

              这是一个序列化 SWT Rectangle 类的示例:

              XMLEncoder encoder = new XMLEncoder(new FileOutputStream(file));
              encoder.setPersistenceDelegate(
                  Rectangle.class, 
                  new DefaultPersistenceDelegate(new String[]{"x", "y", "width", "height"}));
              encoder.writeObject(groups);
              encoder.close();
              

              【讨论】:

                【解决方案10】:

                首先,如果您使用 Web 服务,这意味着您正在序列化为 XML,而不是常规的 Java 序列化(而是一些其他用于编组和解组的库)。所以这个问题缺少一些信息。

                其次,如果你可以控制你的 InputStream 和 OutputStream 尝试扩展 ObjectOutputStream 和 ObjectInputStream 并覆盖 replaceObject()resolveObject() 然后你可以为 java 实现序列化.sql.日期。

                【讨论】:

                  【解决方案11】:

                  java.sql.Date 已经实现了 Serializable 所以不需要实现它:-)

                  就您的主要问题而言,我非常喜欢 JAXB,因为我几乎可以将任何 XML 转换为对象,因此可能值得您花时间研究一下。

                  【讨论】:

                    【解决方案12】:

                    嗯...想不出任何理由为什么任何序列化的对象实例(通过默认的 java 机制序列化)应该将自身反序列化为另一个类的实例,因为类信息应该是序列化数据的固有部分.

                    因此,这要么是您的(反)序列化框架的问题,要么是框架在“发送端”(日历、java.util.Date 等)接受任何“类似日期”的对象 - 因此是 java.sql。日期也因为它扩展了 java.util.Date),将其“序列化”为某种常见日期格式的字符串(因此类型信息丢失)并将其“反序列化”回接收端的日历对象。

                    所以我认为获取 java.sql.Date 最简单的方法是做一个

                    java.sql.Date date = new java.sql.Date(calendar.getTimeInMillis);

                    您需要 java.sql.Date 但从“反序列化”中获取 GregorianCalendar。

                    【讨论】:

                      猜你喜欢
                      • 2011-12-02
                      • 1970-01-01
                      • 2012-02-13
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多