java 转换 from/to asn1 dateTimes
java conversion from/to asn1 dateTimes
在我的框架中,我需要转换 to/from 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()));
}
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);
避免使用过时的日期和时间类
我建议您避免使用过时的 类 Date
、SimpleDateFormat
和 TimeZone
。您已经在使用 OFfsetDateTime
的现代 Java 日期和时间 API 更易于使用。特别是混合两个 APIs,虽然可能,但势必会产生混乱的代码。
例如,如果最后您需要一个老式的 Date
对象作为遗留 API,请仅在最后一刻从 Instant
转换为 Date
以最小化你对旧 API.
的使用
格式模式字符串中的错误
您的格式模式字符串中有两个错误:
- 您不能使用大写
YY
。这适用于基于周的年份,仅对周数有用。使用小写 yy
或 uu
,并注意两位数的年份将被解释为 2000 到 2099 的范围。
- 格式模式字母
Z
与区域偏移量 Z
不匹配。请在您的格式模式中使用 X
。
在我的框架中,我需要转换 to/from 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()));
}
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);
避免使用过时的日期和时间类
我建议您避免使用过时的 类 Date
、SimpleDateFormat
和 TimeZone
。您已经在使用 OFfsetDateTime
的现代 Java 日期和时间 API 更易于使用。特别是混合两个 APIs,虽然可能,但势必会产生混乱的代码。
例如,如果最后您需要一个老式的 Date
对象作为遗留 API,请仅在最后一刻从 Instant
转换为 Date
以最小化你对旧 API.
格式模式字符串中的错误
您的格式模式字符串中有两个错误:
- 您不能使用大写
YY
。这适用于基于周的年份,仅对周数有用。使用小写yy
或uu
,并注意两位数的年份将被解释为 2000 到 2099 的范围。 - 格式模式字母
Z
与区域偏移量Z
不匹配。请在您的格式模式中使用X
。