Я даю современный ответ, используя java.time, современный API даты и времени Java.
Шестнадцатеричная строка состоит из следующих полей:
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
. Поэтому я предполагаю шестнадцатеричную строку без пробелов между байтами. Как из ответа Роберта Коха, так и из этого повторяющегося вопроса кажется, что не все 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
Ссылки
person
Ole V.V.
schedule
14.07.2020