У меня есть база данных, в которой хранятся даты и даты и время (как INTEGER и DOUBLE, соответственно) как модифицированные числа дней по юлианскому календарю (MJD). Модифицированные числа дней по юлианскому календарю представляют собой последовательный подсчет дней с полуночи по Гринвичу 17 ноября 1858 года. По определению они всегда отсчитываются в формате UTC, имеют смещение +0:00 от GMT и не учитывают переход на летнее время. Эти свойства упрощают определенные операции с DateTimes, такие как приоритет и арифметика дат.
Недостатком является то, что MJD должны быть перемещены из UTC и делокализованы обратно в UTC до и после использования, особенно для приложений, для которых критически важны границы дня (например, Medicare распознает границу оплачиваемой даты как полночь в -местном-времени).
Рассмотрим следующий статический фабричный метод, целью которого является делокализовать в MJD (в формате UTC) «региональный номер дня» (по сути, MJD, к которому добавлено соответствующее смещение, чтобы он представлял локальный DateTime):
public static MJD ofDayNumberInZone(double regDN, ZoneId zone) {
:
:
}
Кажется интуитивно очевидным, что если у вас есть местная дата и время и вы знаете местный часовой пояс, у вас должна быть вся необходимая информация, чтобы сместить regDN
обратно в UTC (как того требует MJD).
На самом деле эту функцию довольно просто написать, используя предыдущий Java Calendar API. regDN
легко преобразуется в Date
, который используется для установки экземпляра GregorianCalendar. Зная «местный часовой пояс», календарь сообщает значения ZONE_OFFSET и DST_OFFSET, которые затем можно использовать для корректировки номера дня в MJD.
Это моя попытка написать аналогичный алгоритм в Java 8 DateTime API:
public static MJD ofDayNumberInZone(double zonedMJD, ZoneId zone) {
double epochSec = ((zonedMJD - MJD.POSIX_EPOCH_AS_MJD) * 86400.0);
LocalDateTime dt = LocalDateTime
.ofEpochSecond(
(long) epochSec,
(int) (epochSec - Math.floor(epochSec) * 1000000000.0),
---> zone.getRules().getOffset( <Instant> )
);
}
Проблема указана стрелкой. Построение экземпляра LocalDateTime с использованием метода ofEpochSecond, по-видимому, требует, чтобы вы знали смещения заранее, что кажется нелогичным (у меня уже есть местное время и часовой пояс, это смещение, которое я хочу).
Мне не удалось найти простой способ получить смещения от местного времени до UTC с помощью API Java 8. Хотя я мог бы продолжать использовать старый API календаря, новые библиотеки DateTime предлагают неоспоримые преимущества... поэтому я хотел бы попытаться выяснить это. Что мне не хватает?
РЕДАКТИРОВАТЬ: Вот пример использования старого API календаря Java о том, как количество дней и дробных дней в произвольном часовом поясе «дерегионализируется» в UTC. Этот метод принимает двойное значение, которое является «региональным номером дня» и объектом часового пояса. Он использует GregorianCalendar для преобразования параметров в миллисекунды UTC от эпохи:
private static final Object lockCal = new Object();
private static final SimpleDateFormat SDF = new SimpleDateFormat();
private static final GregorianCalendar CAL = new
GregorianCalendar(TimeZone.getTimeZone(HECTOR_ZONE));
:
:
public static MJD ofDayNumberInZone(double rdn, TimeZone tz) {
Date dat = new Date((long) ((rdn - MJD.POSIX_EPOCH_AS_MJD) *
(86400.0 * 1000.0)));
return MJD.ofDateInZone(dat, tz);
}
public static MJD ofDateInZone(Date dat, TimeZone tz) {
long utcMillisFromEpoch;
synchronized(lockCal) {
CAL.setTimeZone(tz);
CAL.setTime(dat);
utcMillisFromEpoch = CAL.getTimeInMillis();
}
return MJD.ofEpochMillisInUTC(utcMillisFromEpoch);
}
public static MJD ofEpochMillisInUTC(long millis)
{ return new MJD((millis / (86400.0 * 1000.0)) + POSIX_EPOCH_AS_MJD); }
Zoned MJD
вUTC MJD
? - person fdsa   schedule 05.08.2015