тл; д-р
Чи є спосіб, або в коді, або з аргументами JVM, змінити поточний час, представлений через System.currentTimeMillis, окрім ручного зміни системного годинника на хост-машині?
Так.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock
У java.time
Ми маємо нове рішення проблеми заміни підключеного годинника, щоб полегшити тестування з підробленими значеннями дати та часу. Пакет java.time в Java 8 включає абстрактний клас java.time.Clock
із чіткою метою:
щоб дозволити підключати альтернативні годинники як і коли потрібно
Ви можете підключити власну реалізацію Clock
, хоча ви, ймовірно, можете знайти такий, який вже зроблений для задоволення ваших потреб. Для вашої зручності java.time включає статичні методи для отримання спеціальних реалізацій. Ці альтернативні реалізації можуть бути цінними під час тестування.
Змінена каденція
Різні tick…
методи виробляють годинники, які збільшують поточний момент з різною каденцією.
За замовчуванням Clock
повідомляється про час, оновлений так само часто, як мілісекунди в Java 8, а в Java 9 так само добре, як наносекунди (залежно від обладнання). Ви можете попросити повідомляти про справжній поточний момент з різною детальністю.
Неправдиві годинники
Деякі годинники можуть лежати, створюючи результат, інший, ніж апаратний годинник хост-операційної системи.
fixed
- Повідомляє про єдиний незмінний (не збільшується) момент як поточний момент.
offset
- Звітує про поточний момент, але зміщений Duration
аргументом, що передається .
Наприклад, замкніть у першу мить самого раннього Різдва цього року. Іншими словами, коли Санта та його оленя роблять свою першу зупинку . Найраніший часовий пояс в даний час , як видається, Pacific/Kiritimati
в +14:00
.
LocalDate ld = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate xmasThisYear = MonthDay.of( Month.DECEMBER , 25 ).atYear( ld.getYear() );
ZoneId earliestXmasZone = ZoneId.of( "Pacific/Kiritimati" ) ;
ZonedDateTime zdtEarliestXmasThisYear = xmasThisYear.atStartOfDay( earliestXmasZone );
Instant instantEarliestXmasThisYear = zdtEarliestXmasThisYear.toInstant();
Clock clockEarliestXmasThisYear = Clock.fixed( instantEarliestXmasThisYear , earliestXmasZone );
Використовуйте цей спеціальний фіксований годинник, щоб завжди повертати той самий момент. Ми отримуємо перший момент Різдва в Кірітіматі , з UTC, який показує годинник на чотирнадцять годин раніше, 10 ранку на попередню дату 24 грудня.
Instant instant = Instant.now( clockEarliestXmasThisYear );
ZonedDateTime zdt = ZonedDateTime.now( clockEarliestXmasThisYear );
instant.toString (): 2016-12-24T10: 00: 00Z
zdt.toString (): 2016-12-25T00: 00 + 14: 00 [Тихий океан / Кірітіматі]
Дивіться прямий код на IdeOne.com .
Справжній час, різний часовий пояс
Ви можете керувати, який часовий пояс призначений Clock
реалізацією. Це може бути корисно в деяких тестуваннях. Але я не рекомендую це у виробничому коді, де завжди слід чітко вказувати необов'язкові ZoneId
чи ZoneOffset
аргументи.
Ви можете вказати, що UTC є зоною за замовчуванням.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
Ви можете вказати будь-який конкретний часовий пояс. Вкажіть правильний час ім'я зони в форматі continent/region
, наприклад America/Montreal
, Africa/Casablanca
або Pacific/Auckland
. Ніколи не використовуйте абревіатуру з 3–4 літер, наприклад, EST
або IST
як вони не є справжніми часовими поясами, не стандартизовані та навіть не унікальні (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Ви можете вказати, що поточний часовий пояс JVM за замовчуванням повинен бути типовим для певного Clock
об'єкта.
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Запустіть цей код для порівняння. Зауважте, що всі вони повідомляють один і той же момент, ту саму точку на шкалі часу. Вони відрізняються лише настінним годинником ; іншими словами, три способи сказати одне і те ж, три способи відображення одного і того ж моменту.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles
була поточною зоною за замовчуванням JVM на комп’ютері, на якому працює цей код.
zdtClockSystemUTC.toString (): 2016-12-31T20: 52: 39.688Z
zdtClockSystem.toString (): 2016-12-31T15: 52: 39.750-05: 00 [Америка / Монреаль]
zdtClockSystemDefaultZone.toString (): 2016-12-31T12: 52: 39.762-08: 00 [America / Los_Angeles]
Instant
Клас завжди в UTC за визначенням. Отже, ці три зони, пов'язані із зоною, Clock
мають абсолютно однаковий ефект.
Instant instantClockSystemUTC = Instant.now ( Clock.systemUTC () );
Instant instantClockSystem = Instant.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Instant instantClockSystemDefaultZone = Instant.now ( Clock.systemDefaultZone () );
instantClockSystemUTC.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystem.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystemDefaultZone.toString (): 2016-12-31T20: 52: 39.763Z
Годинник за замовчуванням
Реалізація, яка використовується за замовчуванням для, Instant.now
- це повернена Clock.systemUTC()
. Це реалізація, яка використовується, коли ви не вказуєте a Clock
. Переконайтесь у попередньому випуску вихідного коду Java 9 дляInstant.now
.
public static Instant now() {
return Clock.systemUTC().instant();
}
Типовим Clock
для OffsetDateTime.now
і ZonedDateTime.now
є Clock.systemDefaultZone()
. Див. Вихідний код .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Поведінка реалізацій за замовчуванням змінилася між Java 8 та Java 9. У Java 8 поточний момент фіксується з роздільною здатністю лише в мілісекундах, незважаючи на можливість класів зберігати роздільну здатність наносекунд . Java 9 пропонує нову реалізацію, здатну фіксувати поточний момент з роздільною здатністю наносекунд - залежно, звичайно, від можливостей годинника апаратного забезпечення вашого комп'ютера.
Про java.time
Java.time каркас вбудований в Java 8 і пізніших версій. Ці класи витісняти неприємні старі застарілі класи дати і часу , такі як java.util.Date
, Calendar
, і SimpleDateFormat
.
Щоб дізнатися більше, дивіться навчальний посібник Oracle . І шукайте переповнення стека за багатьма прикладами та поясненнями. Специфікація - JSR 310 .
Проект Joda-Time , який зараз знаходиться в режимі обслуговування , радить перейти до класів java.time .
Ви можете обмінюватися об'єктами java.time безпосередньо зі своєю базою даних. Використовуйте драйвер JDBC, сумісний з JDBC 4.2 або пізнішої версії. Немає потреби в струнах, немає потреби в java.sql.*
заняттях. Hibernate 5 & JPA 2.2 підтримують java.time .
Де отримати класи java.time?