【问题标题】:java conversion from/to asn1 dateTimes从/到 asn1 dateTimes 的 java 转换
【发布时间】:2017-09-26 06:16:08
【问题描述】:

在我的框架中,我需要在 Java 日期和 ASN1 UTC 时间(通用时间)之间进行转换。我试过 SimpleDateFormat 和 OffsetDateTime。有没有一种明确简单的方法来获得两个方向? asn1 中的字节是字符字节。例如下面,但是我需要以字节为单位的“YYMMDDhhmmssZ”。

解码测试通过,由于与第一个答案的变化,如下:

@Test
public void testUTCTimeDecode() throws IOException {
    byte[] bytes = new byte[] {48, 55, 48, 51, 50, 50, 49, 53, 53, 56, 49, 55, 90};
    ByteArrayInputStream derStream = new ByteArrayInputStream(bytes);

    Date testDate = new Date(OffsetDateTime.parse("2007-03-22T15:58:17+00:00").toEpochSecond() * 1000);

    byte[] decodeBytes = new byte[bytes.length];
    derStream.read(decodeBytes);

    OffsetDateTime actual = OffsetDateTime.parse(
            new String(decodeBytes),
            DateTimeFormatter.ofPattern("uuMMddHHmmssX"));

    Date date = Date.from(actual.toInstant());
    assertTrue(date.equals(testDate));
}

我仍然遇到编码问题。下面是抛出的异常和测试方法:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
at java.time.Instant.getLong(Instant.java:603)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2540)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720)
at club.callistohouse.asn1.ASN1TestModel.testUTCTimeEncode(ASN1TestModel.java:47)

这是我正在使用的测试方法,现已修复。

    @Test
public void testUTCTimeEncode() throws IOException {
    byte[] bytes = new byte[] {48, 55, 48, 51, 50, 50, 49, 53, 53, 56, 49, 55, 90};
    ByteArrayOutputStream derStream = new ByteArrayOutputStream();

    Date testDate = new Date(OffsetDateTime.parse("2007-03-22T15:58:17+00:00").toEpochSecond() * 1000);

    Instant instant = Instant.ofEpochMilli(testDate.getTime());
    DateTimeFormatter utcFormatter = DateTimeFormatter
               .ofPattern ( "uuMMddHHmmssX" ) 
               .withLocale( Locale.US )
               .withZone( ZoneId.of("UTC"));
    String formattedDate = utcFormatter.format(instant);
    derStream.write(formattedDate.getBytes());
    assertTrue(Arrays.equals(bytes, derStream.toByteArray()));
}

【问题讨论】:

  • 如果不知道您的 ASN1InputStreamASN1OutputStream 课程,就很难分辨。您可以生成Minimal, Complete, and Verifiable example 吗?
  • 由于您可以使用OffsetDateTime,我建议您使用没有过时类DateSimpleDateFormatTimeZone 的解决方案。
  • 我修复了一个演员表问题,尽管解析格式的解码仍然失败。除了 testUTCTime 之外,我还启用了 testGeneralizedTime。
  • 欢迎来到 Stack Overflow。如果您可以提供一个最小的、完整的和可验证的示例,包括精确的预期和观察到的输出,我们可能会帮助您,并且很乐意帮助您。
  • 我编辑了 OP,感谢您帮助我解决了一个更好的问题,希望如此。

标签: java utc


【解决方案1】:

TL;DR

    OffsetDateTime expected = OffsetDateTime.of(2007, 3, 22, 15, 58, 17, 0, ZoneOffset.UTC);
    DateTimeFormatter asn1Formatter = DateTimeFormatter.ofPattern("uuMMddHHmmssX");
    OffsetDateTime actual = OffsetDateTime.parse(dateString, asn1Formatter);
    assertEquals(expected, actual);

避免过时的日期和时间类

我建议您避免使用过时的课程DateSimpleDateFormatTimeZone。现代 Java 日期和时间 API,您已经在使用 OFfsetDateTime,使用起来要好得多。尤其是混合这两个 API,尽管可能,但必然会产生令人困惑的代码。

例如,如果您最终需要一个老式的 Date 对象用于旧版 API,请仅在最后一刻从 Instant 转换为 Date,以尽量减少对旧版 API 的使用。

你格式化模式字符串的错误

您的格式模式字符串中有两个错误:

  1. 您不能使用大写的YY。这适用于基于周的年份,仅对周数有用。使用小写 yyuu,并注意两位数的年份将被解释为 2000 到 2099 的范围内。
  2. 格式模式字母Z 与区域偏移Z 不匹配。请在您的格式模式中改用 X

【讨论】:

  • 我能够让它用于解码,但我仍然遇到编码问题。测试方法和新异常被编辑到原始问题中。我现在遇到一个异常:java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
  • 我在这里找到了答案:stackoverflow.com/questions/40211892/…
  • 有没有办法覆盖世纪选择策略?在这种情况下,简单地使用当前世纪是不正确的;如果年份 % 100 在某个范围内,则应为 21 世纪,否则应为 20 世纪。
  • @erickson 世纪选择的控制方法见Meno Hochschild’s answer here
  • @OleV.V.该 API 文档有点复杂,但听起来很有潜力。谢谢!
猜你喜欢
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 2016-06-29
  • 2020-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多