Неправильный способ отслеживания даты и времени
Во-первых, я должен сказать, что это использование кол-from- epoch целых чисел для значений даты и времени в различных time zones, а не в UTC действительно, очень плохая идея. Я видел некоторые плохие способы обработки дат, включая изобрести один или два плохих пути. Но это самое худшее. Кто бы это ни думал, должен быть приговорен к году ежедневных чтений ответов StackOverflow с пометками «java», «date» и «Jon Skeet».
Использование count-from-epoch для обработки даты в вашем коде приложения похоже на использование бит-массивов для обработки текста. У нас есть классы/интерфейсы, такие как CharSequence, String, StringBuilder, Printer, Reader и т. Д., Чтобы справиться с сложными деталями текста, символов, кодировки символов, сопоставлений и т. Д. Для упрощения написания приложений. Представьте, что вы пытаетесь отлаживать, устранять неполадки и записывать текстовые данные в виде бит-массивов. Сумасшедший, не так ли? Попытка отладки, устранения неполадок и записи данных даты и времени, так как длинные целые числа тоже сумасшедшие.
Ditto for date-time, где у нас было Joda-Time и теперь есть его преемник java.time (Tutorial), встроенный в Java 8 и более поздние версии.
Во-вторых, неявное изменение отсчета от эпохи в часовой пояс, а затем потерять этот факт еще хуже.
Fix
Путь, чтобы исправить это, чтобы получить, что отсчет от-эпохи в произвольной временной зоне переведенного в местную дату и местное время, когда местный означает wall-clock time глазами людей, чем время зона.
С помощью этого локального дате-времени в ручном режиме мы создаем объект с датой, который имеет назначенный часовой пояс, ZonedDateTime
. A ZonedDateTime в основном Instant
(точка на шкале времени в UTC) плюс ZoneId
(часовой пояс).
Поскольку автор вопроса не предоставил никаких выборочных данных, давайте создадим значение в этом мерзком виде. Получите текущий момент в часовом поясе Чикаго.Получите легитимный счет-от-эпохи, настроившись от nanosecond до millisecond. Затем произвольно добавьте/вычтите смещение от UTC для этого часового пояса.
В этом примере мы используем часовой пояс America/Chicago
. Это смещение для нашего образца, с летним временем, составляет -05:00
. В миллисекундах 5 * 60 * 60 * 1000 = 18 000 000.
// First, create sample data, a count-from-epoch but not in UTC, instead adjusted for the time zone’s offset.
ZoneId zoneId = ZoneId.of("America/Chicago");
// 2015-09-19T12:34:56.000-05:00[America/Chicago]
ZonedDateTime zdtTemp = ZonedDateTime.of(2015 , 9 , 19 , 12 , 34 , 56 , 0 , zoneId);
long millisecondsFromEpoch = zdtTemp.toInstant().toEpochMilli(); // Loosing data, goin from nanosecond
long offsetInMillisecondsForChicagoInDaylightSavingTime = 18_000_000L; // Offset of `-05:00` is in milliseconds, 5 * 60 * 60 * 1,000 = 18,000,000.
long input = (millisecondsFromEpoch - offsetInMillisecondsForChicagoInDaylightSavingTime);
Дамп для консоли.
System.out.println("zoneId : " + zoneId);
System.out.println("zdtTemp : " + zdtTemp);
System.out.println("millisecondsFromEpoch : " + millisecondsFromEpoch);
System.out.println("offsetInMillisecondsForChicagoInDaylightSavingTime : " + offsetInMillisecondsForChicagoInDaylightSavingTime);
System.out.println("input : " + input);
Теперь выполняйте эту работу. Возьмите этот жуткий номер ввода, притворившись, что он находится в UTC, хотя мы знаем, что это не так, чтобы произвести Мгновенное действие. Из Мгновенно получите LocalDateTime. Теперь нажмите LocalDateTime в часовой пояс, чтобы получить то, что мы, наконец, хотим, ZonedDateTime
.
// With example data in hand, proceed to convert to a valid date-time object.
Instant instantPretendingToBeInUtcButNotReally = Instant.ofEpochMilli(input);
LocalDateTime localDateTimeOfPretendInstant = LocalDateTime.ofInstant(instantPretendingToBeInUtcButNotReally , ZoneOffset.UTC);
ZonedDateTime zdt = localDateTimeOfPretendInstant.atZone(zoneId);
Дамп для консоли.
System.out.println("instantPretendingToBeInUtcButNotReally : " + instantPretendingToBeInUtcButNotReally);
System.out.println("localDateTimeOfPretendInstant : " + localDateTimeOfPretendInstant);
System.out.println("zdt : " + zdt);
При запуске.
zoneId : America/Chicago
zdtTemp : 2015-09-19T12:34:56-05:00[America/Chicago]
millisecondsFromEpoch : 1442684096000
offsetInMillisecondsForChicagoInDaylightSavingTime : 18000000
input : 1442666096000
instantPretendingToBeInUtcButNotReally : 2015-09-19T12:34:56Z
localDateTimeOfPretendInstant : 2015-09-19T12:34:56
zdt : 2015-09-19T12:34:56-05:00[America/Chicago]
CAVEAT Я сделал это в спешке. Прокомментируйте или исправьте ошибки.
Кстати, я должен сказать, что эта схема использования подсчета от эпохи в разных часовых поясах, а не в UTC - это идея * очень плохой. Если у вас есть какой-либо контроль над причиной, я настоятельно рекомендую вам исправить эту проблему на своем источнике, а не пытаться улучшить ее. –
Можете ли вы разместить некоторые данные образца? Дайте подсчет-эпоху, ее предполагаемый часовой пояс и ожидаемый результат. –
FYI, нет такой вещи, как «местная эпоха». Эта идея лежит в основе этого ошибочного подхода. –