我正在使用现代 Java 日期和时间 API java.time 提供现代答案。
十六进制字符串由以下字段组成:
Field Octets Contents Range
------------------------------------------------------
1 1-2 year 0..65536
2 3 month 1..12
3 4 day 1..31
4 5 hour 0..23
5 6 minutes 0..59
6 7 seconds (use 60 for leap-second) 0..60
7 8 deci-seconds 0..9
8 9 direction from UTC '+' / '-'
9 10 hours from UTC 0..13
10 11 minutes from UTC 0..59
我在一个重复的问题中写了这个答案,其中示例 SNMP 事件时间字符串是07e4070e04032b
. 所以我假设一个十六进制字符串,字节之间没有空格。从 Robert Koch 的回答和从那个重复的问题看来,并非所有 11 个字节都需要存在(示例字符串的长度为 7 个字节)。所以我的转换考虑了长度 6、7、8、10 和 11。
public static Temporal decodeSnmpEventTime(String snmpEventTimeString) {
if (snmpEventTimeString.length() % 2 != 0) {
throw new IllegalArgumentException("Not a valid byte string, must have even length");
}
if (snmpEventTimeString.startsWith("00")
|| snmpEventTimeString.charAt(0) > '7') {
throw new IllegalArgumentException(
"This simple implementation cannot handle years before year 256 nor after 32767;"
+ " we need a different conversion to bytes");
}
byte[] bytes = new BigInteger(snmpEventTimeString, 16).toByteArray();
int year = (bytes[0] & 0xFF) * 0x100 + (bytes[1] & 0xFF);
int month = bytes[2] & 0xFF;
checkRange(month, 1, 12);
int dayOfMonth = bytes[3] & 0xFF;
checkRange(dayOfMonth, 1, 31);
int hour = bytes[4] & 0xFF;
checkRange(hour, 0, 23);
int minute = bytes[5] & 0xFF;
checkRange(minute, 0, 59);
int second = 0;
int deciseconds = 0;
if (bytes.length >= 7) {
second = bytes[6] & 0xFF;
checkRange(second, 0, 60); // 60 will cause conversion to fail, though
if (bytes.length >= 8) {
deciseconds = bytes[7] & 0xFF;
checkRange(deciseconds, 0, 9);
}
}
LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth,
hour, minute, second, deciseconds * 100_000_000);
if (bytes.length >= 9) { // there’s an offset
char offsetSign = (char) (bytes[8] & 0xFF);
int offsetHours = bytes[9] & 0xFF;
checkRange(offsetHours, 0, 13); // allow 14 for all modern offsets
int offsetMinutes = 0;
if (bytes.length >= 11) {
offsetMinutes = bytes[10] & 0xFF;
checkRange(offsetMinutes, 0, 59);
}
ZoneOffset offset;
if (offsetSign == '+') {
offset = ZoneOffset.ofHoursMinutes(offsetHours, offsetMinutes);
} else if (offsetSign == '-') {
offset = ZoneOffset.ofHoursMinutes(-offsetHours, -offsetMinutes);
} else {
throw new IllegalArgumentException("Offset sign must be + or -, was " + offsetSign);
}
return ldt.atOffset(offset);
} else {
return ldt;
}
}
private static void checkRange(int value, int min, int max) {
if (value < min || value > max) {
throw new IllegalArgumentException("Value " + value + " out of range " + min + ".." + max);
}
}
让我们试一试:
String snmpEventTimeString = "07e4070e04032b";
Temporal dateTime = decodeSnmpEventTime(snmpEventTimeString);
System.out.println(dateTime);
输出是:
2020-07-14T04:03:43
链接