Почему Timestamp печатает разницу между моделью прогона и моделью отладки в модульном тесте?
java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
//-2209017600000
System.out.println(date.getTime());
java.sql.Timestamp timestamp = new Timestamp(date.getTime());
System.out.println(timestamp);
если непосредственно работает в модульном тесте, результат будет 1900-01-01 00:00:00.0
если запустить с отладкой в модульном тесте, результат будет 1970-01-01 07:30:00.0
Как это вывести 1900-01-01 00:00:00.0
? Где это хранится?
Почему не выводится 1970-01-01 00:00:00.0
? потому что я видел комментарий конструктора Timestamp говорит, что миллисекунды с 1 января 1970 года, 00:00:00 по Гринвичу. Отрицательное число - это количество миллисекунд до 1 января 1970 года, 00:00:00 по Гринвичу.
1 ответ
ТЛ; др
Избегайте ужасных старых классов даты и времени. Используйте java.time. Пуф, все странное поведение, которое ты видишь, ушло, и твой вопрос спорен.
LocalDate // A class to represent a date-only value, without time-of-day, without time zone. Replaces `java.sql.Date` which only pretends to be date-only but actually has both a time-of-day and a time zone.
.parse( "1900-01-01" ) // Standard ISO 8601 formatted strings are parsed directly by the *java.time* classes.
.atStartOfDay( // Let java.time determine the first moment of a day.
ZoneId.of( "Pacific/Auckland" )
) // Returns a `ZonedDateTime` object.
.toString() // Generates a `String` with text in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.
1900-01-01T00: 00 + 11: 30 [Pacific / Auckland]
Вы мучаете себя этими Вопросами о старых классах даты и времени. Sun, Oracle и сообщество JCP отказались от этих занятий много лет назад, приняв JSR 310. Я предлагаю вам сделать то же самое.
Никогда не используйте java.sql.Date
Этот класс является частью ужасных старых классов даты и времени, которые были вытеснены несколько лет назад классами java.time. это java.sql.Date
особенно плохо продуман. Расширяется java.util.Date
в то время как документация говорит нам игнорировать факт этого наследования. Как подкласс, он претендует на значение только для даты, но на самом деле имеет время суток, унаследованное от другого Date
который, в свою очередь, неправильно назван, имея дату и время суток. Кроме того, часовой пояс скрывается глубоко внутри этих классов, хотя недоступен без какого-либо метода получения или установки. Смешение? Да, ужасный беспорядок. Никогда не используйте java.sql.Date
,
Вместо этого используйте java.time.LocalDate
,
LocalDate ld = LocalDate.parse( "1900-01-01" ) ;
ld.toString(): 1900-01-01
Никогда не используйте java.sql.Timestamp
Как с java.sql.Date
, java.sql.Timestamp
класс был заменен несколько лет назад. использование java.time.Instant
, Если передал Timestamp
, немедленно конвертировать, используя новые методы конвертации, добавленные к старым классам.
Если вы хотите первый момент дня для конкретной даты, пусть LocalDate
определить это. Первый момент не всегда 00:00:00, поэтому никогда не предполагайте это. Укажите часовой пояс региона, в котором люди используют часы, которые вам нужны.
Укажите правильное название часового пояса в формате continent/region
, такие как America/Montreal
, Africa/Casablanca
, или же Pacific/Auckland
, Никогда не используйте 3-4 буквенное сокращение, такое как EST
или же IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
Чтобы увидеть тот же момент в UTC, извлеките Instant
, Instant
класс представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).
Instant instant = zdt.toInstant() ;
Если вы хотели первый момент дня в UTC, используйте OffsetDateTime
,
OffsetDateTime odt = ld.atOffset( ZoneOffset.UTC ) ;
преобразование
Если вам необходимо взаимодействовать со старым кодом, который еще не обновлен до классов java.time, вы можете конвертировать туда и обратно. Вызовите новые методы, добавленные к старым классам.
java.sql.Timestamp ts = Timestamp.from( instant ) ;
…а также…
Instant instant = ts.toInstant() ;
То же самое для свидания.
java.sql.Date d = java.sql.Date.valueOf( ld ) ;
…а также…
LocalDate ld = d.toLocalDate() ;
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
Где взять классы java.time?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11 и более поздние версии - часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.