diff --git a/src/main/java/emissary/util/TimeUtil.java b/src/main/java/emissary/util/TimeUtil.java index 7cc2c34415..351096ea31 100755 --- a/src/main/java/emissary/util/TimeUtil.java +++ b/src/main/java/emissary/util/TimeUtil.java @@ -1,13 +1,17 @@ package emissary.util; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.time.DateTimeException; import java.time.Instant; +import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAccessor; import java.time.zone.ZoneRulesException; import java.util.Date; @@ -20,7 +24,12 @@ public class TimeUtil { private static final DateTimeFormatter DATE_ISO_8601 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(GMT); private static final DateTimeFormatter DATE_FULL_ISO_8601 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX").withZone(GMT); private static final DateTimeFormatter DATE_ORDINAL = DateTimeFormatter.ofPattern("yyyyDDD").withZone(GMT); + private static final DateTimeFormatter DATE_ISO_8601_SSS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); private static final String ISO_8601_TIME_DATE_STRING = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + private static final int HEX_PREFIX_LEN = "0x".length(); + private static final int HEX_RADIX = 16; + private static final LocalDateTime STARTING_DATE = LocalDateTime.parse("1900-01-01 00:00:00.000", DATE_ISO_8601_SSS); + private static final Logger logger = LoggerFactory.getLogger(TimeUtil.class); /** * Get the application configured timezone @@ -232,6 +241,35 @@ public static ZonedDateTime getZonedDateFromISO8601(@Nullable final String dateS return dateString == null ? null : ZonedDateTime.parse(dateString, DATE_ISO_8601); } + /** + * Parses hex date string into formatted string ("yyyy-MM-dd HH:mm:ss.SSS") + * + * @param hexDate hex string representation of the date + * @return converted time in string format yyyy-MM-dd HH:mm:ss.SSS + * @throws DateTimeParseException if could not parse date + * + */ + public static String convertHexDate(String hexDate) { + String hexNumber = hexDate.substring(HEX_PREFIX_LEN); + String dateHex = hexNumber.substring(0, 8); + String timeHex = hexNumber.substring(8, 16); + + long daysToAdd = Long.parseLong(dateHex, HEX_RADIX); + long millisToAdd = Math.round(Long.parseLong(timeHex, HEX_RADIX) * 10 / 3.0); + + LocalDateTime ldt; + + try { + ldt = STARTING_DATE.plusDays(daysToAdd); + ldt = ldt.plus(millisToAdd, ChronoUnit.MILLIS); + } catch (DateTimeParseException ex) { + logger.debug("Could not parse date", ex); + throw ex; + } + + return ldt.format(DATE_ISO_8601_SSS); + } + public static String getISO8601DateFormatString() { return ISO_8601_TIME_DATE_STRING; } diff --git a/src/test/java/emissary/util/TimeUtilTest.java b/src/test/java/emissary/util/TimeUtilTest.java index 2fed9461be..75ae9ef33b 100644 --- a/src/test/java/emissary/util/TimeUtilTest.java +++ b/src/test/java/emissary/util/TimeUtilTest.java @@ -156,4 +156,12 @@ void testDateAsFullIOS8601() { assertTrue(time.contains("T"), "Full ISO8601 must have a 'T'"); assertTrue(time.contains("Z"), "Full ISO8601 must have a 'Z'"); } + + @Test + void testConvertHexDate() { + String cellContents = "0x00009FF700F77536"; + String cellContents2 = "0x0000A07800E93033"; + assertEquals("2012-02-14 15:00:57.993", TimeUtil.convertHexDate(cellContents), "convertHexDate did not match"); + assertEquals("2012-06-22 14:09:00.757", TimeUtil.convertHexDate(cellContents2), "convertHexDate did not match"); + } }