【问题标题】:Java Time Zone When Parsing DateFormat解析 DateFormat 时的 Java 时区
【发布时间】:2010-12-27 23:44:00
【问题描述】:

我有如下解析日期的代码:

String ALT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
SimpleDateFormat sdf = new SimpleDateFormat(
                    ALT_DATE_TIME_FORMAT);
Date date = sdf.parse(requiredTimeStamp);

它工作正常,突然间,它停止工作了。事实证明,管理员在服务器上进行了一些配置更改,并且日期当前返回为“2010-12-27T10:50:44.000-08:00”,上述模式无法解析。我有两个问题:

第一个是什么模式会解析 JVM 以上述格式返回的日期(具体来说,只是 '-08:00' 作为时区)?其次,究竟应该在哪里更改 linux RHEL 5 服务器上的此类设置,以便我们在未来了解此类更改?

【问题讨论】:

    标签: java datetime timezone date-format iso8601


    【解决方案1】:

    tl;博士

    OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" )
    

    ISO 8601

    输入字符串格式在ISO 8601 标准中定义,这是一系列日期时间格式。

    避免使用旧的日期时间类

    问题和其他答案使用与最早版本的 Java 捆绑在一起的旧的过时日期时间类。避开他们。现在被 java.time 类所取代。

    使用 java.time

    您的输入字符串以offset-from-UTC 结尾。所以我们解析为OffsetDateTime 对象。

    java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要指定格式模式。

    OffsetDateTime odt = OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" );
    

    如果您想将此日期时间值视为时间轴上的时刻(UTC 时间),请提取 Instant

    Instant instant = odt.toInstant();
    

    时区是一个偏移量加上一组用于处理异常情况的规则,例如夏令时 (DST)。如果您有一个时区,请应用 ZoneId 以获取 ZonedDateTime 对象。时间线上的同一时刻,但通过不同的wall-clock time 查看。

    ZoneId z = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = odt.atZoneSameInstant( z );  // Same moment on the timeline, but viewed through a different wall-clock time.
    


    关于java.time

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

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

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

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

    从哪里获得 java.time 类?

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

    【讨论】:

      【解决方案2】:

      另一个应用程序使用 ISO 8601 日期时间格式。我假设另一个应用程序正在向您发送一个符合 XML Schema 的 dateTime 类型(即 ISO 8601)的 XML 响应。现在,众所周知,DateFormat 无法解析这种格式。您要么必须使用其他库,如 joda-time(joda-time 是赢家)或其他响应中指定的 FastDateFormat。看这个帖子Converting ISO 8601-compliant String to java.util.Date

      【讨论】:

      • Joda-Time 库工作,但现在处于维护模式。团队建议迁移到 java.time 类。
      【解决方案3】:

      如果仍在寻找答案,这对我有用

      我的输入:2020-12-08T10:36:53.939+05:30
      我的输出:Tue Dec 08 10:36:53 IST 2020

      您可以将此日期转换为您需要的任何格式!

      private static Date convertDate(String input) {
          Date newDate = null;
          try {
              DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
              newDate=dateFormat.parse(input);  
          } catch (Exception e) {
              e.printStackTrace();
          }
          return newDate;
      }
      

      【讨论】:

        【解决方案4】:

        如果你想使用直接的 JDK 解析它,我相信它应该可以使用 JAXB 工具来解析,请参阅DatatypeFactory.newXMLGregorianCalendarDatatypeConverter.parseDateTime

        【讨论】:

          【解决方案5】:

          使用JodaTime

          作为@Pangea 建议使用 JodaTime 的更具体示例,您可以使用以下内容:

          String timestamp = "2012-09-17T04:11:46Z";
          
          DateTime date = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);
          

          这可以正确识别 UTC 时区。我还没有在字符串时间戳中尝试过毫秒,但我相信它也能正常工作。

          希望对其他人有所帮助。

          日本

          【讨论】:

          【解决方案6】:

          问题应该是requiredTimeStamp 的来源和格式。它是由用户输入的,还是从另一个程序中读取的?哪个组件在字符串表示中创建日期?

          格式“2010-12-27T10:50:44.000-08:00”看起来像标准格式ISO-8601 它应该可以用yyyy-MM-dd'T'HH:mm:ss.SSSZ模式解析

          不确定哪些设置会对此产生影响,但有一个Oracle FAQ about Java TimeZones。 它可能是user.timezone 系统属性或RHEL 中的/etc/localtime 符号链接。

          【讨论】:

          • 对不起,我不清楚。 requiredTimeStamp 由服务器(不是我们的)上的 java 应用程序生成,并作为服务响应的一部分发送。它似乎使用了一些默认的服务器设置,因为它随着服务器重新配置而改变。即使在我机器上的独立单元测试中,模式中的 Z 也无法解析时间戳“-08:00”,Z 可以解析“-0800”或“GMT-08:00”但不能解析“-08:00” '。
          【解决方案7】:

          SimpleDateFormat 仅接受 -0800GMT-08:00 作为时区。

          似乎无法使用SimpleDateFormat 解析 ISO 8601 格式。也许你应该看看Apache Commons LangFastDateFormat。它与SimpleDateFormat 兼容,但接受ZZ 时区模式,该模式应该解析您需要的时区格式。 DateFormatUtils 包含一些看起来像您需要的模式的示例常量,只是没有毫秒(例如 ISO_DATETIME_TIME_ZONE_FORMAT)。

          【讨论】:

          • 据我所知,FastDateFormat 不支持解析。
          • 看来你是对的。由于它实现了标准的 Format 接口,我假设它也会像 SimpleDateFormat 一样解析格式。我没有检查 cmets 的解析方法。
          【解决方案8】:

          尝试将其更改为小写 z。

          z 处理大多数常见的通用时区语法,而 Z 使用更严格的 4 位 RFC 822 时区。

          虽然它记录了两者都应该解析“常规时区设置”,但它可能会对您的情况产生影响。

          【讨论】:

            【解决方案9】:

            两种解决方案:

            • OffsetDateTime(Java 8 内置)
            • joda(所有强大的日期 - 第三方图书馆)

            OffsetDateTime 在这里显然是一个更好的选择,但如果 joda 已经被证明在很长一段时间内非常强大,并且如果有人更喜欢使用它,那么下面的代码有两个示例

            两种方法的代码示例如下:

            public class Demo {
            public static void jodaTimeStuff(String dateString, DateTimeZone dtz) {
                System.out.println(StringUtils.leftPad(dateString, 29, " ") + "\t------->\t" + ISODateTimeFormat.dateTime().parseDateTime(dateString).toDateTime(dtz));
                System.out.println(StringUtils.leftPad(dateString, 29, " ") + "\t------->\t" + OffsetDateTime.parse(dateString).toZonedDateTime());
            }
            public static void main(String[] args) throws Exception {
                jodaTimeStuff("2010-03-01T08:00:00.000Z", DateTimeZone.UTC);
                jodaTimeStuff("2010-03-01T08:00:00.000Z", DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Kolkata")));
                jodaTimeStuff("2010-03-01T00:00:00.000-08:00", DateTimeZone.UTC);
                jodaTimeStuff("2010-03-01T00:00:00.000-08:00", DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Kolkata")));
                jodaTimeStuff("2010-03-01T00:00:00.000+05:30", DateTimeZone.UTC);
                jodaTimeStuff("2010-03-01T00:00:00.000+05:30", DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Kolkata")));
                jodaTimeStuff("2021-11-15T02:27:24.540288Z", DateTimeZone.UTC);
                jodaTimeStuff("2021-11-15T02:27:24.540288Z", DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Kolkata")));
            }
            

            }

            输出:

                 2010-03-01T08:00:00.000Z   ------->    2010-03-01T08:00:00.000Z
                 2010-03-01T08:00:00.000Z   ------->    2010-03-01T08:00Z
                 2010-03-01T08:00:00.000Z   ------->    2010-03-01T13:30:00.000+05:30
                 2010-03-01T08:00:00.000Z   ------->    2010-03-01T08:00Z
            2010-03-01T00:00:00.000-08:00   ------->    2010-03-01T08:00:00.000Z
            2010-03-01T00:00:00.000-08:00   ------->    2010-03-01T00:00-08:00
            2010-03-01T00:00:00.000-08:00   ------->    2010-03-01T13:30:00.000+05:30
            2010-03-01T00:00:00.000-08:00   ------->    2010-03-01T00:00-08:00
            2010-03-01T00:00:00.000+05:30   ------->    2010-02-28T18:30:00.000Z
            2010-03-01T00:00:00.000+05:30   ------->    2010-03-01T00:00+05:30
            2010-03-01T00:00:00.000+05:30   ------->    2010-03-01T00:00:00.000+05:30
            2010-03-01T00:00:00.000+05:30   ------->    2010-03-01T00:00+05:30
              2021-11-15T02:27:24.540288Z   ------->    2021-11-15T02:27:24.540Z
              2021-11-15T02:27:24.540288Z   ------->    2021-11-15T02:27:24.540288Z
              2021-11-15T02:27:24.540288Z   ------->    2021-11-15T07:57:24.540+05:30
              2021-11-15T02:27:24.540288Z   ------->    2021-11-15T02:27:24.540288Z

            示例代码中使用的一些依赖项(一个仅用于格式化,另一个用于 joda:

                <dependency>
                    <groupId>joda-time</groupId>
                    <artifactId>joda-time</artifactId>
                    <version>2.10.13</version>
                </dependency>
            
                <dependency>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                    <version>3.8</version>
                </dependency>
            

            Dua me yaad rakhna(请在祈祷中记住我)??

            【讨论】:

              猜你喜欢
              • 2011-11-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-03-15
              • 1970-01-01
              • 1970-01-01
              • 2014-06-08
              • 2011-12-18
              相关资源
              最近更新 更多