В чем разница между java.util.Date и Zoneddatetime?
blockquote>
Date
представляет момент в UTC, в то время какZonedDateTime
представляет момент в конкретном часовом поясе.Date
- ужасный класс, изобилующий недостатками дизайна, которые никогда не должны использоваться, в то время какZonedDateTime
- современный класс из пакета java.time , который вы найдете довольно полезно.Java поставляется с двумя очень разными средами для обработки работы с датой и временем: ужасно неуклюжим и неудачным набором унаследованных классов и современным ведущим в отрасли набором классов, найденным в [1180 ] java.time пакет.
Legacy ➙ modern:
java.util.Date
был заменен наjava.time.Instant
- Оба представляют момент в UTC.
java.util.GregorianCalendar
был заменен наjava.time.ZonedDateTime
- Оба представляют момент, наблюдаемый в определенном часовом поясе.
java.util.Date
Класс
Date
представляет момент в UTC. То есть дата, время суток плюс контекст UTC.Внутренне это счет в миллисекундах с эталонной даты первого момента 1970 года в UTC, 1970-01-01T00: 00: 00Z.
Чтобы усложнить ситуацию:
- Существует захват часового пояса при создании, который хранится глубоко внутри, без геттеров или сеттеров. Таким образом, по большей части мы можем игнорировать эту зону, хотя она применима к таким вопросам, как реализация этого класса
equals
.- При вызове
toString
этот класс имеет очень сбивающее с толку поведение динамического применения текущего часового пояса JVM при генерации текста для представления значения этого объекта. Несмотря на благие намерения, эта анти-функция причинила неисчислимые страдания программистам Java, пытающимся научиться работать с датой и временем.В замешательстве? Да, этот класс сбивает с толку, жалкий беспорядок плохих дизайнерских решений. Усугубляется последующим добавлением
java.util.Calendar
& amp;GregorianCalendar
.Все эти проблемные классы даты и времени в комплекте с самой ранней версией Java теперь полностью вытеснены классами java.time .
В частности,
java.util.Date
заменяется наjava.time.Instant
. Оба представляют момент в UTC, считая с эпохи 1970 UTC. НоInstant
имеет более высокое разрешение, наносекунд , а не миллисекунд .Вы можете конвертировать туда-обратно между унаследованным классом
Date
и современным классомInstant
, вызывая новые методы, добавленные к старому классу. Обычно вы избегаете использованияDate
. Но при взаимодействии со старым кодом, который еще не обновлен до java.time , вам может понадобиться конвертировать.
java.time.ZonedDateTime
Современный класс
ZonedDateTime
представляет момент, наблюдаемый во время настенных часов, используемых людьми определенного региона (часового пояса).Итак,
Instant
иZonedDateTime
похожи в том, что они оба представляют момент, конкретную точку на этой временной шкале. Разница в том, чтоZonedDateTime
знает о правилах часового пояса. Таким образом,ZonedDateTime
знает, как учитывать аномалии, такие как переход на летнее время (DST) или другие изменения в хронометраже, требуемые политиками.Вы можете думать об этом как:
blockquote>
ZonedDateTime
= (Instant
+ZoneId
)Мы можем легко настроить из UTC для некоторого часового пояса путем применения часового пояса (
ZoneId
) к объектуInstant
.Instant instant = Instant.now() ; // Capture the current moment as seen in UTC. ZoneId z = ZoneId.of( "Asia/Tokyo" ) ; ZonedDateTime zdt = instant.atZone( z ) ; // Apply a time zone to see the same moment through the wall-clock time in use by the people of a particular region (a time zone).
См. Этот код, запущенный на IdeOne.com . Обратите внимание на другую дату и другое время суток, но в то же время одновременно.
instant.toString (): 2019-02-27T19: 32: 43.366Z
zdt.toString (): 2019-02-28T04: 32: 43.366 + 09: 00 [Азия / Токио]
blockquote>Важная концепция:
Instant
иZonedDateTime
оба представляют один и тот же момент, одну и ту же одновременную точку на временной шкале. Они отличаются по времени настенных часов. Например, если кто-то в Японии звонит кому-то в Исландии ( где UTC используется для своих часов все время), и они оба смотрят на часы, висящие на их соответствующих стенах, они увидят другое время суток и, возможно, даже другую дату в месячном календаре. В тот же момент, разное время настенных часов.Что касается унаследованных классов, то эквивалентом
ZonedDateTime
являетсяGregorianCalendar
, конкретная реализацияjava.util.Calendar
. Действительно, старый классGregorianCalendar
получил новые методы для преобразования в / изZonedDateTime
.ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime(); // Convert from legacy to modern class.
… и…
GregorianCalendar gc = GregorianCalendar.from( zdt ) ; // Convert from modern to legacy class.
Заключение
Таким образом,
Date
эквивалентноInstant
, оба являются моментом в UTC. НоZonedDateTime
отличается от обоих тем, что часовой пояс скорректировал восприятие момента, применяя линзу регулировки времени на часах людей региона.Советы:
- Никогда не используйте
Date
. Когда вручитеDate
, немедленно преобразуйте вInstant
. Затем перейдите к вашей бизнес-логике.- Большая часть работы выполняется в UTC. Отслеживание моментов, отладка, ведение журнала, обмен значениями даты и времени и сохранение в базе данных, как правило, должны выполняться в UTC. Учитесь забывать о своем собственном приходском часовом поясе, когда работаете программистом. Держите вторые часы на вашем столе, настроенные на UTC.
База данных
Вопрос затрагивает работу базы данных. Вот краткое резюме. Поиск переполнения стека для более подробной информации, поскольку это уже было обработано много раз.
Начиная с JDBC 4.2, мы можем напрямую обмениваться объектами java.time с базой данных. Используйте
PreparedStatement::setObject
иResultSet::getObject
. Больше не нужно трогать ужасныеjava.sql.*
классы, такие какjava.sql.Timestamp
.Вы , возможно, сможете обменять
Instant
, но спецификация JDBC этого не требует. Спецификация вместо этого требуетOffsetDateTime
.индексирование.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
И хранение.
myPreparedStatement.setObject( … , odt ) ;
Если у вас под рукой
Instant
, конвертируйте вOffsetDateTime
, используя константуZoneOffset.UTC
.OffsetDateTime odt = Instant.atOffset( ZoneOffset.UTC ) ;
Чтобы просмотреть этот момент через время настенных часов некоторого региона, примените
ZoneId
.ZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Чтобы сохранить
ZonedDateTime
в базе данных, преобразуйте вOffsetDateTime
. Это лишает информацию о часовом поясе (историю прошлых, настоящих и будущих изменений, внесенных в смещение, используемое жителями этого региона по решению их политиков), оставляя дату, время дня и смещение -из UTC (количество часов, минут, секунд).OffsetDateTime odt = zdt.toOffsetDateTime();
Большинство баз данных хранят момент в UTC для столбца стандартного типа SQL
TIMESTAMP WITH TIMESTAMP
. При отправке вашегоOffsetDateTime
в базу данных ваш драйвер JDBC, скорее всего, отрегулирует смещение вOffsetDateTime
до нуля часов-минут-секунд (для самого UTC). Но мне нравится делать это явно. Это облегчает отладку и демонстрирует читателю мое понимание момента, хранящегося в UTC.OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC ) ;
Как насчет этого: grep 11085 / proc / net / unix
. Предполагая, что в строке с интересующим вас индексом присутствует непустой путь, grep
для этого пути в / proc / net / unix
, чтобы найти индекс для на другом конце соединения, затем используйте метод @ffectivejelly для сопоставления другого inode с pid
.
Ключевым моментом здесь является тот факт, что каждый из двух подключенных сокетов будет иметь различный номер inode.
Помогает ли netstat -p
?
С Manpage:
-p,
--program Show the PID and name of the program to which each socket belongs.
Если по какой-то причине вам не повезло с соответствующими опциями lsof и netstat, вы также можете сделать следующее:
find /proc -lname '*11085*' 2> /dev/null
lsof | grep 11085
lsof должен выполняться как root.
Я экспериментировал с lsof в моей системе Linux, и lsof -U
показывает, что все числа в столбце NODE являются уникальными.