timestamp
- это количество миллисекунд, прошедшее с 1 января 1970 года в 00:00 UT C. timeZone
- это смещение в миллисекундах от UT C , Это может быть положительным, отрицательным или нулевым. Однако, чтобы формула работала, ее знак должен быть обратным: смещение +01:00
должно быть задано как минус 3 600 000 миллисекунд. Когда я добавляю смещение, я получаю другой момент времени, когда дата и время дня в UT C совпадают с исходной датой и временем дня в этом смещении UT C. - Деление на 24 * 60 * 60 * 1000 преобразуется из миллисекунд в дни, начиная с эпохи. Любая часть дня, то есть любое время суток, отбрасывается.
- Умножение на 24 * 60 * 60 * 1000 переводит обратно из дней в миллисекунды. Поскольку время суток было отброшено, у нас теперь есть время в 00:00 UT C в этот день.
Так что это способ конвертации из некоторого момента времени в какое-то время UT C смещение только до даты, представленной в UT C.
Это не тот код, который вы хотели бы иметь в своей программе. Вы должны оставить такие преобразования для проверенных библиотечных методов. Однако это может быть код, который можно найти в такой проверенной и проверенной библиотеке.
Редактировать: Почему я считаю, что знак смещения был полностью изменен? Не может ли быть обратное преобразование из UT C в местное? Имя переменной localTimeDay
, кажется, подсказывает это? Деление и умножение работает только в UT C. Поскольку эпоха в 00:00 UT C, формула обязательно дает вам начало дня в UT C, она не может дать вам начало дня с любым ненулевым смещением. Поэтому я считаю, что преобразование должно быть локальным в UT C.
Как это сделать в вашем коде
Вот хороший способ сделать то же преобразование, используя java .time, современный Java API даты и времени
// The point in time given in UTC
Instant time = Instant.parse("2020-04-23T05:16:45Z");
// The UTC offset, +02:00
ZoneOffset offset = ZoneOffset.ofHours(2);
ZonedDateTime startOfDayInUtc = time.atOffset(offset)
.toLocalDate()
.atStartOfDay(ZoneOffset.UTC);
System.out.println(startOfDayInUtc);
long epochMillis = startOfDayInUtc.toInstant().toEpochMilli();
System.out.println(epochMillis);
Вывод:
2020-04-23T00:00Z
1587600000000
Мы можем проверить, что он дает тот же результат, что и ваша строка кода:
long timeStamp = time.toEpochMilli();
// Reverse sign of offset
long timeZone = -Duration.ofSeconds(offset.getTotalSeconds()).toMillis();
long localTimeDay = (timeStamp + timeZone) / (24 * 60 * 60 * 1000) * (24 * 60 * 60 * 1000);
System.out.println(localTimeDay);
System.out.println("Agree? " + (localTimeDay == epochMillis));
1587600000000
Agree? true
Редактировать: вы спросили в комментарии:
У меня все еще есть это сомнение: существует фиксированное количество миллис, прошедших с тех пор 1 января 1970 года, поэтому каждая страна должна получить одинаковый номер. Означает ли localTimeDate «дату для моей страны» или для страны, откуда поступили эти данные? Например: Страна-А, Страна-Б; они увидят ту же миллис со времен. Предположим, что обработка данных происходит в стране-A, а источником данных является страна-B. Поэтому, когда мы говорим «localTimeDate», это относится к стране-A или стране-B.
Это будет работать для обеих стран. Все зависит от значения timeZone
, которое входит в формулу. Если это смещение UT C для страны A (знак обратный), преобразование будет происходить из времени страны A в дату UT C. Если это смещение страны B, конвертация будет из страны B времени. И вы полностью правы, вы получите две разные даты, если в странах A и B это будет не одна и та же дата, что может быть легко.